blob: 57072023738ba145df0ea0446481fd512ef8dc4b [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 Lamaa8e15a2014-02-11 23:30:06 -080023 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
24 * All Rights Reserved.
25 * Qualcomm Atheros Confidential and Proprietary.
Kiet Lam842dad02014-02-18 18:44:02 -080026 *
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080027 */
Kiet Lam842dad02014-02-18 18:44:02 -080028
29
Jeff Johnson295189b2012-06-20 16:38:30 -070030/*========================================================================
31
32 \file wlan_hdd_main.c
33
34 \brief WLAN Host Device Driver implementation
35
36 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
37
38 Qualcomm Confidential and Proprietary.
39
40 ========================================================================*/
41
42/**=========================================================================
43
44 EDIT HISTORY FOR FILE
45
46
47 This section contains comments describing changes made to the module.
48 Notice that changes are listed in reverse chronological order.
49
50
51 $Header:$ $DateTime: $ $Author: $
52
53
54 when who what, where, why
55 -------- --- --------------------------------------------------------
56 04/5/09 Shailender Created module.
57 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
58 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
59 ==========================================================================*/
60
61/*--------------------------------------------------------------------------
62 Include Files
63 ------------------------------------------------------------------------*/
64//#include <wlan_qct_driver.h>
65#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070066#include <vos_api.h>
67#include <vos_sched.h>
68#include <vos_power.h>
69#include <linux/etherdevice.h>
70#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#ifdef ANI_BUS_TYPE_PLATFORM
72#include <linux/wcnss_wlan.h>
73#endif //ANI_BUS_TYPE_PLATFORM
74#ifdef ANI_BUS_TYPE_PCI
75#include "wcnss_wlan.h"
76#endif /* ANI_BUS_TYPE_PCI */
77#include <wlan_hdd_tx_rx.h>
78#include <palTimer.h>
79#include <wniApi.h>
80#include <wlan_nlink_srv.h>
81#include <wlan_btc_svc.h>
82#include <wlan_hdd_cfg.h>
83#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053084#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070085#include <wlan_hdd_wowl.h>
86#include <wlan_hdd_misc.h>
87#include <wlan_hdd_wext.h>
88#ifdef WLAN_BTAMP_FEATURE
89#include <bap_hdd_main.h>
90#include <bapInternal.h>
91#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053092#include "wlan_hdd_trace.h"
93#include "vos_types.h"
94#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070095#include <linux/wireless.h>
96#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053097#include <linux/inetdevice.h>
98#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099#include "wlan_hdd_cfg80211.h"
100#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700101#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700102int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700103#include "sapApi.h"
104#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700105#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
107#include <soc/qcom/subsystem_restart.h>
108#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700109#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530110#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include <wlan_hdd_hostapd.h>
112#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#include "wlan_hdd_dev_pwr.h"
115#ifdef WLAN_BTAMP_FEATURE
116#include "bap_hdd_misc.h"
117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800120#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530121#ifdef FEATURE_WLAN_TDLS
122#include "wlan_hdd_tdls.h"
123#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700124#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700125
126#ifdef MODULE
127#define WLAN_MODULE_NAME module_name(THIS_MODULE)
128#else
129#define WLAN_MODULE_NAME "wlan"
130#endif
131
132#ifdef TIMER_MANAGER
133#define TIMER_MANAGER_STR " +TIMER_MANAGER"
134#else
135#define TIMER_MANAGER_STR ""
136#endif
137
138#ifdef MEMORY_DEBUG
139#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
140#else
141#define MEMORY_DEBUG_STR ""
142#endif
143
144/* the Android framework expects this param even though we don't use it */
145#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700146static char fwpath_buffer[BUF_LEN];
147static struct kparam_string fwpath = {
148 .string = fwpath_buffer,
149 .maxlen = BUF_LEN,
150};
Arif Hussain66559122013-11-21 10:11:40 -0800151
152static char *country_code;
153static int enable_11d = -1;
154static int enable_dfs_chan_scan = -1;
155
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700157static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700159
Jeff Johnsone7245742012-09-05 17:12:55 -0700160/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800161 * spinlock for synchronizing asynchronous request/response
162 * (full description of use in wlan_hdd_main.h)
163 */
164DEFINE_SPINLOCK(hdd_context_lock);
165
166/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700167 * The rate at which the driver sends RESTART event to supplicant
168 * once the function 'vos_wlanRestart()' is called
169 *
170 */
171#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
172#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700173
174/*
175 * Size of Driver command strings from upper layer
176 */
177#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
178#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
179
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800180#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700181#define TID_MIN_VALUE 0
182#define TID_MAX_VALUE 15
183static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
184 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800185static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
186 tCsrEseBeaconReq *pEseBcnReq);
187#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700188
Atul Mittal1d722422014-03-19 11:15:07 +0530189/*
190 * Maximum buffer size used for returning the data back to user space
191 */
192#define WLAN_MAX_BUF_SIZE 1024
193#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700194/*
195 * Driver miracast parameters 0-Disabled
196 * 1-Source, 2-Sink
197 */
198#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
199#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
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);
238
Jeff Johnson295189b2012-06-20 16:38:30 -0700239static int hdd_netdev_notifier_call(struct notifier_block * nb,
240 unsigned long state,
241 void *ndev)
242{
243 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700244 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700245 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700246#ifdef WLAN_BTAMP_FEATURE
247 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700248#endif
249
250 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700251 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700252 (strncmp(dev->name, "p2p", 3)))
253 return NOTIFY_DONE;
254
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700256 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700257
Jeff Johnson27cee452013-03-27 11:10:24 -0700258 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 VOS_ASSERT(0);
262 return NOTIFY_DONE;
263 }
264
Jeff Johnson27cee452013-03-27 11:10:24 -0700265 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
266 if (NULL == pHddCtx)
267 {
268 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
269 VOS_ASSERT(0);
270 return NOTIFY_DONE;
271 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800272 if (pHddCtx->isLogpInProgress)
273 return NOTIFY_DONE;
274
Jeff Johnson27cee452013-03-27 11:10:24 -0700275
276 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
277 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278
279 switch (state) {
280 case NETDEV_REGISTER:
281 break;
282
283 case NETDEV_UNREGISTER:
284 break;
285
286 case NETDEV_UP:
287 break;
288
289 case NETDEV_DOWN:
290 break;
291
292 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700293 if(TRUE == pAdapter->isLinkUpSvcNeeded)
294 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 break;
296
297 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700298 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700299 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530300 long result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800301 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Srinivas, Dasari138af4f2014-02-07 11:13:45 +0530302 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId,
303 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800305 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530307 if (result <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 {
309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530310 "%s: Timeout occurred while waiting for abortscan %ld",
311 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 }
313 }
314 else
315 {
316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700317 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700318 }
319#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 status = WLANBAP_StopAmp();
322 if(VOS_STATUS_SUCCESS != status )
323 {
324 pHddCtx->isAmpAllowed = VOS_TRUE;
325 hddLog(VOS_TRACE_LEVEL_FATAL,
326 "%s: Failed to stop AMP", __func__);
327 }
328 else
329 {
330 //a state m/c implementation in PAL is TBD to avoid this delay
331 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700332 if ( pHddCtx->isAmpAllowed )
333 {
334 WLANBAP_DeregisterFromHCI();
335 pHddCtx->isAmpAllowed = VOS_FALSE;
336 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 }
338#endif //WLAN_BTAMP_FEATURE
339 break;
340
341 default:
342 break;
343 }
344
345 return NOTIFY_DONE;
346}
347
348struct notifier_block hdd_netdev_notifier = {
349 .notifier_call = hdd_netdev_notifier_call,
350};
351
352/*---------------------------------------------------------------------------
353 * Function definitions
354 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700355void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
356void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700357//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700358static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700359#ifndef MODULE
360/* current con_mode - used only for statically linked driver
361 * con_mode is changed by userspace to indicate a mode change which will
362 * result in calling the module exit and init functions. The module
363 * exit function will clean up based on the value of con_mode prior to it
364 * being changed by userspace. So curr_con_mode records the current con_mode
365 * for exit when con_mode becomes the next mode for init
366 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700367static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700368#endif
369
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800370/**---------------------------------------------------------------------------
371
372 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = VOS_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 vos_trace_setValue(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
410
411
Jeff Johnson295189b2012-06-20 16:38:30 -0700412/**---------------------------------------------------------------------------
413
414 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
415
416 Called immediately after the cfg.ini is read in order to configure
417 the desired trace levels in the WDI.
418
419 \param - moduleId - module whose trace level is being configured
420 \param - bitmask - bitmask of log levels to be enabled
421
422 \return - void
423
424 --------------------------------------------------------------------------*/
425static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
426{
427 wpt_tracelevel level;
428
429 /* if the bitmask is the default value, then a bitmask was not
430 specified in cfg.ini, so leave the logging level alone (it
431 will remain at the "compiled in" default value) */
432 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
433 {
434 return;
435 }
436
437 /* a mask was specified. start by disabling all logging */
438 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
439
440 /* now cycle through the bitmask until all "set" bits are serviced */
441 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
442 while (0 != bitmask)
443 {
444 if (bitmask & 1)
445 {
446 wpalTraceSetLevel(moduleId, level, 1);
447 }
448 level++;
449 bitmask >>= 1;
450 }
451}
Jeff Johnson295189b2012-06-20 16:38:30 -0700452
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530453/*
454 * FUNCTION: wlan_hdd_validate_context
455 * This function is used to check the HDD context
456 */
457int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
458{
459 ENTER();
460
461 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
462 {
463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
464 "%s: HDD context is Null", __func__);
465 return -ENODEV;
466 }
467
468 if (pHddCtx->isLogpInProgress)
469 {
470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
471 "%s: LOGP in Progress. Ignore!!!", __func__);
472 return -EAGAIN;
473 }
474
Mihir Shete18156292014-03-11 15:38:30 +0530475 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530476 {
477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
478 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
479 return -EAGAIN;
480 }
481 return 0;
482}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700483#ifdef CONFIG_ENABLE_LINUX_REG
484void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
485{
486 hdd_adapter_t *pAdapter = NULL;
487 hdd_station_ctx_t *pHddStaCtx = NULL;
488 eCsrPhyMode phyMode;
489 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530490
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700491 if (NULL == pHddCtx)
492 {
493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
494 "HDD Context is null !!");
495 return ;
496 }
497
498 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
499 if (NULL == pAdapter)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "pAdapter is null !!");
503 return ;
504 }
505
506 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
507 if (NULL == pHddStaCtx)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "pHddStaCtx is null !!");
511 return ;
512 }
513
514 cfg_param = pHddCtx->cfg_ini;
515 if (NULL == cfg_param)
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
518 "cfg_params not available !!");
519 return ;
520 }
521
522 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
523
524 if (!pHddCtx->isVHT80Allowed)
525 {
526 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
527 (eCSR_DOT11_MODE_11ac == phyMode) ||
528 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
529 {
530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
531 "Setting phymode to 11n!!");
532 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
533 }
534 }
535 else
536 {
537 /*New country Supports 11ac as well resetting value back from .ini*/
538 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
539 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
540 return ;
541 }
542
543 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
544 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
545 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
546 {
547 VOS_STATUS vosStatus;
548
549 // need to issue a disconnect to CSR.
550 INIT_COMPLETION(pAdapter->disconnect_comp_var);
551 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
552 pAdapter->sessionId,
553 eCSR_DISCONNECT_REASON_UNSPECIFIED );
554
555 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530556 {
557 long ret;
558
559 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700560 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530561 if (0 >= ret)
562 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
563 ret);
564 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700565
566 }
567}
568#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530569void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
570{
571 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
572 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
573 hdd_config_t *cfg_param;
574 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530575 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530576
577 if (NULL == pHddCtx)
578 {
579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
580 "HDD Context is null !!");
581 return ;
582 }
583
584 cfg_param = pHddCtx->cfg_ini;
585
586 if (NULL == cfg_param)
587 {
588 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
589 "cfg_params not available !!");
590 return ;
591 }
592
593 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
594
595 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
596 {
597 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
598 (eCSR_DOT11_MODE_11ac == phyMode) ||
599 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
600 {
601 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
602 "Setting phymode to 11n!!");
603 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
604 }
605 }
606 else
607 {
608 /*New country Supports 11ac as well resetting value back from .ini*/
609 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
610 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
611 return ;
612 }
613
614 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
615 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
616 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
617 {
618 VOS_STATUS vosStatus;
619
620 // need to issue a disconnect to CSR.
621 INIT_COMPLETION(pAdapter->disconnect_comp_var);
622 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
623 pAdapter->sessionId,
624 eCSR_DISCONNECT_REASON_UNSPECIFIED );
625
626 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530627 {
628 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530629 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530630 if (ret <= 0)
631 {
632 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
633 "wait on disconnect_comp_var is failed %ld", ret);
634 }
635 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530636
637 }
638}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700639#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530640
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700641void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
642{
643 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
644 hdd_config_t *cfg_param;
645
646 if (NULL == pHddCtx)
647 {
648 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
649 "HDD Context is null !!");
650 return ;
651 }
652
653 cfg_param = pHddCtx->cfg_ini;
654
655 if (NULL == cfg_param)
656 {
657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
658 "cfg_params not available !!");
659 return ;
660 }
661
662 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
663 {
664 /*New country doesn't support DFS */
665 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
666 }
667 else
668 {
669 /*New country Supports DFS as well resetting value back from .ini*/
670 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
671 }
672
673}
674
Rajeev79dbe4c2013-10-05 11:03:42 +0530675#ifdef FEATURE_WLAN_BATCH_SCAN
676
677/**---------------------------------------------------------------------------
678
679 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
680 input string
681
682 This function extracts assigned integer from string in below format:
683 "STRING=10" : extracts integer 10 from this string
684
685 \param - pInPtr Pointer to input string
686 \param - base Base for string to int conversion(10 for decimal 16 for hex)
687 \param - pOutPtr Pointer to variable in which extracted integer needs to be
688 assigned
689 \param - pLastArg to tell whether it is last arguement in input string or
690 not
691
692 \return - NULL for failure cases
693 pointer to next arguement in input string for success cases
694 --------------------------------------------------------------------------*/
695static tANI_U8 *
696hdd_extract_assigned_int_from_str
697(
698 tANI_U8 *pInPtr,
699 tANI_U8 base,
700 tANI_U32 *pOutPtr,
701 tANI_U8 *pLastArg
702)
703{
704 int tempInt;
705 int v = 0;
706 char buf[32];
707 int val = 0;
708 *pLastArg = FALSE;
709
710 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
711 if (NULL == pInPtr)
712 {
713 return NULL;
714 }
715
716 pInPtr++;
717
718 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
719
720 val = sscanf(pInPtr, "%32s ", buf);
721 if (val < 0 && val > strlen(pInPtr))
722 {
723 return NULL;
724 }
725 pInPtr += val;
726 v = kstrtos32(buf, base, &tempInt);
727 if (v < 0)
728 {
729 return NULL;
730 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800731 if (tempInt < 0)
732 {
733 tempInt = 0;
734 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530735 *pOutPtr = tempInt;
736
737 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
738 if (NULL == pInPtr)
739 {
740 *pLastArg = TRUE;
741 return NULL;
742 }
743 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
744
745 return pInPtr;
746}
747
748/**---------------------------------------------------------------------------
749
750 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
751 input string
752
753 This function extracts assigned character from string in below format:
754 "STRING=A" : extracts char 'A' from this string
755
756 \param - pInPtr Pointer to input string
757 \param - pOutPtr Pointer to variable in which extracted char needs to be
758 assigned
759 \param - pLastArg to tell whether it is last arguement in input string or
760 not
761
762 \return - NULL for failure cases
763 pointer to next arguement in input string for success cases
764 --------------------------------------------------------------------------*/
765static tANI_U8 *
766hdd_extract_assigned_char_from_str
767(
768 tANI_U8 *pInPtr,
769 tANI_U8 *pOutPtr,
770 tANI_U8 *pLastArg
771)
772{
773 *pLastArg = FALSE;
774
775 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
776 if (NULL == pInPtr)
777 {
778 return NULL;
779 }
780
781 pInPtr++;
782
783 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
784
785 *pOutPtr = *pInPtr;
786
787 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
788 if (NULL == pInPtr)
789 {
790 *pLastArg = TRUE;
791 return NULL;
792 }
793 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
794
795 return pInPtr;
796}
797
798
799/**---------------------------------------------------------------------------
800
801 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
802
803 This function parses set batch scan command in below format:
804 WLS_BATCHING_SET <space> followed by below arguements
805 "SCANFREQ=XX" : Optional defaults to 30 sec
806 "MSCAN=XX" : Required number of scans to attempt to batch
807 "BESTN=XX" : Best Network (RSSI) defaults to 16
808 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
809 A. implies only 5 GHz , B. implies only 2.4GHz
810 "RTT=X" : optional defaults to 0
811 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
812 error
813
814 For example input commands:
815 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
816 translated into set batch scan with following parameters:
817 a) Frequence 60 seconds
818 b) Batch 10 scans together
819 c) Best RSSI to be 20
820 d) 5GHz band only
821 e) RTT is equal to 0
822
823 \param - pValue Pointer to input channel list
824 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
825
826 \return - 0 for success non-zero for failure
827
828 --------------------------------------------------------------------------*/
829static int
830hdd_parse_set_batchscan_command
831(
832 tANI_U8 *pValue,
833 tSirSetBatchScanReq *pHddSetBatchScanReq
834)
835{
836 tANI_U8 *inPtr = pValue;
837 tANI_U8 val = 0;
838 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800839 tANI_U32 nScanFreq;
840 tANI_U32 nMscan;
841 tANI_U32 nBestN;
842 tANI_U8 ucRfBand;
843 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800844 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530845
846 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800847 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
848 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
849 nRtt = 0;
850 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530851
852 /*go to space after WLS_BATCHING_SET command*/
853 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
854 /*no argument after the command*/
855 if (NULL == inPtr)
856 {
857 return -EINVAL;
858 }
859
860 /*no space after the command*/
861 else if (SPACE_ASCII_VALUE != *inPtr)
862 {
863 return -EINVAL;
864 }
865
866 /*removing empty spaces*/
867 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
868
869 /*no argument followed by spaces*/
870 if ('\0' == *inPtr)
871 {
872 return -EINVAL;
873 }
874
875 /*check and parse SCANFREQ*/
876 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
877 {
878 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800879 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800880
Rajeev Kumarc933d982013-11-18 20:04:20 -0800881 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800882 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800883 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800884 }
885
Rajeev79dbe4c2013-10-05 11:03:42 +0530886 if ( (NULL == inPtr) || (TRUE == lastArg))
887 {
888 return -EINVAL;
889 }
890 }
891
892 /*check and parse MSCAN*/
893 if ((strncmp(inPtr, "MSCAN", 5) == 0))
894 {
895 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800896 &nMscan, &lastArg);
897
898 if (0 == nMscan)
899 {
900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
901 "invalid MSCAN=%d", nMscan);
902 return -EINVAL;
903 }
904
Rajeev79dbe4c2013-10-05 11:03:42 +0530905 if (TRUE == lastArg)
906 {
907 goto done;
908 }
909 else if (NULL == inPtr)
910 {
911 return -EINVAL;
912 }
913 }
914 else
915 {
916 return -EINVAL;
917 }
918
919 /*check and parse BESTN*/
920 if ((strncmp(inPtr, "BESTN", 5) == 0))
921 {
922 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800923 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800924
Rajeev Kumarc933d982013-11-18 20:04:20 -0800925 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800926 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800927 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800928 }
929
Rajeev79dbe4c2013-10-05 11:03:42 +0530930 if (TRUE == lastArg)
931 {
932 goto done;
933 }
934 else if (NULL == inPtr)
935 {
936 return -EINVAL;
937 }
938 }
939
940 /*check and parse CHANNEL*/
941 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
942 {
943 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800944
Rajeev79dbe4c2013-10-05 11:03:42 +0530945 if (('A' == val) || ('a' == val))
946 {
c_hpothuebf89732014-02-25 13:00:24 +0530947 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530948 }
949 else if (('B' == val) || ('b' == val))
950 {
c_hpothuebf89732014-02-25 13:00:24 +0530951 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530952 }
953 else
954 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800955 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
956 }
957
958 if (TRUE == lastArg)
959 {
960 goto done;
961 }
962 else if (NULL == inPtr)
963 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530964 return -EINVAL;
965 }
966 }
967
968 /*check and parse RTT*/
969 if ((strncmp(inPtr, "RTT", 3) == 0))
970 {
971 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800972 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530973 if (TRUE == lastArg)
974 {
975 goto done;
976 }
977 if (NULL == inPtr)
978 {
979 return -EINVAL;
980 }
981 }
982
983
984done:
985
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800986 pHddSetBatchScanReq->scanFrequency = nScanFreq;
987 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
988 pHddSetBatchScanReq->bestNetwork = nBestN;
989 pHddSetBatchScanReq->rfBand = ucRfBand;
990 pHddSetBatchScanReq->rtt = nRtt;
991
Rajeev79dbe4c2013-10-05 11:03:42 +0530992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
993 "Received WLS_BATCHING_SET with SCANFREQ=%d "
994 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
995 pHddSetBatchScanReq->scanFrequency,
996 pHddSetBatchScanReq->numberOfScansToBatch,
997 pHddSetBatchScanReq->bestNetwork,
998 pHddSetBatchScanReq->rfBand,
999 pHddSetBatchScanReq->rtt);
1000
1001 return 0;
1002}/*End of hdd_parse_set_batchscan_command*/
1003
1004/**---------------------------------------------------------------------------
1005
1006 \brief hdd_set_batch_scan_req_callback () - This function is called after
1007 receiving set batch scan response from FW and it saves set batch scan
1008 response data FW to HDD context and sets the completion event on
1009 which hdd_ioctl is waiting
1010
1011 \param - callbackContext Pointer to HDD adapter
1012 \param - pRsp Pointer to set batch scan response data received from FW
1013
1014 \return - nothing
1015
1016 --------------------------------------------------------------------------*/
1017static void hdd_set_batch_scan_req_callback
1018(
1019 void *callbackContext,
1020 tSirSetBatchScanRsp *pRsp
1021)
1022{
1023 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1024 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1025
1026 /*sanity check*/
1027 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1028 {
1029 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1030 "%s: Invalid pAdapter magic", __func__);
1031 VOS_ASSERT(0);
1032 return;
1033 }
1034 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1035
1036 /*save set batch scan response*/
1037 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1038
1039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1040 "Received set batch scan rsp from FW with nScansToBatch=%d",
1041 pHddSetBatchScanRsp->nScansToBatch);
1042
1043 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1044 complete(&pAdapter->hdd_set_batch_scan_req_var);
1045
1046 return;
1047}/*End of hdd_set_batch_scan_req_callback*/
1048
1049
1050/**---------------------------------------------------------------------------
1051
1052 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1053 info in hdd batch scan response queue
1054
1055 \param - pAdapter Pointer to hdd adapter
1056 \param - pAPMetaInfo Pointer to access point meta info
1057 \param - scanId scan ID of batch scan response
1058 \param - isLastAp tells whether AP is last AP in batch scan response or not
1059
1060 \return - nothing
1061
1062 --------------------------------------------------------------------------*/
1063static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1064 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1065{
1066 tHddBatchScanRsp *pHead;
1067 tHddBatchScanRsp *pNode;
1068 tHddBatchScanRsp *pPrev;
1069 tHddBatchScanRsp *pTemp;
1070 tANI_U8 ssidLen;
1071
1072 /*head of hdd batch scan response queue*/
1073 pHead = pAdapter->pBatchScanRsp;
1074
1075 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1076 if (NULL == pNode)
1077 {
1078 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s: Could not allocate memory", __func__);
1080 VOS_ASSERT(0);
1081 return;
1082 }
1083
1084 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1085 sizeof(pNode->ApInfo.bssid));
1086 ssidLen = strlen(pApMetaInfo->ssid);
1087 if (SIR_MAX_SSID_SIZE < ssidLen)
1088 {
1089 /*invalid scan result*/
1090 vos_mem_free(pNode);
1091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1092 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1093 return;
1094 }
1095 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1096 /*null terminate ssid*/
1097 pNode->ApInfo.ssid[ssidLen] = '\0';
1098 pNode->ApInfo.ch = pApMetaInfo->ch;
1099 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1100 pNode->ApInfo.age = pApMetaInfo->timestamp;
1101 pNode->ApInfo.batchId = scanId;
1102 pNode->ApInfo.isLastAp = isLastAp;
1103
1104 pNode->pNext = NULL;
1105 if (NULL == pHead)
1106 {
1107 pAdapter->pBatchScanRsp = pNode;
1108 }
1109 else
1110 {
1111 pTemp = pHead;
1112 while (NULL != pTemp)
1113 {
1114 pPrev = pTemp;
1115 pTemp = pTemp->pNext;
1116 }
1117 pPrev->pNext = pNode;
1118 }
1119
1120 return;
1121}/*End of hdd_populate_batch_scan_rsp_queue*/
1122
1123/**---------------------------------------------------------------------------
1124
1125 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1126 receiving batch scan response indication from FW. It saves get batch scan
1127 response data in HDD batch scan response queue. This callback sets the
1128 completion event on which hdd_ioctl is waiting only after getting complete
1129 batch scan response data from FW
1130
1131 \param - callbackContext Pointer to HDD adapter
1132 \param - pRsp Pointer to get batch scan response data received from FW
1133
1134 \return - nothing
1135
1136 --------------------------------------------------------------------------*/
1137static void hdd_batch_scan_result_ind_callback
1138(
1139 void *callbackContext,
1140 void *pRsp
1141)
1142{
1143 v_BOOL_t isLastAp;
1144 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001145 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301146 tANI_U32 numberScanList;
1147 tANI_U32 nextScanListOffset;
1148 tANI_U32 nextApMetaInfoOffset;
1149 hdd_adapter_t* pAdapter;
1150 tpSirBatchScanList pScanList;
1151 tpSirBatchScanNetworkInfo pApMetaInfo;
1152 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1153 tSirSetBatchScanReq *pReq;
1154
1155 pAdapter = (hdd_adapter_t *)callbackContext;
1156 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001157 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301158 {
1159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1160 "%s: Invalid pAdapter magic", __func__);
1161 VOS_ASSERT(0);
1162 return;
1163 }
1164
1165 /*initialize locals*/
1166 pReq = &pAdapter->hddSetBatchScanReq;
1167 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1168 isLastAp = FALSE;
1169 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001170 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301171 numberScanList = 0;
1172 nextScanListOffset = 0;
1173 nextApMetaInfoOffset = 0;
1174 pScanList = NULL;
1175 pApMetaInfo = NULL;
1176
1177 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1178 {
1179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1180 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1181 isLastAp = TRUE;
1182 goto done;
1183 }
1184
1185 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1186 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1187 "Batch scan rsp: numberScalList %d", numberScanList);
1188
1189 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1190 {
1191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1192 "%s: numberScanList %d", __func__, numberScanList);
1193 isLastAp = TRUE;
1194 goto done;
1195 }
1196
1197 while (numberScanList)
1198 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001199 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301200 nextScanListOffset);
1201 if (NULL == pScanList)
1202 {
1203 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1204 "%s: pScanList is %p", __func__, pScanList);
1205 isLastAp = TRUE;
1206 goto done;
1207 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001208 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001210 "Batch scan rsp: numApMetaInfo %d scanId %d",
1211 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301212
1213 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1214 {
1215 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1216 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1217 isLastAp = TRUE;
1218 goto done;
1219 }
1220
Rajeev Kumarce651e42013-10-21 18:57:15 -07001221 /*Initialize next AP meta info offset for next scan list*/
1222 nextApMetaInfoOffset = 0;
1223
Rajeev79dbe4c2013-10-05 11:03:42 +05301224 while (numApMetaInfo)
1225 {
1226 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1227 nextApMetaInfoOffset);
1228 if (NULL == pApMetaInfo)
1229 {
1230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1231 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1232 isLastAp = TRUE;
1233 goto done;
1234 }
1235 /*calculate AP age*/
1236 pApMetaInfo->timestamp =
1237 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1238
1239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001240 "%s: bssId "MAC_ADDRESS_STR
1241 " ch %d rssi %d timestamp %d", __func__,
1242 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1243 pApMetaInfo->ch, pApMetaInfo->rssi,
1244 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301245
1246 /*mark last AP in batch scan response*/
1247 if ((TRUE == pBatchScanRsp->isLastResult) &&
1248 (1 == numberScanList) && (1 == numApMetaInfo))
1249 {
1250 isLastAp = TRUE;
1251 }
1252
1253 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1254 /*store batch scan repsonse in hdd queue*/
1255 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1256 pScanList->scanId, isLastAp);
1257 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1258
1259 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1260 numApMetaInfo--;
1261 }
1262
Rajeev Kumarce651e42013-10-21 18:57:15 -07001263 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1264 + (sizeof(tSirBatchScanNetworkInfo)
1265 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301266 numberScanList--;
1267 }
1268
1269done:
1270
1271 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1272 requested from hdd_ioctl*/
1273 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1274 (TRUE == isLastAp))
1275 {
1276 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1277 complete(&pAdapter->hdd_get_batch_scan_req_var);
1278 }
1279
1280 return;
1281}/*End of hdd_batch_scan_result_ind_callback*/
1282
1283/**---------------------------------------------------------------------------
1284
1285 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1286 response as per batch scan FR request format by putting proper markers
1287
1288 \param - pDest pointer to destination buffer
1289 \param - cur_len current length
1290 \param - tot_len total remaining size which can be written to user space
1291 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1292 \param - pAdapter Pointer to HDD adapter
1293
1294 \return - ret no of characters written
1295
1296 --------------------------------------------------------------------------*/
1297static tANI_U32
1298hdd_format_batch_scan_rsp
1299(
1300 tANI_U8 *pDest,
1301 tANI_U32 cur_len,
1302 tANI_U32 tot_len,
1303 tHddBatchScanRsp *pApMetaInfo,
1304 hdd_adapter_t* pAdapter
1305)
1306{
1307 tANI_U32 ret = 0;
1308 tANI_U32 rem_len = 0;
1309 tANI_U8 temp_len = 0;
1310 tANI_U8 temp_total_len = 0;
1311 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1312 tANI_U8 *pTemp = temp;
1313
1314 /*Batch scan reponse needs to be returned to user space in
1315 following format:
1316 "scancount=X\n" where X is the number of scans in current batch
1317 batch
1318 "trunc\n" optional present if current scan truncated
1319 "bssid=XX:XX:XX:XX:XX:XX\n"
1320 "ssid=XXXX\n"
1321 "freq=X\n" frequency in Mhz
1322 "level=XX\n"
1323 "age=X\n" ms
1324 "dist=X\n" cm (-1 if not available)
1325 "errror=X\n" (-1if not available)
1326 "====\n" (end of ap marker)
1327 "####\n" (end of scan marker)
1328 "----\n" (end of results)*/
1329 /*send scan result in above format to user space based on
1330 available length*/
1331 /*The GET response may have more data than the driver can return in its
1332 buffer. In that case the buffer should be filled to the nearest complete
1333 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1334 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1335 The final buffer should end with "----\n"*/
1336
1337 /*sanity*/
1338 if (cur_len > tot_len)
1339 {
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1341 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1342 return 0;
1343 }
1344 else
1345 {
1346 rem_len = (tot_len - cur_len);
1347 }
1348
1349 /*end scan marker*/
1350 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1351 {
1352 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1353 pTemp += temp_len;
1354 temp_total_len += temp_len;
1355 }
1356
1357 /*bssid*/
1358 temp_len = snprintf(pTemp, sizeof(temp),
1359 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1360 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1361 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1362 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1363 pTemp += temp_len;
1364 temp_total_len += temp_len;
1365
1366 /*ssid*/
1367 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1368 pApMetaInfo->ApInfo.ssid);
1369 pTemp += temp_len;
1370 temp_total_len += temp_len;
1371
1372 /*freq*/
1373 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001374 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301375 pTemp += temp_len;
1376 temp_total_len += temp_len;
1377
1378 /*level*/
1379 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1380 pApMetaInfo->ApInfo.rssi);
1381 pTemp += temp_len;
1382 temp_total_len += temp_len;
1383
1384 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001385 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301386 pApMetaInfo->ApInfo.age);
1387 pTemp += temp_len;
1388 temp_total_len += temp_len;
1389
1390 /*dist*/
1391 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1392 pTemp += temp_len;
1393 temp_total_len += temp_len;
1394
1395 /*error*/
1396 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1397 pTemp += temp_len;
1398 temp_total_len += temp_len;
1399
1400 /*end AP marker*/
1401 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1402 pTemp += temp_len;
1403 temp_total_len += temp_len;
1404
1405 /*last AP in batch scan response*/
1406 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1407 {
1408 /*end scan marker*/
1409 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1410 pTemp += temp_len;
1411 temp_total_len += temp_len;
1412
1413 /*end batch scan result marker*/
1414 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1415 pTemp += temp_len;
1416 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001417
Rajeev79dbe4c2013-10-05 11:03:42 +05301418 }
1419
1420 if (temp_total_len < rem_len)
1421 {
1422 ret = temp_total_len + 1;
1423 strlcpy(pDest, temp, ret);
1424 pAdapter->isTruncated = FALSE;
1425 }
1426 else
1427 {
1428 pAdapter->isTruncated = TRUE;
1429 if (rem_len >= strlen("%%%%"))
1430 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001431 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301432 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001433 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301434 {
1435 ret = 0;
1436 }
1437 }
1438
1439 return ret;
1440
1441}/*End of hdd_format_batch_scan_rsp*/
1442
1443/**---------------------------------------------------------------------------
1444
1445 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1446 buffer starting with head of hdd batch scan response queue
1447
1448 \param - pAdapter Pointer to HDD adapter
1449 \param - pDest Pointer to user data buffer
1450 \param - cur_len current offset in user buffer
1451 \param - rem_len remaining no of bytes in user buffer
1452
1453 \return - number of bytes written in user buffer
1454
1455 --------------------------------------------------------------------------*/
1456
1457tANI_U32 hdd_populate_user_batch_scan_rsp
1458(
1459 hdd_adapter_t* pAdapter,
1460 tANI_U8 *pDest,
1461 tANI_U32 cur_len,
1462 tANI_U32 rem_len
1463)
1464{
1465 tHddBatchScanRsp *pHead;
1466 tHddBatchScanRsp *pPrev;
1467 tANI_U32 len;
1468
Rajeev79dbe4c2013-10-05 11:03:42 +05301469 pAdapter->isTruncated = FALSE;
1470
1471 /*head of hdd batch scan response queue*/
1472 pHead = pAdapter->pBatchScanRsp;
1473 while (pHead)
1474 {
1475 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1476 pAdapter);
1477 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001478 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301479 cur_len += len;
1480 if(TRUE == pAdapter->isTruncated)
1481 {
1482 /*result is truncated return rest of scan rsp in next req*/
1483 cur_len = rem_len;
1484 break;
1485 }
1486 pPrev = pHead;
1487 pHead = pHead->pNext;
1488 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001489 if (TRUE == pPrev->ApInfo.isLastAp)
1490 {
1491 pAdapter->prev_batch_id = 0;
1492 }
1493 else
1494 {
1495 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1496 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301497 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001498 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301499 }
1500
1501 return cur_len;
1502}/*End of hdd_populate_user_batch_scan_rsp*/
1503
1504/**---------------------------------------------------------------------------
1505
1506 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1507 scan response data from HDD queue to user space
1508 It does following in detail:
1509 a) if HDD has enough data in its queue then it 1st copies data to user
1510 space and then send get batch scan indication message to FW. In this
1511 case it does not wait on any event and batch scan response data will
1512 be populated in HDD response queue in MC thread context after receiving
1513 indication from FW
1514 b) else send get batch scan indication message to FW and wait on an event
1515 which will be set once HDD receives complete batch scan response from
1516 FW and then this function returns batch scan response to user space
1517
1518 \param - pAdapter Pointer to HDD adapter
1519 \param - pPrivData Pointer to priv_data
1520
1521 \return - 0 for success -EFAULT for failure
1522
1523 --------------------------------------------------------------------------*/
1524
1525int hdd_return_batch_scan_rsp_to_user
1526(
1527 hdd_adapter_t* pAdapter,
1528 hdd_priv_data_t *pPrivData,
1529 tANI_U8 *command
1530)
1531{
1532 tANI_U8 *pDest;
1533 tANI_U32 count = 0;
1534 tANI_U32 len = 0;
1535 tANI_U32 cur_len = 0;
1536 tANI_U32 rem_len = 0;
1537 eHalStatus halStatus;
1538 unsigned long rc;
1539 tSirTriggerBatchScanResultInd *pReq;
1540
1541 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1542 pReq->param = 0;/*batch scan client*/
1543 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1544 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1545
1546 cur_len = pPrivData->used_len;
1547 if (pPrivData->total_len > pPrivData->used_len)
1548 {
1549 rem_len = pPrivData->total_len - pPrivData->used_len;
1550 }
1551 else
1552 {
1553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1554 "%s: Invalid user data buffer total_len %d used_len %d",
1555 __func__, pPrivData->total_len, pPrivData->used_len);
1556 return -EFAULT;
1557 }
1558
1559 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1560 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1561 cur_len, rem_len);
1562 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1563
1564 /*enough scan result available in cache to return to user space or
1565 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001566 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301567 {
1568 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1569 halStatus = sme_TriggerBatchScanResultInd(
1570 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1571 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1572 pAdapter);
1573 if ( eHAL_STATUS_SUCCESS == halStatus )
1574 {
1575 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1576 {
1577 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1578 rc = wait_for_completion_timeout(
1579 &pAdapter->hdd_get_batch_scan_req_var,
1580 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1581 if (0 == rc)
1582 {
1583 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1584 "%s: Timeout waiting to fetch batch scan rsp from fw",
1585 __func__);
1586 return -EFAULT;
1587 }
1588 }
1589
1590 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001591 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301592 pDest += len;
1593 cur_len += len;
1594
1595 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1596 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1597 cur_len, rem_len);
1598 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1599
1600 count = 0;
1601 len = (len - pPrivData->used_len);
1602 pDest = (command + pPrivData->used_len);
1603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001604 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301605 while(count < len)
1606 {
1607 printk("%c", *(pDest + count));
1608 count++;
1609 }
1610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1611 "%s: copy %d data to user buffer", __func__, len);
1612 if (copy_to_user(pPrivData->buf, pDest, len))
1613 {
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1615 "%s: failed to copy data to user buffer", __func__);
1616 return -EFAULT;
1617 }
1618 }
1619 else
1620 {
1621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1622 "sme_GetBatchScanScan returned failure halStatus %d",
1623 halStatus);
1624 return -EINVAL;
1625 }
1626 }
1627 else
1628 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301629 count = 0;
1630 len = (len - pPrivData->used_len);
1631 pDest = (command + pPrivData->used_len);
1632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001633 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301634 while(count < len)
1635 {
1636 printk("%c", *(pDest + count));
1637 count++;
1638 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1640 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301641 if (copy_to_user(pPrivData->buf, pDest, len))
1642 {
1643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1644 "%s: failed to copy data to user buffer", __func__);
1645 return -EFAULT;
1646 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301647 }
1648
1649 return 0;
1650} /*End of hdd_return_batch_scan_rsp_to_user*/
1651
Rajeev Kumar8b373292014-01-08 20:36:55 -08001652
1653/**---------------------------------------------------------------------------
1654
1655 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1656 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1657 WLS_BATCHING VERSION
1658 WLS_BATCHING SET
1659 WLS_BATCHING GET
1660 WLS_BATCHING STOP
1661
1662 \param - pAdapter Pointer to HDD adapter
1663 \param - pPrivdata Pointer to priv_data
1664 \param - command Pointer to command
1665
1666 \return - 0 for success -EFAULT for failure
1667
1668 --------------------------------------------------------------------------*/
1669
1670int hdd_handle_batch_scan_ioctl
1671(
1672 hdd_adapter_t *pAdapter,
1673 hdd_priv_data_t *pPrivdata,
1674 tANI_U8 *command
1675)
1676{
1677 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001678 hdd_context_t *pHddCtx;
1679
1680 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1681 ret = wlan_hdd_validate_context(pHddCtx);
1682 if (ret)
1683 {
1684 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1685 "%s: HDD context is not valid!", __func__);
1686 goto exit;
1687 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001688
1689 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1690 {
1691 char extra[32];
1692 tANI_U8 len = 0;
1693 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1694
1695 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1696 {
1697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1698 "%s: Batch scan feature is not supported by FW", __func__);
1699 ret = -EINVAL;
1700 goto exit;
1701 }
1702
1703 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1704 version);
1705 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1706 {
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: failed to copy data to user buffer", __func__);
1709 ret = -EFAULT;
1710 goto exit;
1711 }
1712 ret = HDD_BATCH_SCAN_VERSION;
1713 }
1714 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1715 {
1716 int status;
1717 tANI_U8 *value = (command + 16);
1718 eHalStatus halStatus;
1719 unsigned long rc;
1720 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1721 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1722
1723 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1724 {
1725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1726 "%s: Batch scan feature is not supported by FW", __func__);
1727 ret = -EINVAL;
1728 goto exit;
1729 }
1730
1731 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1732 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1733 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1734 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1735 {
1736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1737 "Received WLS_BATCHING SET command in invalid mode %d "
1738 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1739 pAdapter->device_mode);
1740 ret = -EINVAL;
1741 goto exit;
1742 }
1743
1744 status = hdd_parse_set_batchscan_command(value, pReq);
1745 if (status)
1746 {
1747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1748 "Invalid WLS_BATCHING SET command");
1749 ret = -EINVAL;
1750 goto exit;
1751 }
1752
1753
1754 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1755 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1756 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1757 pAdapter);
1758
1759 if ( eHAL_STATUS_SUCCESS == halStatus )
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1762 "sme_SetBatchScanReq returned success halStatus %d",
1763 halStatus);
1764 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1765 {
1766 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1767 rc = wait_for_completion_timeout(
1768 &pAdapter->hdd_set_batch_scan_req_var,
1769 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1770 if (0 == rc)
1771 {
1772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1773 "%s: Timeout waiting for set batch scan to complete",
1774 __func__);
1775 ret = -EINVAL;
1776 goto exit;
1777 }
1778 }
1779 if ( !pRsp->nScansToBatch )
1780 {
1781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1782 "%s: Received set batch scan failure response from FW",
1783 __func__);
1784 ret = -EINVAL;
1785 goto exit;
1786 }
1787 /*As per the Batch Scan Framework API we should return the MIN of
1788 either MSCAN or the max # of scans firmware can cache*/
1789 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1790
1791 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1792
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1794 "%s: request MSCAN %d response MSCAN %d ret %d",
1795 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1796 }
1797 else
1798 {
1799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 "sme_SetBatchScanReq returned failure halStatus %d",
1801 halStatus);
1802 ret = -EINVAL;
1803 goto exit;
1804 }
1805 }
1806 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1807 {
1808 eHalStatus halStatus;
1809 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1810 pInd->param = 0;
1811
1812 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1813 {
1814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1815 "%s: Batch scan feature is not supported by FW", __func__);
1816 ret = -EINVAL;
1817 goto exit;
1818 }
1819
1820 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1821 {
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1823 "Batch scan is not yet enabled batch scan state %d",
1824 pAdapter->batchScanState);
1825 ret = -EINVAL;
1826 goto exit;
1827 }
1828
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001829 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1830 hdd_deinit_batch_scan(pAdapter);
1831 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1832
Rajeev Kumar8b373292014-01-08 20:36:55 -08001833 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1834
1835 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1836 pAdapter->sessionId);
1837 if ( eHAL_STATUS_SUCCESS == halStatus )
1838 {
1839 ret = 0;
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1841 "sme_StopBatchScanInd returned success halStatus %d",
1842 halStatus);
1843 }
1844 else
1845 {
1846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1847 "sme_StopBatchScanInd returned failure halStatus %d",
1848 halStatus);
1849 ret = -EINVAL;
1850 goto exit;
1851 }
1852 }
1853 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1854 {
1855 tANI_U32 remain_len;
1856
1857 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1858 {
1859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1860 "%s: Batch scan feature is not supported by FW", __func__);
1861 ret = -EINVAL;
1862 goto exit;
1863 }
1864
1865 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "Batch scan is not yet enabled could not return results"
1869 "Batch Scan state %d",
1870 pAdapter->batchScanState);
1871 ret = -EINVAL;
1872 goto exit;
1873 }
1874
1875 pPrivdata->used_len = 16;
1876 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1877 if (remain_len < pPrivdata->total_len)
1878 {
1879 /*Clear previous batch scan response data if any*/
1880 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1881 }
1882 else
1883 {
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1885 "Invalid total length from user space can't fetch batch"
1886 " scan response total_len %d used_len %d remain len %d",
1887 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1888 ret = -EINVAL;
1889 goto exit;
1890 }
1891 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1892 }
1893
1894exit:
1895
1896 return ret;
1897}
1898
1899
Rajeev79dbe4c2013-10-05 11:03:42 +05301900#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1901
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001902static int hdd_driver_command(hdd_adapter_t *pAdapter,
1903 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07001904{
Jeff Johnson295189b2012-06-20 16:38:30 -07001905 hdd_priv_data_t priv_data;
1906 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001907 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001908
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001909 /*
1910 * Note that valid pointers are provided by caller
1911 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001912
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001913 /* copy to local struct to avoid numerous changes to legacy code */
1914 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07001915
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001916 if (priv_data.total_len <= 0 ||
1917 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001918 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001919 hddLog(VOS_TRACE_LEVEL_WARN,
1920 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1921 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001922 ret = -EINVAL;
1923 goto exit;
1924 }
1925
1926 /* Allocate +1 for '\0' */
1927 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 if (!command)
1929 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001930 hddLog(VOS_TRACE_LEVEL_ERROR,
1931 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001932 ret = -ENOMEM;
1933 goto exit;
1934 }
1935
1936 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1937 {
1938 ret = -EFAULT;
1939 goto exit;
1940 }
1941
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001942 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001943 command[priv_data.total_len] = '\0';
1944
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001945 /* at one time the following block of code was conditional. braces
1946 * have been retained to avoid re-indenting the legacy code
1947 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 {
1949 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1950
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001952 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001953
1954 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1955 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301956 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1957 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
1958 pAdapter->sessionId, (unsigned)
1959 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
1960 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
1961 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
1962 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1964 sizeof(tSirMacAddr)))
1965 {
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001967 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001968 ret = -EFAULT;
1969 }
1970 }
Amar Singhal0974e402013-02-12 14:27:46 -08001971 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 {
Amar Singhal0974e402013-02-12 14:27:46 -08001973 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001974
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001976
1977 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001980 "%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 -07001981 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001982 ret = hdd_setBand_helper(pAdapter->dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301983 if(ret != 0)
1984 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07001985 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001986 }
Kiet Lamf040f472013-11-20 21:15:23 +05301987 else if(strncmp(command, "SETWMMPS", 8) == 0)
1988 {
1989 tANI_U8 *ptr = command;
1990 ret = hdd_wmmps_helper(pAdapter, ptr);
1991 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001992 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1993 {
1994 char *country_code;
1995
1996 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001997
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001998 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001999 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002000#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302001 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002002#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002003 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2004 (void *)(tSmeChangeCountryCallback)
2005 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302006 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002007 if (eHAL_STATUS_SUCCESS == ret)
2008 {
2009 ret = wait_for_completion_interruptible_timeout(
2010 &pAdapter->change_country_code,
2011 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2012 if (0 >= ret)
2013 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002014 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302015 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002016 }
2017 }
2018 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002019 {
2020 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002021 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002022 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002023 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002024
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002025 }
2026 /*
2027 command should be a string having format
2028 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2029 */
Amar Singhal0974e402013-02-12 14:27:46 -08002030 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002031 {
Amar Singhal0974e402013-02-12 14:27:46 -08002032 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002033
2034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002035 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002036
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002037 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002038 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002039 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2040 {
2041 int suspend = 0;
2042 tANI_U8 *ptr = (tANI_U8*)command + 15;
2043
2044 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302045 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2046 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2047 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002048 hdd_set_wlan_suspend_mode(suspend);
2049 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002050#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2051 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2052 {
2053 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002054 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002055 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2056 eHalStatus status = eHAL_STATUS_SUCCESS;
2057
2058 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2059 value = value + 15;
2060
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002061 /* Convert the value from ascii to integer */
2062 ret = kstrtos8(value, 10, &rssi);
2063 if (ret < 0)
2064 {
2065 /* If the input value is greater than max value of datatype, then also
2066 kstrtou8 fails */
2067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2068 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002069 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002070 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2071 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2072 ret = -EINVAL;
2073 goto exit;
2074 }
2075
Srinivas Girigowdade697412013-02-14 16:31:48 -08002076 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002077
Srinivas Girigowdade697412013-02-14 16:31:48 -08002078 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2079 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2080 {
2081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2082 "Neighbor lookup threshold value %d is out of range"
2083 " (Min: %d Max: %d)", lookUpThreshold,
2084 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2085 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2086 ret = -EINVAL;
2087 goto exit;
2088 }
2089
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302090 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2091 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2092 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2094 "%s: Received Command to Set Roam trigger"
2095 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2096
2097 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2098 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2099 if (eHAL_STATUS_SUCCESS != status)
2100 {
2101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2102 "%s: Failed to set roam trigger, try again", __func__);
2103 ret = -EPERM;
2104 goto exit;
2105 }
2106
2107 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2108 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2109 }
2110 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2111 {
2112 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2113 int rssi = (-1) * lookUpThreshold;
2114 char extra[32];
2115 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302116 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2117 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2118 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002119 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002120 if (copy_to_user(priv_data.buf, &extra, len + 1))
2121 {
2122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2123 "%s: failed to copy data to user buffer", __func__);
2124 ret = -EFAULT;
2125 goto exit;
2126 }
2127 }
2128 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2129 {
2130 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002131 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002132 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002133
Srinivas Girigowdade697412013-02-14 16:31:48 -08002134 /* input refresh period is in terms of seconds */
2135 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2136 value = value + 18;
2137 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002138 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002139 if (ret < 0)
2140 {
2141 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002142 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002144 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002145 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002146 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2147 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002148 ret = -EINVAL;
2149 goto exit;
2150 }
2151
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002152 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2153 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002154 {
2155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002156 "Roam scan period value %d is out of range"
2157 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002158 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2159 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002160 ret = -EINVAL;
2161 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302162 }
2163 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2164 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2165 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002166 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002167
2168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2169 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002170 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002171
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002172 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2173 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002174 }
2175 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2176 {
2177 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2178 char extra[32];
2179 tANI_U8 len = 0;
2180
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302181 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2182 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2183 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002184 len = scnprintf(extra, sizeof(extra), "%s %d",
2185 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002186 /* Returned value is in units of seconds */
2187 if (copy_to_user(priv_data.buf, &extra, len + 1))
2188 {
2189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2190 "%s: failed to copy data to user buffer", __func__);
2191 ret = -EFAULT;
2192 goto exit;
2193 }
2194 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002195 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2196 {
2197 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002198 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002199 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002200
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002201 /* input refresh period is in terms of seconds */
2202 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2203 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002204
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002205 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002206 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002207 if (ret < 0)
2208 {
2209 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002210 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002212 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002213 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002214 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2215 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2216 ret = -EINVAL;
2217 goto exit;
2218 }
2219
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002220 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2221 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2222 {
2223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2224 "Neighbor scan results refresh period value %d is out of range"
2225 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2226 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2227 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2228 ret = -EINVAL;
2229 goto exit;
2230 }
2231 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2232
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2234 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002235 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002236
2237 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2238 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2239 }
2240 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2241 {
2242 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2243 char extra[32];
2244 tANI_U8 len = 0;
2245
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002246 len = scnprintf(extra, sizeof(extra), "%s %d",
2247 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002248 /* Returned value is in units of seconds */
2249 if (copy_to_user(priv_data.buf, &extra, len + 1))
2250 {
2251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2252 "%s: failed to copy data to user buffer", __func__);
2253 ret = -EFAULT;
2254 goto exit;
2255 }
2256 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002257#ifdef FEATURE_WLAN_LFR
2258 /* SETROAMMODE */
2259 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2260 {
2261 tANI_U8 *value = command;
2262 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2263
2264 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2265 value = value + SIZE_OF_SETROAMMODE + 1;
2266
2267 /* Convert the value from ascii to integer */
2268 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2269 if (ret < 0)
2270 {
2271 /* If the input value is greater than max value of datatype, then also
2272 kstrtou8 fails */
2273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2274 "%s: kstrtou8 failed range [%d - %d]", __func__,
2275 CFG_LFR_FEATURE_ENABLED_MIN,
2276 CFG_LFR_FEATURE_ENABLED_MAX);
2277 ret = -EINVAL;
2278 goto exit;
2279 }
2280 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2281 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2282 {
2283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2284 "Roam Mode value %d is out of range"
2285 " (Min: %d Max: %d)", roamMode,
2286 CFG_LFR_FEATURE_ENABLED_MIN,
2287 CFG_LFR_FEATURE_ENABLED_MAX);
2288 ret = -EINVAL;
2289 goto exit;
2290 }
2291
2292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2293 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2294 /*
2295 * Note that
2296 * SETROAMMODE 0 is to enable LFR while
2297 * SETROAMMODE 1 is to disable LFR, but
2298 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2299 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2300 */
2301 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2302 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2303 else
2304 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2305
2306 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2307 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2308 }
2309 /* GETROAMMODE */
2310 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2311 {
2312 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2313 char extra[32];
2314 tANI_U8 len = 0;
2315
2316 /*
2317 * roamMode value shall be inverted because the sementics is different.
2318 */
2319 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2320 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2321 else
2322 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2323
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002324 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002325 if (copy_to_user(priv_data.buf, &extra, len + 1))
2326 {
2327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2328 "%s: failed to copy data to user buffer", __func__);
2329 ret = -EFAULT;
2330 goto exit;
2331 }
2332 }
2333#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002334#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002335#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002336 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2337 {
2338 tANI_U8 *value = command;
2339 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2340
2341 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2342 value = value + 13;
2343 /* Convert the value from ascii to integer */
2344 ret = kstrtou8(value, 10, &roamRssiDiff);
2345 if (ret < 0)
2346 {
2347 /* If the input value is greater than max value of datatype, then also
2348 kstrtou8 fails */
2349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2350 "%s: kstrtou8 failed range [%d - %d]", __func__,
2351 CFG_ROAM_RSSI_DIFF_MIN,
2352 CFG_ROAM_RSSI_DIFF_MAX);
2353 ret = -EINVAL;
2354 goto exit;
2355 }
2356
2357 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2358 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2359 {
2360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2361 "Roam rssi diff value %d is out of range"
2362 " (Min: %d Max: %d)", roamRssiDiff,
2363 CFG_ROAM_RSSI_DIFF_MIN,
2364 CFG_ROAM_RSSI_DIFF_MAX);
2365 ret = -EINVAL;
2366 goto exit;
2367 }
2368
2369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2370 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2371
2372 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2373 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2374 }
2375 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2376 {
2377 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2378 char extra[32];
2379 tANI_U8 len = 0;
2380
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302381 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2382 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2383 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002384 len = scnprintf(extra, sizeof(extra), "%s %d",
2385 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002386 if (copy_to_user(priv_data.buf, &extra, len + 1))
2387 {
2388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2389 "%s: failed to copy data to user buffer", __func__);
2390 ret = -EFAULT;
2391 goto exit;
2392 }
2393 }
2394#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002395#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002396 else if (strncmp(command, "GETBAND", 7) == 0)
2397 {
2398 int band = -1;
2399 char extra[32];
2400 tANI_U8 len = 0;
2401 hdd_getBand_helper(pHddCtx, &band);
2402
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302403 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2404 TRACE_CODE_HDD_GETBAND_IOCTL,
2405 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002406 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002407 if (copy_to_user(priv_data.buf, &extra, len + 1))
2408 {
2409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2410 "%s: failed to copy data to user buffer", __func__);
2411 ret = -EFAULT;
2412 goto exit;
2413 }
2414 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002415 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2416 {
2417 tANI_U8 *value = command;
2418 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2419 tANI_U8 numChannels = 0;
2420 eHalStatus status = eHAL_STATUS_SUCCESS;
2421
2422 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2423 if (eHAL_STATUS_SUCCESS != status)
2424 {
2425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2426 "%s: Failed to parse channel list information", __func__);
2427 ret = -EINVAL;
2428 goto exit;
2429 }
2430
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302431 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2432 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2433 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002434 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2435 {
2436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2437 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2438 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2439 ret = -EINVAL;
2440 goto exit;
2441 }
2442 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2443 numChannels);
2444 if (eHAL_STATUS_SUCCESS != status)
2445 {
2446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2447 "%s: Failed to update channel list information", __func__);
2448 ret = -EINVAL;
2449 goto exit;
2450 }
2451 }
2452 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2453 {
2454 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2455 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002456 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002457 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002458 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002459
2460 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2461 ChannelList, &numChannels ))
2462 {
2463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2464 "%s: failed to get roam scan channel list", __func__);
2465 ret = -EFAULT;
2466 goto exit;
2467 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302468 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2469 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2470 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002471 /* output channel list is of the format
2472 [Number of roam scan channels][Channel1][Channel2]... */
2473 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002474 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002475 for (j = 0; (j < numChannels); j++)
2476 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002477 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2478 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002479 }
2480
2481 if (copy_to_user(priv_data.buf, &extra, len + 1))
2482 {
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2484 "%s: failed to copy data to user buffer", __func__);
2485 ret = -EFAULT;
2486 goto exit;
2487 }
2488 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002489 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2490 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002491 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002492 char extra[32];
2493 tANI_U8 len = 0;
2494
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002495 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002496 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002497 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002498 hdd_is_okc_mode_enabled(pHddCtx) &&
2499 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2500 {
2501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002502 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002503 " hence this operation is not permitted!", __func__);
2504 ret = -EPERM;
2505 goto exit;
2506 }
2507
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002508 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002509 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002510 if (copy_to_user(priv_data.buf, &extra, len + 1))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "%s: failed to copy data to user buffer", __func__);
2514 ret = -EFAULT;
2515 goto exit;
2516 }
2517 }
2518 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2519 {
2520 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2521 char extra[32];
2522 tANI_U8 len = 0;
2523
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002524 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002525 then this operation is not permitted (return FAILURE) */
2526 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002527 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002528 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002531 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002532 " hence this operation is not permitted!", __func__);
2533 ret = -EPERM;
2534 goto exit;
2535 }
2536
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002537 len = scnprintf(extra, sizeof(extra), "%s %d",
2538 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002539 if (copy_to_user(priv_data.buf, &extra, len + 1))
2540 {
2541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2542 "%s: failed to copy data to user buffer", __func__);
2543 ret = -EFAULT;
2544 goto exit;
2545 }
2546 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002547 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002548 {
2549 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2550 char extra[32];
2551 tANI_U8 len = 0;
2552
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002553 len = scnprintf(extra, sizeof(extra), "%s %d",
2554 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002555 if (copy_to_user(priv_data.buf, &extra, len + 1))
2556 {
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "%s: failed to copy data to user buffer", __func__);
2559 ret = -EFAULT;
2560 goto exit;
2561 }
2562 }
2563 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2564 {
2565 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2566 char extra[32];
2567 tANI_U8 len = 0;
2568
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002569 len = scnprintf(extra, sizeof(extra), "%s %d",
2570 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002571 if (copy_to_user(priv_data.buf, &extra, len + 1))
2572 {
2573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2574 "%s: failed to copy data to user buffer", __func__);
2575 ret = -EFAULT;
2576 goto exit;
2577 }
2578 }
2579 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2580 {
2581 tANI_U8 *value = command;
2582 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2583
2584 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2585 value = value + 26;
2586 /* Convert the value from ascii to integer */
2587 ret = kstrtou8(value, 10, &minTime);
2588 if (ret < 0)
2589 {
2590 /* If the input value is greater than max value of datatype, then also
2591 kstrtou8 fails */
2592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2593 "%s: kstrtou8 failed range [%d - %d]", __func__,
2594 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2595 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2596 ret = -EINVAL;
2597 goto exit;
2598 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002599 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2600 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2601 {
2602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2603 "scan min channel time value %d is out of range"
2604 " (Min: %d Max: %d)", minTime,
2605 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2606 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2607 ret = -EINVAL;
2608 goto exit;
2609 }
2610
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302611 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2612 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2613 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2615 "%s: Received Command to change channel min time = %d", __func__, minTime);
2616
2617 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2618 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2619 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002620 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2621 {
2622 tANI_U8 *value = command;
2623 tANI_U8 channel = 0;
2624 tANI_U8 dwellTime = 0;
2625 tANI_U8 bufLen = 0;
2626 tANI_U8 *buf = NULL;
2627 tSirMacAddr targetApBssid;
2628 eHalStatus status = eHAL_STATUS_SUCCESS;
2629 struct ieee80211_channel chan;
2630 tANI_U8 finalLen = 0;
2631 tANI_U8 *finalBuf = NULL;
2632 tANI_U8 temp = 0;
2633 u64 cookie;
2634 hdd_station_ctx_t *pHddStaCtx = NULL;
2635 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2636
2637 /* if not associated, no need to send action frame */
2638 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2639 {
2640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2641 ret = -EINVAL;
2642 goto exit;
2643 }
2644
2645 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2646 &dwellTime, &buf, &bufLen);
2647 if (eHAL_STATUS_SUCCESS != status)
2648 {
2649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2650 "%s: Failed to parse send action frame data", __func__);
2651 ret = -EINVAL;
2652 goto exit;
2653 }
2654
2655 /* if the target bssid is different from currently associated AP,
2656 then no need to send action frame */
2657 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2658 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2659 {
2660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2661 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002662 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002663 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002664 goto exit;
2665 }
2666
2667 /* if the channel number is different from operating channel then
2668 no need to send action frame */
2669 if (channel != pHddStaCtx->conn_info.operationChannel)
2670 {
2671 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2672 "%s: channel(%d) is different from operating channel(%d)",
2673 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2674 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002675 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002676 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002677 goto exit;
2678 }
2679 chan.center_freq = sme_ChnToFreq(channel);
2680
2681 finalLen = bufLen + 24;
2682 finalBuf = vos_mem_malloc(finalLen);
2683 if (NULL == finalBuf)
2684 {
2685 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2686 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002687 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002688 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002689 goto exit;
2690 }
2691 vos_mem_zero(finalBuf, finalLen);
2692
2693 /* Fill subtype */
2694 temp = SIR_MAC_MGMT_ACTION << 4;
2695 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2696
2697 /* Fill type */
2698 temp = SIR_MAC_MGMT_FRAME;
2699 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2700
2701 /* Fill destination address (bssid of the AP) */
2702 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2703
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002704 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002705 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2706
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002707 /* Fill BSSID (AP mac address) */
2708 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002709
2710 /* Fill received buffer from 24th address */
2711 vos_mem_copy(finalBuf + 24, buf, bufLen);
2712
Jeff Johnson11c33152013-04-16 17:52:40 -07002713 /* done with the parsed buffer */
2714 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002715 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002716
DARAM SUDHA39eede62014-02-12 11:16:40 +05302717 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002718#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2719 &(pAdapter->wdev),
2720#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002721 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002722#endif
2723 &chan, 0,
2724#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2725 NL80211_CHAN_HT20, 1,
2726#endif
2727 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002728 1, &cookie );
2729 vos_mem_free(finalBuf);
2730 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002731 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2732 {
2733 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2734 char extra[32];
2735 tANI_U8 len = 0;
2736
2737 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002738 len = scnprintf(extra, sizeof(extra), "%s %d",
2739 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302740 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2741 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2742 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002743 if (copy_to_user(priv_data.buf, &extra, len + 1))
2744 {
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2746 "%s: failed to copy data to user buffer", __func__);
2747 ret = -EFAULT;
2748 goto exit;
2749 }
2750 }
2751 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2752 {
2753 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002754 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002755
2756 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2757 value = value + 19;
2758 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002759 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002760 if (ret < 0)
2761 {
2762 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002763 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002765 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002766 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2767 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2768 ret = -EINVAL;
2769 goto exit;
2770 }
2771
2772 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2773 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2774 {
2775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2776 "lfr mode value %d is out of range"
2777 " (Min: %d Max: %d)", maxTime,
2778 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2779 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2780 ret = -EINVAL;
2781 goto exit;
2782 }
2783
2784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2785 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2786
2787 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2788 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2789 }
2790 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2791 {
2792 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2793 char extra[32];
2794 tANI_U8 len = 0;
2795
2796 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002797 len = scnprintf(extra, sizeof(extra), "%s %d",
2798 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002799 if (copy_to_user(priv_data.buf, &extra, len + 1))
2800 {
2801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2802 "%s: failed to copy data to user buffer", __func__);
2803 ret = -EFAULT;
2804 goto exit;
2805 }
2806 }
2807 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2808 {
2809 tANI_U8 *value = command;
2810 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2811
2812 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2813 value = value + 16;
2814 /* Convert the value from ascii to integer */
2815 ret = kstrtou16(value, 10, &val);
2816 if (ret < 0)
2817 {
2818 /* If the input value is greater than max value of datatype, then also
2819 kstrtou16 fails */
2820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2821 "%s: kstrtou16 failed range [%d - %d]", __func__,
2822 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2823 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2824 ret = -EINVAL;
2825 goto exit;
2826 }
2827
2828 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2829 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2830 {
2831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2832 "scan home time value %d is out of range"
2833 " (Min: %d Max: %d)", val,
2834 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2835 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
2839
2840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2841 "%s: Received Command to change scan home time = %d", __func__, val);
2842
2843 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2844 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2845 }
2846 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2847 {
2848 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2849 char extra[32];
2850 tANI_U8 len = 0;
2851
2852 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002853 len = scnprintf(extra, sizeof(extra), "%s %d",
2854 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002855 if (copy_to_user(priv_data.buf, &extra, len + 1))
2856 {
2857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2858 "%s: failed to copy data to user buffer", __func__);
2859 ret = -EFAULT;
2860 goto exit;
2861 }
2862 }
2863 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2864 {
2865 tANI_U8 *value = command;
2866 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2867
2868 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2869 value = value + 17;
2870 /* Convert the value from ascii to integer */
2871 ret = kstrtou8(value, 10, &val);
2872 if (ret < 0)
2873 {
2874 /* If the input value is greater than max value of datatype, then also
2875 kstrtou8 fails */
2876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2877 "%s: kstrtou8 failed range [%d - %d]", __func__,
2878 CFG_ROAM_INTRA_BAND_MIN,
2879 CFG_ROAM_INTRA_BAND_MAX);
2880 ret = -EINVAL;
2881 goto exit;
2882 }
2883
2884 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2885 (val > CFG_ROAM_INTRA_BAND_MAX))
2886 {
2887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2888 "intra band mode value %d is out of range"
2889 " (Min: %d Max: %d)", val,
2890 CFG_ROAM_INTRA_BAND_MIN,
2891 CFG_ROAM_INTRA_BAND_MAX);
2892 ret = -EINVAL;
2893 goto exit;
2894 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2896 "%s: Received Command to change intra band = %d", __func__, val);
2897
2898 pHddCtx->cfg_ini->nRoamIntraBand = val;
2899 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2900 }
2901 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2902 {
2903 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2904 char extra[32];
2905 tANI_U8 len = 0;
2906
2907 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002908 len = scnprintf(extra, sizeof(extra), "%s %d",
2909 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002910 if (copy_to_user(priv_data.buf, &extra, len + 1))
2911 {
2912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2913 "%s: failed to copy data to user buffer", __func__);
2914 ret = -EFAULT;
2915 goto exit;
2916 }
2917 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002918 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2919 {
2920 tANI_U8 *value = command;
2921 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2922
2923 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2924 value = value + 15;
2925 /* Convert the value from ascii to integer */
2926 ret = kstrtou8(value, 10, &nProbes);
2927 if (ret < 0)
2928 {
2929 /* If the input value is greater than max value of datatype, then also
2930 kstrtou8 fails */
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2932 "%s: kstrtou8 failed range [%d - %d]", __func__,
2933 CFG_ROAM_SCAN_N_PROBES_MIN,
2934 CFG_ROAM_SCAN_N_PROBES_MAX);
2935 ret = -EINVAL;
2936 goto exit;
2937 }
2938
2939 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2940 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2941 {
2942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "NProbes value %d is out of range"
2944 " (Min: %d Max: %d)", nProbes,
2945 CFG_ROAM_SCAN_N_PROBES_MIN,
2946 CFG_ROAM_SCAN_N_PROBES_MAX);
2947 ret = -EINVAL;
2948 goto exit;
2949 }
2950
2951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2952 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2953
2954 pHddCtx->cfg_ini->nProbes = nProbes;
2955 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2956 }
2957 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2958 {
2959 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2960 char extra[32];
2961 tANI_U8 len = 0;
2962
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002963 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002964 if (copy_to_user(priv_data.buf, &extra, len + 1))
2965 {
2966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2967 "%s: failed to copy data to user buffer", __func__);
2968 ret = -EFAULT;
2969 goto exit;
2970 }
2971 }
2972 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2973 {
2974 tANI_U8 *value = command;
2975 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2976
2977 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2978 /* input value is in units of msec */
2979 value = value + 20;
2980 /* Convert the value from ascii to integer */
2981 ret = kstrtou16(value, 10, &homeAwayTime);
2982 if (ret < 0)
2983 {
2984 /* If the input value is greater than max value of datatype, then also
2985 kstrtou8 fails */
2986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2987 "%s: kstrtou8 failed range [%d - %d]", __func__,
2988 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2989 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2990 ret = -EINVAL;
2991 goto exit;
2992 }
2993
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002994 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2995 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2996 {
2997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2998 "homeAwayTime value %d is out of range"
2999 " (Min: %d Max: %d)", homeAwayTime,
3000 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3001 CFG_ROAM_SCAN_HOME_AWAY_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 Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003008 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3009 {
3010 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3011 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3012 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003013 }
3014 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3015 {
3016 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3017 char extra[32];
3018 tANI_U8 len = 0;
3019
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003020 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -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, "REASSOC", 7) == 0)
3030 {
3031 tANI_U8 *value = command;
3032 tANI_U8 channel = 0;
3033 tSirMacAddr targetApBssid;
3034 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003035#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3036 tCsrHandoffRequest handoffInfo;
3037#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003038 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003039 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3040
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003041 /* if not associated, no need to proceed with reassoc */
3042 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3043 {
3044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3045 ret = -EINVAL;
3046 goto exit;
3047 }
3048
3049 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3050 if (eHAL_STATUS_SUCCESS != status)
3051 {
3052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3053 "%s: Failed to parse reassoc command data", __func__);
3054 ret = -EINVAL;
3055 goto exit;
3056 }
3057
3058 /* if the target bssid is same as currently associated AP,
3059 then no need to proceed with reassoc */
3060 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3061 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3062 {
3063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067
3068 /* Check channel number is a valid channel number */
3069 if(VOS_STATUS_SUCCESS !=
3070 wlan_hdd_validate_operation_channel(pAdapter, channel))
3071 {
3072 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003073 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003074 return -EINVAL;
3075 }
3076
3077 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003078#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3079 handoffInfo.channel = channel;
3080 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3081 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3082#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003083 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003084 else if (strncmp(command, "SETWESMODE", 10) == 0)
3085 {
3086 tANI_U8 *value = command;
3087 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3088
3089 /* Move pointer to ahead of SETWESMODE<delimiter> */
3090 value = value + 11;
3091 /* Convert the value from ascii to integer */
3092 ret = kstrtou8(value, 10, &wesMode);
3093 if (ret < 0)
3094 {
3095 /* If the input value is greater than max value of datatype, then also
3096 kstrtou8 fails */
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3098 "%s: kstrtou8 failed range [%d - %d]", __func__,
3099 CFG_ENABLE_WES_MODE_NAME_MIN,
3100 CFG_ENABLE_WES_MODE_NAME_MAX);
3101 ret = -EINVAL;
3102 goto exit;
3103 }
3104
3105 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3106 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3107 {
3108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3109 "WES Mode value %d is out of range"
3110 " (Min: %d Max: %d)", wesMode,
3111 CFG_ENABLE_WES_MODE_NAME_MIN,
3112 CFG_ENABLE_WES_MODE_NAME_MAX);
3113 ret = -EINVAL;
3114 goto exit;
3115 }
3116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3117 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3118
3119 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3120 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3121 }
3122 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3123 {
3124 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3125 char extra[32];
3126 tANI_U8 len = 0;
3127
Arif Hussain826d9412013-11-12 16:44:54 -08003128 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003129 if (copy_to_user(priv_data.buf, &extra, len + 1))
3130 {
3131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3132 "%s: failed to copy data to user buffer", __func__);
3133 ret = -EFAULT;
3134 goto exit;
3135 }
3136 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003137#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003138#ifdef FEATURE_WLAN_LFR
3139 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3140 {
3141 tANI_U8 *value = command;
3142 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3143
3144 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3145 value = value + 12;
3146 /* Convert the value from ascii to integer */
3147 ret = kstrtou8(value, 10, &lfrMode);
3148 if (ret < 0)
3149 {
3150 /* If the input value is greater than max value of datatype, then also
3151 kstrtou8 fails */
3152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3153 "%s: kstrtou8 failed range [%d - %d]", __func__,
3154 CFG_LFR_FEATURE_ENABLED_MIN,
3155 CFG_LFR_FEATURE_ENABLED_MAX);
3156 ret = -EINVAL;
3157 goto exit;
3158 }
3159
3160 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3161 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3162 {
3163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3164 "lfr mode value %d is out of range"
3165 " (Min: %d Max: %d)", lfrMode,
3166 CFG_LFR_FEATURE_ENABLED_MIN,
3167 CFG_LFR_FEATURE_ENABLED_MAX);
3168 ret = -EINVAL;
3169 goto exit;
3170 }
3171
3172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3173 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3174
3175 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3176 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3177 }
3178#endif
3179#ifdef WLAN_FEATURE_VOWIFI_11R
3180 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3181 {
3182 tANI_U8 *value = command;
3183 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3184
3185 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3186 value = value + 18;
3187 /* Convert the value from ascii to integer */
3188 ret = kstrtou8(value, 10, &ft);
3189 if (ret < 0)
3190 {
3191 /* If the input value is greater than max value of datatype, then also
3192 kstrtou8 fails */
3193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3194 "%s: kstrtou8 failed range [%d - %d]", __func__,
3195 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3196 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3197 ret = -EINVAL;
3198 goto exit;
3199 }
3200
3201 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3202 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3203 {
3204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3205 "ft mode value %d is out of range"
3206 " (Min: %d Max: %d)", ft,
3207 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3208 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3209 ret = -EINVAL;
3210 goto exit;
3211 }
3212
3213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3214 "%s: Received Command to change ft mode = %d", __func__, ft);
3215
3216 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3217 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3218 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303219
3220 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3221 {
3222 tANI_U8 *value = command;
3223 tSirMacAddr targetApBssid;
3224 tANI_U8 trigger = 0;
3225 eHalStatus status = eHAL_STATUS_SUCCESS;
3226 hdd_station_ctx_t *pHddStaCtx = NULL;
3227 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3228
3229 /* if not associated, no need to proceed with reassoc */
3230 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3231 {
3232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3233 ret = -EINVAL;
3234 goto exit;
3235 }
3236
3237 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3238 if (eHAL_STATUS_SUCCESS != status)
3239 {
3240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3241 "%s: Failed to parse reassoc command data", __func__);
3242 ret = -EINVAL;
3243 goto exit;
3244 }
3245
3246 /* if the target bssid is same as currently associated AP,
3247 then no need to proceed with reassoc */
3248 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3249 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3250 {
3251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3252 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3253 __func__);
3254 ret = -EINVAL;
3255 goto exit;
3256 }
3257
3258 /* Proceed with scan/roam */
3259 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3260 &targetApBssid[0],
3261 (tSmeFastRoamTrigger)(trigger));
3262 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003263#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003264#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003265 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3266 {
3267 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003268 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003269
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003270 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003271 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003272 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003273 hdd_is_okc_mode_enabled(pHddCtx) &&
3274 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3275 {
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003277 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003278 " hence this operation is not permitted!", __func__);
3279 ret = -EPERM;
3280 goto exit;
3281 }
3282
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003283 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3284 value = value + 11;
3285 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003286 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003287 if (ret < 0)
3288 {
3289 /* If the input value is greater than max value of datatype, then also
3290 kstrtou8 fails */
3291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3292 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003293 CFG_ESE_FEATURE_ENABLED_MIN,
3294 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003295 ret = -EINVAL;
3296 goto exit;
3297 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003298 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3299 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003300 {
3301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003302 "Ese mode value %d is out of range"
3303 " (Min: %d Max: %d)", eseMode,
3304 CFG_ESE_FEATURE_ENABLED_MIN,
3305 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003306 ret = -EINVAL;
3307 goto exit;
3308 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003310 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003311
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003312 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3313 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003314 }
3315#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003316 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3317 {
3318 tANI_U8 *value = command;
3319 tANI_BOOLEAN roamScanControl = 0;
3320
3321 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3322 value = value + 19;
3323 /* Convert the value from ascii to integer */
3324 ret = kstrtou8(value, 10, &roamScanControl);
3325 if (ret < 0)
3326 {
3327 /* If the input value is greater than max value of datatype, then also
3328 kstrtou8 fails */
3329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3330 "%s: kstrtou8 failed ", __func__);
3331 ret = -EINVAL;
3332 goto exit;
3333 }
3334
3335 if (0 != roamScanControl)
3336 {
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3338 "roam scan control invalid value = %d",
3339 roamScanControl);
3340 ret = -EINVAL;
3341 goto exit;
3342 }
3343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3344 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3345
3346 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3347 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003348#ifdef FEATURE_WLAN_OKC
3349 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3350 {
3351 tANI_U8 *value = command;
3352 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3353
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003354 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003355 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003356 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003357 hdd_is_okc_mode_enabled(pHddCtx) &&
3358 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3359 {
3360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003361 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003362 " hence this operation is not permitted!", __func__);
3363 ret = -EPERM;
3364 goto exit;
3365 }
3366
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003367 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3368 value = value + 11;
3369 /* Convert the value from ascii to integer */
3370 ret = kstrtou8(value, 10, &okcMode);
3371 if (ret < 0)
3372 {
3373 /* If the input value is greater than max value of datatype, then also
3374 kstrtou8 fails */
3375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3376 "%s: kstrtou8 failed range [%d - %d]", __func__,
3377 CFG_OKC_FEATURE_ENABLED_MIN,
3378 CFG_OKC_FEATURE_ENABLED_MAX);
3379 ret = -EINVAL;
3380 goto exit;
3381 }
3382
3383 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3384 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3385 {
3386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3387 "Okc mode value %d is out of range"
3388 " (Min: %d Max: %d)", okcMode,
3389 CFG_OKC_FEATURE_ENABLED_MIN,
3390 CFG_OKC_FEATURE_ENABLED_MAX);
3391 ret = -EINVAL;
3392 goto exit;
3393 }
3394
3395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3396 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3397
3398 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3399 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003400#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003401 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3402 {
3403 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3404 char extra[32];
3405 tANI_U8 len = 0;
3406
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003407 len = scnprintf(extra, sizeof(extra), "%s %d",
3408 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003409 if (copy_to_user(priv_data.buf, &extra, len + 1))
3410 {
3411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3412 "%s: failed to copy data to user buffer", __func__);
3413 ret = -EFAULT;
3414 goto exit;
3415 }
3416 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303417#ifdef WLAN_FEATURE_PACKET_FILTERING
3418 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3419 {
3420 tANI_U8 filterType = 0;
3421 tANI_U8 *value = command;
3422
3423 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3424 value = value + 22;
3425
3426 /* Convert the value from ascii to integer */
3427 ret = kstrtou8(value, 10, &filterType);
3428 if (ret < 0)
3429 {
3430 /* If the input value is greater than max value of datatype,
3431 * then also kstrtou8 fails
3432 */
3433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3434 "%s: kstrtou8 failed range ", __func__);
3435 ret = -EINVAL;
3436 goto exit;
3437 }
3438
3439 if (filterType != 0 && filterType != 1)
3440 {
3441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3442 "%s: Accepted Values are 0 and 1 ", __func__);
3443 ret = -EINVAL;
3444 goto exit;
3445 }
3446 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3447 pAdapter->sessionId);
3448 }
3449#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303450 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3451 {
3452 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303453 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303454 if ('1' == *dhcpPhase)
3455 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu0b0cab72014-02-13 21:52:40 +05303457 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303458
3459 pHddCtx->btCoexModeSet = TRUE;
3460
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303461 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
c_hpothu0b0cab72014-02-13 21:52:40 +05303462 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303463 }
3464 else if ('2' == *dhcpPhase)
3465 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu0b0cab72014-02-13 21:52:40 +05303467 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303468
3469 pHddCtx->btCoexModeSet = FALSE;
3470
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303471 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
c_hpothu0b0cab72014-02-13 21:52:40 +05303472 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303473 }
3474 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003475 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3476 {
3477 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3478 }
3479 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3480 {
3481 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3482 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303483 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3484 {
3485 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3486 char extra[32];
3487 tANI_U8 len = 0;
3488
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003489 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303490 (int)pCfg->nActiveMaxChnTime);
3491 if (copy_to_user(priv_data.buf, &extra, len + 1))
3492 {
3493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3494 "%s: failed to copy data to user buffer", __func__);
3495 ret = -EFAULT;
3496 goto exit;
3497 }
3498 ret = len;
3499 }
3500 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3501 {
3502 tANI_U8 *value = command;
3503 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3504 int val = 0, temp;
3505
3506 value = value + 13;
3507 temp = kstrtou32(value, 10, &val);
3508 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3509 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3513 ret = -EFAULT;
3514 goto exit;
3515 }
3516 pCfg->nActiveMaxChnTime = val;
3517 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003518 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3519 {
3520 tANI_U8 filterType = 0;
3521 tANI_U8 *value;
3522 value = command + 9;
3523
3524 /* Convert the value from ascii to integer */
3525 ret = kstrtou8(value, 10, &filterType);
3526 if (ret < 0)
3527 {
3528 /* If the input value is greater than max value of datatype,
3529 * then also kstrtou8 fails
3530 */
3531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3532 "%s: kstrtou8 failed range ", __func__);
3533 ret = -EINVAL;
3534 goto exit;
3535 }
3536 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3537 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3538 {
3539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3540 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3541 " 2-Sink ", __func__);
3542 ret = -EINVAL;
3543 goto exit;
3544 }
3545 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3546 pHddCtx->drvr_miracast = filterType;
3547 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3548 }
Leo Chang614d2072013-08-22 14:59:44 -07003549 else if (strncmp(command, "SETMCRATE", 9) == 0)
3550 {
Leo Chang614d2072013-08-22 14:59:44 -07003551 tANI_U8 *value = command;
3552 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003553 tSirRateUpdateInd *rateUpdate;
3554 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003555
3556 /* Only valid for SAP mode */
3557 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3558 {
3559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3560 "%s: SAP mode is not running", __func__);
3561 ret = -EFAULT;
3562 goto exit;
3563 }
3564
3565 /* Move pointer to ahead of SETMCRATE<delimiter> */
3566 /* input value is in units of hundred kbps */
3567 value = value + 10;
3568 /* Convert the value from ascii to integer, decimal base */
3569 ret = kstrtouint(value, 10, &targetRate);
3570
Leo Chang1f98cbd2013-10-17 15:03:52 -07003571 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3572 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003573 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003574 hddLog(VOS_TRACE_LEVEL_ERROR,
3575 "%s: SETMCRATE indication alloc fail", __func__);
3576 ret = -EFAULT;
3577 goto exit;
3578 }
3579 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3580
3581 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3582 "MC Target rate %d", targetRate);
3583 /* Ignore unicast */
3584 rateUpdate->ucastDataRate = -1;
3585 rateUpdate->mcastDataRate24GHz = targetRate;
3586 rateUpdate->mcastDataRate5GHz = targetRate;
3587 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3588 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3589 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3590 if (eHAL_STATUS_SUCCESS != status)
3591 {
3592 hddLog(VOS_TRACE_LEVEL_ERROR,
3593 "%s: SET_MC_RATE failed", __func__);
3594 vos_mem_free(rateUpdate);
3595 ret = -EFAULT;
3596 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003597 }
3598 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303599#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003600 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303601 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003602 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303603 }
3604#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003605#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003606 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3607 {
3608 tANI_U8 *value = command;
3609 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3610 tANI_U8 numChannels = 0;
3611 eHalStatus status = eHAL_STATUS_SUCCESS;
3612
3613 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3614 if (eHAL_STATUS_SUCCESS != status)
3615 {
3616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3617 "%s: Failed to parse channel list information", __func__);
3618 ret = -EINVAL;
3619 goto exit;
3620 }
3621
3622 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3623 {
3624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3625 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3626 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3627 ret = -EINVAL;
3628 goto exit;
3629 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003630 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003631 ChannelList,
3632 numChannels);
3633 if (eHAL_STATUS_SUCCESS != status)
3634 {
3635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3636 "%s: Failed to update channel list information", __func__);
3637 ret = -EINVAL;
3638 goto exit;
3639 }
3640 }
3641 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3642 {
3643 tANI_U8 *value = command;
3644 char extra[128] = {0};
3645 int len = 0;
3646 tANI_U8 tid = 0;
3647 hdd_station_ctx_t *pHddStaCtx = NULL;
3648 tAniTrafStrmMetrics tsmMetrics;
3649 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3650
3651 /* if not associated, return error */
3652 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3653 {
3654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3655 ret = -EINVAL;
3656 goto exit;
3657 }
3658
3659 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3660 value = value + 12;
3661 /* Convert the value from ascii to integer */
3662 ret = kstrtou8(value, 10, &tid);
3663 if (ret < 0)
3664 {
3665 /* If the input value is greater than max value of datatype, then also
3666 kstrtou8 fails */
3667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3668 "%s: kstrtou8 failed range [%d - %d]", __func__,
3669 TID_MIN_VALUE,
3670 TID_MAX_VALUE);
3671 ret = -EINVAL;
3672 goto exit;
3673 }
3674
3675 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3676 {
3677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3678 "tid value %d is out of range"
3679 " (Min: %d Max: %d)", tid,
3680 TID_MIN_VALUE,
3681 TID_MAX_VALUE);
3682 ret = -EINVAL;
3683 goto exit;
3684 }
3685
3686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3687 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3688
3689 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3690 {
3691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3692 "%s: failed to get tsm stats", __func__);
3693 ret = -EFAULT;
3694 goto exit;
3695 }
3696
3697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3698 "UplinkPktQueueDly(%d)\n"
3699 "UplinkPktQueueDlyHist[0](%d)\n"
3700 "UplinkPktQueueDlyHist[1](%d)\n"
3701 "UplinkPktQueueDlyHist[2](%d)\n"
3702 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303703 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003704 "UplinkPktLoss(%d)\n"
3705 "UplinkPktCount(%d)\n"
3706 "RoamingCount(%d)\n"
3707 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3708 tsmMetrics.UplinkPktQueueDlyHist[0],
3709 tsmMetrics.UplinkPktQueueDlyHist[1],
3710 tsmMetrics.UplinkPktQueueDlyHist[2],
3711 tsmMetrics.UplinkPktQueueDlyHist[3],
3712 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3713 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3714
3715 /* Output TSM stats is of the format
3716 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3717 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003718 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003719 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3720 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3721 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3722 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3723 tsmMetrics.RoamingDly);
3724
3725 if (copy_to_user(priv_data.buf, &extra, len + 1))
3726 {
3727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3728 "%s: failed to copy data to user buffer", __func__);
3729 ret = -EFAULT;
3730 goto exit;
3731 }
3732 }
3733 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3734 {
3735 tANI_U8 *value = command;
3736 tANI_U8 *cckmIe = NULL;
3737 tANI_U8 cckmIeLen = 0;
3738 eHalStatus status = eHAL_STATUS_SUCCESS;
3739
3740 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3741 if (eHAL_STATUS_SUCCESS != status)
3742 {
3743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3744 "%s: Failed to parse cckm ie data", __func__);
3745 ret = -EINVAL;
3746 goto exit;
3747 }
3748
3749 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3750 {
3751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3752 "%s: CCKM Ie input length is more than max[%d]", __func__,
3753 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003754 vos_mem_free(cckmIe);
3755 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003756 ret = -EINVAL;
3757 goto exit;
3758 }
3759 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003760 vos_mem_free(cckmIe);
3761 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003762 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003763 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3764 {
3765 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003766 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003767 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003768 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003769 if (eHAL_STATUS_SUCCESS != status)
3770 {
3771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003772 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003773 ret = -EINVAL;
3774 goto exit;
3775 }
3776
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003777 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
3778 if (eHAL_STATUS_SUCCESS != status)
3779 {
3780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3781 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
3782 ret = -EINVAL;
3783 goto exit;
3784 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003785 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003786#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003787 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303788 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3789 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
3790 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003791 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3792 __func__, command);
3793 }
3794
Jeff Johnson295189b2012-06-20 16:38:30 -07003795 }
3796exit:
3797 if (command)
3798 {
3799 kfree(command);
3800 }
3801 return ret;
3802}
3803
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003804#ifdef CONFIG_COMPAT
3805static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
3806{
3807 struct {
3808 compat_uptr_t buf;
3809 int used_len;
3810 int total_len;
3811 } compat_priv_data;
3812 hdd_priv_data_t priv_data;
3813 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003814
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003815 /*
3816 * Note that pAdapter and ifr have already been verified by caller,
3817 * and HDD context has also been validated
3818 */
3819 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
3820 sizeof(compat_priv_data))) {
3821 ret = -EFAULT;
3822 goto exit;
3823 }
3824 priv_data.buf = compat_ptr(compat_priv_data.buf);
3825 priv_data.used_len = compat_priv_data.used_len;
3826 priv_data.total_len = compat_priv_data.total_len;
3827 ret = hdd_driver_command(pAdapter, &priv_data);
3828 exit:
3829 return ret;
3830}
3831#else /* CONFIG_COMPAT */
3832static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
3833{
3834 /* will never be invoked */
3835 return 0;
3836}
3837#endif /* CONFIG_COMPAT */
3838
3839static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
3840{
3841 hdd_priv_data_t priv_data;
3842 int ret = 0;
3843
3844 /*
3845 * Note that pAdapter and ifr have already been verified by caller,
3846 * and HDD context has also been validated
3847 */
3848 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
3849 ret = -EFAULT;
3850 } else {
3851 ret = hdd_driver_command(pAdapter, &priv_data);
3852 }
3853 return ret;
3854}
3855
3856int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3857{
3858 hdd_adapter_t *pAdapter;
3859 hdd_context_t *pHddCtx;
3860 int ret;
3861
3862 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3863 if (NULL == pAdapter) {
3864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3865 "%s: HDD adapter context is Null", __func__);
3866 ret = -ENODEV;
3867 goto exit;
3868 }
3869 if (dev != pAdapter->dev) {
3870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3871 "%s: HDD adapter/dev inconsistency", __func__);
3872 ret = -ENODEV;
3873 goto exit;
3874 }
3875
3876 if ((!ifr) || (!ifr->ifr_data)) {
3877 ret = -EINVAL;
3878 goto exit;
3879 }
3880
3881 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3882 ret = wlan_hdd_validate_context(pHddCtx);
3883 if (ret) {
3884 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3885 "%s: invalid context", __func__);
3886 ret = -EBUSY;
3887 goto exit;
3888 }
3889
3890 switch (cmd) {
3891 case (SIOCDEVPRIVATE + 1):
3892 if (is_compat_task())
3893 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
3894 else
3895 ret = hdd_driver_ioctl(pAdapter, ifr);
3896 break;
3897 default:
3898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
3899 __func__, cmd);
3900 ret = -EINVAL;
3901 break;
3902 }
3903 exit:
3904 return ret;
3905}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003906
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003907#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003908/**---------------------------------------------------------------------------
3909
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003910 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003911
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003912 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003913 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3914 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3915 <space>Scan Mode N<space>Meas Duration N
3916 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3917 then take N.
3918 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3919 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3920 This function does not take care of removing duplicate channels from the list
3921
3922 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003923 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003924
3925 \return - 0 for success non-zero for failure
3926
3927 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003928static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
3929 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003930{
3931 tANI_U8 *inPtr = pValue;
3932 int tempInt = 0;
3933 int j = 0, i = 0, v = 0;
3934 char buf[32];
3935
3936 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3937 /*no argument after the command*/
3938 if (NULL == inPtr)
3939 {
3940 return -EINVAL;
3941 }
3942 /*no space after the command*/
3943 else if (SPACE_ASCII_VALUE != *inPtr)
3944 {
3945 return -EINVAL;
3946 }
3947
3948 /*removing empty spaces*/
3949 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3950
3951 /*no argument followed by spaces*/
3952 if ('\0' == *inPtr) return -EINVAL;
3953
3954 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003955 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003956 if (1 != v) return -EINVAL;
3957
3958 v = kstrtos32(buf, 10, &tempInt);
3959 if ( v < 0) return -EINVAL;
3960
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003961 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003962
3963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003964 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003965
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003966 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003967 {
3968 for (i = 0; i < 4; i++)
3969 {
3970 /*inPtr pointing to the beginning of first space after number of ie fields*/
3971 inPtr = strpbrk( inPtr, " " );
3972 /*no ie data after the number of ie fields argument*/
3973 if (NULL == inPtr) return -EINVAL;
3974
3975 /*removing empty space*/
3976 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3977
3978 /*no ie data after the number of ie fields argument and spaces*/
3979 if ( '\0' == *inPtr ) return -EINVAL;
3980
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003981 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003982 if (1 != v) return -EINVAL;
3983
3984 v = kstrtos32(buf, 10, &tempInt);
3985 if (v < 0) return -EINVAL;
3986
3987 switch (i)
3988 {
3989 case 0: /* Measurement token */
3990 if (tempInt <= 0)
3991 {
3992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3993 "Invalid Measurement Token(%d)", tempInt);
3994 return -EINVAL;
3995 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003996 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003997 break;
3998
3999 case 1: /* Channel number */
4000 if ((tempInt <= 0) ||
4001 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4002 {
4003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4004 "Invalid Channel Number(%d)", tempInt);
4005 return -EINVAL;
4006 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004007 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004008 break;
4009
4010 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004011 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004012 {
4013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4014 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4015 return -EINVAL;
4016 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004017 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004018 break;
4019
4020 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004021 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4022 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004023 {
4024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4025 "Invalid Measurement Duration(%d)", tempInt);
4026 return -EINVAL;
4027 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004028 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004029 break;
4030 }
4031 }
4032 }
4033
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004034 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004035 {
4036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304037 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004038 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004039 pEseBcnReq->bcnReq[j].measurementToken,
4040 pEseBcnReq->bcnReq[j].channel,
4041 pEseBcnReq->bcnReq[j].scanMode,
4042 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004043 }
4044
4045 return VOS_STATUS_SUCCESS;
4046}
4047
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004048static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4049{
4050 struct statsContext *pStatsContext = NULL;
4051 hdd_adapter_t *pAdapter = NULL;
4052
4053 if (NULL == pContext)
4054 {
4055 hddLog(VOS_TRACE_LEVEL_ERROR,
4056 "%s: Bad param, pContext [%p]",
4057 __func__, pContext);
4058 return;
4059 }
4060
Jeff Johnson72a40512013-12-19 10:14:15 -08004061 /* there is a race condition that exists between this callback
4062 function and the caller since the caller could time out either
4063 before or while this code is executing. we use a spinlock to
4064 serialize these actions */
4065 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004066
4067 pStatsContext = pContext;
4068 pAdapter = pStatsContext->pAdapter;
4069 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4070 {
4071 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004072 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004073 hddLog(VOS_TRACE_LEVEL_WARN,
4074 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4075 __func__, pAdapter, pStatsContext->magic);
4076 return;
4077 }
4078
Jeff Johnson72a40512013-12-19 10:14:15 -08004079 /* context is valid so caller is still waiting */
4080
4081 /* paranoia: invalidate the magic */
4082 pStatsContext->magic = 0;
4083
4084 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004085 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4086 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4087 tsmMetrics.UplinkPktQueueDlyHist,
4088 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4089 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4090 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4091 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4092 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4093 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4094 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4095
Jeff Johnson72a40512013-12-19 10:14:15 -08004096 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004097 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004098
4099 /* serialization is complete */
4100 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004101}
4102
4103
4104
4105static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4106 tAniTrafStrmMetrics* pTsmMetrics)
4107{
4108 hdd_station_ctx_t *pHddStaCtx = NULL;
4109 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004110 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004111 long lrc;
4112 struct statsContext context;
4113 hdd_context_t *pHddCtx = NULL;
4114
4115 if (NULL == pAdapter)
4116 {
4117 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4118 return VOS_STATUS_E_FAULT;
4119 }
4120
4121 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4122 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4123
4124 /* we are connected prepare our callback context */
4125 init_completion(&context.completion);
4126 context.pAdapter = pAdapter;
4127 context.magic = STATS_CONTEXT_MAGIC;
4128
4129 /* query tsm stats */
4130 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4131 pHddStaCtx->conn_info.staId[ 0 ],
4132 pHddStaCtx->conn_info.bssId,
4133 &context, pHddCtx->pvosContext, tid);
4134
4135 if (eHAL_STATUS_SUCCESS != hstatus)
4136 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004137 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4138 __func__);
4139 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004140 }
4141 else
4142 {
4143 /* request was sent -- wait for the response */
4144 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4145 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004146 if (lrc <= 0)
4147 {
4148 hddLog(VOS_TRACE_LEVEL_ERROR,
4149 "%s: SME %s while retrieving statistics",
4150 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004151 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004152 }
4153 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004154
Jeff Johnson72a40512013-12-19 10:14:15 -08004155 /* either we never sent a request, we sent a request and received a
4156 response or we sent a request and timed out. if we never sent a
4157 request or if we sent a request and got a response, we want to
4158 clear the magic out of paranoia. if we timed out there is a
4159 race condition such that the callback function could be
4160 executing at the same time we are. of primary concern is if the
4161 callback function had already verified the "magic" but had not
4162 yet set the completion variable when a timeout occurred. we
4163 serialize these activities by invalidating the magic while
4164 holding a shared spinlock which will cause us to block if the
4165 callback is currently executing */
4166 spin_lock(&hdd_context_lock);
4167 context.magic = 0;
4168 spin_unlock(&hdd_context_lock);
4169
4170 if (VOS_STATUS_SUCCESS == vstatus)
4171 {
4172 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4173 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4174 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4175 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4176 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4177 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4178 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4179 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4180 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4181 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4182 }
4183 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004184}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004185#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004186
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004187#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004188void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4189{
4190 eCsrBand band = -1;
4191 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4192 switch (band)
4193 {
4194 case eCSR_BAND_ALL:
4195 *pBand = WLAN_HDD_UI_BAND_AUTO;
4196 break;
4197
4198 case eCSR_BAND_24:
4199 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4200 break;
4201
4202 case eCSR_BAND_5G:
4203 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4204 break;
4205
4206 default:
4207 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4208 *pBand = -1;
4209 break;
4210 }
4211}
4212
4213/**---------------------------------------------------------------------------
4214
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004215 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4216
4217 This function parses the send action frame data passed in the format
4218 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4219
Srinivas Girigowda56076852013-08-20 14:00:50 -07004220 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004221 \param - pTargetApBssid Pointer to target Ap bssid
4222 \param - pChannel Pointer to the Target AP channel
4223 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4224 \param - pBuf Pointer to data
4225 \param - pBufLen Pointer to data length
4226
4227 \return - 0 for success non-zero for failure
4228
4229 --------------------------------------------------------------------------*/
4230VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4231 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4232{
4233 tANI_U8 *inPtr = pValue;
4234 tANI_U8 *dataEnd;
4235 int tempInt;
4236 int j = 0;
4237 int i = 0;
4238 int v = 0;
4239 tANI_U8 tempBuf[32];
4240 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004241 /* 12 hexa decimal digits, 5 ':' and '\0' */
4242 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004243
4244 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4245 /*no argument after the command*/
4246 if (NULL == inPtr)
4247 {
4248 return -EINVAL;
4249 }
4250
4251 /*no space after the command*/
4252 else if (SPACE_ASCII_VALUE != *inPtr)
4253 {
4254 return -EINVAL;
4255 }
4256
4257 /*removing empty spaces*/
4258 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4259
4260 /*no argument followed by spaces*/
4261 if ('\0' == *inPtr)
4262 {
4263 return -EINVAL;
4264 }
4265
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004266 v = sscanf(inPtr, "%17s", macAddress);
4267 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004268 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4270 "Invalid MAC address or All hex inputs are not read (%d)", v);
4271 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004272 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004273
4274 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4275 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4276 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4277 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4278 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4279 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004280
4281 /* point to the next argument */
4282 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4283 /*no argument after the command*/
4284 if (NULL == inPtr) return -EINVAL;
4285
4286 /*removing empty spaces*/
4287 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4288
4289 /*no argument followed by spaces*/
4290 if ('\0' == *inPtr)
4291 {
4292 return -EINVAL;
4293 }
4294
4295 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004296 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004297 if (1 != v) return -EINVAL;
4298
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004299 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304300 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304301 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004302
4303 *pChannel = tempInt;
4304
4305 /* point to the next argument */
4306 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4307 /*no argument after the command*/
4308 if (NULL == inPtr) return -EINVAL;
4309 /*removing empty spaces*/
4310 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4311
4312 /*no argument followed by spaces*/
4313 if ('\0' == *inPtr)
4314 {
4315 return -EINVAL;
4316 }
4317
4318 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004319 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004320 if (1 != v) return -EINVAL;
4321
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004322 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004323 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004324
4325 *pDwellTime = tempInt;
4326
4327 /* point to the next argument */
4328 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4329 /*no argument after the command*/
4330 if (NULL == inPtr) return -EINVAL;
4331 /*removing empty spaces*/
4332 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4333
4334 /*no argument followed by spaces*/
4335 if ('\0' == *inPtr)
4336 {
4337 return -EINVAL;
4338 }
4339
4340 /* find the length of data */
4341 dataEnd = inPtr;
4342 while(('\0' != *dataEnd) )
4343 {
4344 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004345 }
Kiet Lambe150c22013-11-21 16:30:32 +05304346 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004347 if ( *pBufLen <= 0) return -EINVAL;
4348
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004349 /* Allocate the number of bytes based on the number of input characters
4350 whether it is even or odd.
4351 if the number of input characters are even, then we need N/2 byte.
4352 if the number of input characters are odd, then we need do (N+1)/2 to
4353 compensate rounding off.
4354 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4355 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4356 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004357 if (NULL == *pBuf)
4358 {
4359 hddLog(VOS_TRACE_LEVEL_FATAL,
4360 "%s: vos_mem_alloc failed ", __func__);
4361 return -EINVAL;
4362 }
4363
4364 /* the buffer received from the upper layer is character buffer,
4365 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4366 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4367 and f0 in 3rd location */
4368 for (i = 0, j = 0; j < *pBufLen; j += 2)
4369 {
Kiet Lambe150c22013-11-21 16:30:32 +05304370 if( j+1 == *pBufLen)
4371 {
4372 tempByte = hdd_parse_hex(inPtr[j]);
4373 }
4374 else
4375 {
4376 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4377 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004378 (*pBuf)[i++] = tempByte;
4379 }
4380 *pBufLen = i;
4381 return VOS_STATUS_SUCCESS;
4382}
4383
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004384/**---------------------------------------------------------------------------
4385
Srinivas Girigowdade697412013-02-14 16:31:48 -08004386 \brief hdd_parse_channellist() - HDD Parse channel list
4387
4388 This function parses the channel list passed in the format
4389 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004390 if the Number of channels (N) does not match with the actual number of channels passed
4391 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4392 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4393 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4394 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004395
4396 \param - pValue Pointer to input channel list
4397 \param - ChannelList Pointer to local output array to record channel list
4398 \param - pNumChannels Pointer to number of roam scan channels
4399
4400 \return - 0 for success non-zero for failure
4401
4402 --------------------------------------------------------------------------*/
4403VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4404{
4405 tANI_U8 *inPtr = pValue;
4406 int tempInt;
4407 int j = 0;
4408 int v = 0;
4409 char buf[32];
4410
4411 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4412 /*no argument after the command*/
4413 if (NULL == inPtr)
4414 {
4415 return -EINVAL;
4416 }
4417
4418 /*no space after the command*/
4419 else if (SPACE_ASCII_VALUE != *inPtr)
4420 {
4421 return -EINVAL;
4422 }
4423
4424 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004425 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004426
4427 /*no argument followed by spaces*/
4428 if ('\0' == *inPtr)
4429 {
4430 return -EINVAL;
4431 }
4432
4433 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004434 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004435 if (1 != v) return -EINVAL;
4436
Srinivas Girigowdade697412013-02-14 16:31:48 -08004437 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004438 if ((v < 0) ||
4439 (tempInt <= 0) ||
4440 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4441 {
4442 return -EINVAL;
4443 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004444
4445 *pNumChannels = tempInt;
4446
4447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4448 "Number of channels are: %d", *pNumChannels);
4449
4450 for (j = 0; j < (*pNumChannels); j++)
4451 {
4452 /*inPtr pointing to the beginning of first space after number of channels*/
4453 inPtr = strpbrk( inPtr, " " );
4454 /*no channel list after the number of channels argument*/
4455 if (NULL == inPtr)
4456 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004457 if (0 != j)
4458 {
4459 *pNumChannels = j;
4460 return VOS_STATUS_SUCCESS;
4461 }
4462 else
4463 {
4464 return -EINVAL;
4465 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004466 }
4467
4468 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004469 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004470
4471 /*no channel list after the number of channels argument and spaces*/
4472 if ( '\0' == *inPtr )
4473 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004474 if (0 != j)
4475 {
4476 *pNumChannels = j;
4477 return VOS_STATUS_SUCCESS;
4478 }
4479 else
4480 {
4481 return -EINVAL;
4482 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004483 }
4484
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004485 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004486 if (1 != v) return -EINVAL;
4487
Srinivas Girigowdade697412013-02-14 16:31:48 -08004488 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004489 if ((v < 0) ||
4490 (tempInt <= 0) ||
4491 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4492 {
4493 return -EINVAL;
4494 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004495 pChannelList[j] = tempInt;
4496
4497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4498 "Channel %d added to preferred channel list",
4499 pChannelList[j] );
4500 }
4501
Srinivas Girigowdade697412013-02-14 16:31:48 -08004502 return VOS_STATUS_SUCCESS;
4503}
4504
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004505
4506/**---------------------------------------------------------------------------
4507
4508 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4509
4510 This function parses the reasoc command data passed in the format
4511 REASSOC<space><bssid><space><channel>
4512
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004513 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004514 \param - pTargetApBssid Pointer to target Ap bssid
4515 \param - pChannel Pointer to the Target AP channel
4516
4517 \return - 0 for success non-zero for failure
4518
4519 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004520VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4521 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004522{
4523 tANI_U8 *inPtr = pValue;
4524 int tempInt;
4525 int v = 0;
4526 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004527 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004528 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004529
4530 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4531 /*no argument after the command*/
4532 if (NULL == inPtr)
4533 {
4534 return -EINVAL;
4535 }
4536
4537 /*no space after the command*/
4538 else if (SPACE_ASCII_VALUE != *inPtr)
4539 {
4540 return -EINVAL;
4541 }
4542
4543 /*removing empty spaces*/
4544 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4545
4546 /*no argument followed by spaces*/
4547 if ('\0' == *inPtr)
4548 {
4549 return -EINVAL;
4550 }
4551
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004552 v = sscanf(inPtr, "%17s", macAddress);
4553 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004554 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4556 "Invalid MAC address or All hex inputs are not read (%d)", v);
4557 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004558 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004559
4560 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4561 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4562 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4563 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4564 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4565 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004566
4567 /* point to the next argument */
4568 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4569 /*no argument after the command*/
4570 if (NULL == inPtr) return -EINVAL;
4571
4572 /*removing empty spaces*/
4573 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4574
4575 /*no argument followed by spaces*/
4576 if ('\0' == *inPtr)
4577 {
4578 return -EINVAL;
4579 }
4580
4581 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004582 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004583 if (1 != v) return -EINVAL;
4584
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004585 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004586 if ((v < 0) ||
4587 (tempInt <= 0) ||
4588 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4589 {
4590 return -EINVAL;
4591 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004592
4593 *pChannel = tempInt;
4594 return VOS_STATUS_SUCCESS;
4595}
4596
4597#endif
4598
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004599#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004600/**---------------------------------------------------------------------------
4601
4602 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4603
4604 This function parses the SETCCKM IE command
4605 SETCCKMIE<space><ie data>
4606
4607 \param - pValue Pointer to input data
4608 \param - pCckmIe Pointer to output cckm Ie
4609 \param - pCckmIeLen Pointer to output cckm ie length
4610
4611 \return - 0 for success non-zero for failure
4612
4613 --------------------------------------------------------------------------*/
4614VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4615 tANI_U8 *pCckmIeLen)
4616{
4617 tANI_U8 *inPtr = pValue;
4618 tANI_U8 *dataEnd;
4619 int j = 0;
4620 int i = 0;
4621 tANI_U8 tempByte = 0;
4622
4623 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4624 /*no argument after the command*/
4625 if (NULL == inPtr)
4626 {
4627 return -EINVAL;
4628 }
4629
4630 /*no space after the command*/
4631 else if (SPACE_ASCII_VALUE != *inPtr)
4632 {
4633 return -EINVAL;
4634 }
4635
4636 /*removing empty spaces*/
4637 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4638
4639 /*no argument followed by spaces*/
4640 if ('\0' == *inPtr)
4641 {
4642 return -EINVAL;
4643 }
4644
4645 /* find the length of data */
4646 dataEnd = inPtr;
4647 while(('\0' != *dataEnd) )
4648 {
4649 dataEnd++;
4650 ++(*pCckmIeLen);
4651 }
4652 if ( *pCckmIeLen <= 0) return -EINVAL;
4653
4654 /* Allocate the number of bytes based on the number of input characters
4655 whether it is even or odd.
4656 if the number of input characters are even, then we need N/2 byte.
4657 if the number of input characters are odd, then we need do (N+1)/2 to
4658 compensate rounding off.
4659 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4660 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4661 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4662 if (NULL == *pCckmIe)
4663 {
4664 hddLog(VOS_TRACE_LEVEL_FATAL,
4665 "%s: vos_mem_alloc failed ", __func__);
4666 return -EINVAL;
4667 }
4668 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4669 /* the buffer received from the upper layer is character buffer,
4670 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4671 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4672 and f0 in 3rd location */
4673 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4674 {
4675 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4676 (*pCckmIe)[i++] = tempByte;
4677 }
4678 *pCckmIeLen = i;
4679
4680 return VOS_STATUS_SUCCESS;
4681}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004682#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004683
Jeff Johnson295189b2012-06-20 16:38:30 -07004684/**---------------------------------------------------------------------------
4685
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004686 \brief hdd_is_valid_mac_address() - Validate MAC address
4687
4688 This function validates whether the given MAC address is valid or not
4689 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4690 where X is the hexa decimal digit character and separated by ':'
4691 This algorithm works even if MAC address is not separated by ':'
4692
4693 This code checks given input string mac contains exactly 12 hexadecimal digits.
4694 and a separator colon : appears in the input string only after
4695 an even number of hex digits.
4696
4697 \param - pMacAddr pointer to the input MAC address
4698 \return - 1 for valid and 0 for invalid
4699
4700 --------------------------------------------------------------------------*/
4701
4702v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4703{
4704 int xdigit = 0;
4705 int separator = 0;
4706 while (*pMacAddr)
4707 {
4708 if (isxdigit(*pMacAddr))
4709 {
4710 xdigit++;
4711 }
4712 else if (':' == *pMacAddr)
4713 {
4714 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4715 break;
4716
4717 ++separator;
4718 }
4719 else
4720 {
4721 separator = -1;
4722 /* Invalid MAC found */
4723 return 0;
4724 }
4725 ++pMacAddr;
4726 }
4727 return (xdigit == 12 && (separator == 5 || separator == 0));
4728}
4729
4730/**---------------------------------------------------------------------------
4731
Jeff Johnson295189b2012-06-20 16:38:30 -07004732 \brief hdd_open() - HDD Open function
4733
4734 This is called in response to ifconfig up
4735
4736 \param - dev Pointer to net_device structure
4737
4738 \return - 0 for success non-zero for failure
4739
4740 --------------------------------------------------------------------------*/
4741int hdd_open (struct net_device *dev)
4742{
4743 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4744 hdd_context_t *pHddCtx;
4745 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4746 VOS_STATUS status;
4747 v_BOOL_t in_standby = TRUE;
4748
4749 if (NULL == pAdapter)
4750 {
4751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304752 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 return -ENODEV;
4754 }
4755
4756 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304757 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
4758 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07004759 if (NULL == pHddCtx)
4760 {
4761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004762 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004763 return -ENODEV;
4764 }
4765
4766 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4767 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4768 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004769 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4770 {
4771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304772 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004773 in_standby = FALSE;
4774 break;
4775 }
4776 else
4777 {
4778 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4779 pAdapterNode = pNext;
4780 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 }
4782
4783 if (TRUE == in_standby)
4784 {
4785 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4786 {
4787 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4788 "wlan out of power save", __func__);
4789 return -EINVAL;
4790 }
4791 }
4792
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004793 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4795 {
4796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004797 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004798 /* Enable TX queues only when we are connected */
4799 netif_tx_start_all_queues(dev);
4800 }
4801
4802 return 0;
4803}
4804
4805int hdd_mon_open (struct net_device *dev)
4806{
4807 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4808
4809 if(pAdapter == NULL) {
4810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004811 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004812 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 }
4814
4815 netif_start_queue(dev);
4816
4817 return 0;
4818}
4819/**---------------------------------------------------------------------------
4820
4821 \brief hdd_stop() - HDD stop function
4822
4823 This is called in response to ifconfig down
4824
4825 \param - dev Pointer to net_device structure
4826
4827 \return - 0 for success non-zero for failure
4828
4829 --------------------------------------------------------------------------*/
4830
4831int hdd_stop (struct net_device *dev)
4832{
4833 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4834 hdd_context_t *pHddCtx;
4835 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4836 VOS_STATUS status;
4837 v_BOOL_t enter_standby = TRUE;
4838
4839 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 if (NULL == pAdapter)
4841 {
4842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304843 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 return -ENODEV;
4845 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304846 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
4847 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07004848 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4849 if (NULL == pHddCtx)
4850 {
4851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004852 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004853 return -ENODEV;
4854 }
4855
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004856 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4858 netif_tx_disable(pAdapter->dev);
4859 netif_carrier_off(pAdapter->dev);
4860
4861
4862 /* SoftAP ifaces should never go in power save mode
4863 making sure same here. */
4864 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4865 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004867 )
4868 {
4869 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4871 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004872 EXIT();
4873 return 0;
4874 }
4875
4876 /* Find if any iface is up then
4877 if any iface is up then can't put device to sleep/ power save mode. */
4878 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4879 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4880 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004881 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4882 {
4883 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304884 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004885 enter_standby = FALSE;
4886 break;
4887 }
4888 else
4889 {
4890 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4891 pAdapterNode = pNext;
4892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 }
4894
4895 if (TRUE == enter_standby)
4896 {
4897 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4898 "entering standby", __func__);
4899 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4900 {
4901 /*log and return success*/
4902 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4903 "wlan in power save", __func__);
4904 }
4905 }
4906
4907 EXIT();
4908 return 0;
4909}
4910
4911/**---------------------------------------------------------------------------
4912
4913 \brief hdd_uninit() - HDD uninit function
4914
4915 This is called during the netdev unregister to uninitialize all data
4916associated with the device
4917
4918 \param - dev Pointer to net_device structure
4919
4920 \return - void
4921
4922 --------------------------------------------------------------------------*/
4923static void hdd_uninit (struct net_device *dev)
4924{
4925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4926
4927 ENTER();
4928
4929 do
4930 {
4931 if (NULL == pAdapter)
4932 {
4933 hddLog(VOS_TRACE_LEVEL_FATAL,
4934 "%s: NULL pAdapter", __func__);
4935 break;
4936 }
4937
4938 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4939 {
4940 hddLog(VOS_TRACE_LEVEL_FATAL,
4941 "%s: Invalid magic", __func__);
4942 break;
4943 }
4944
4945 if (NULL == pAdapter->pHddCtx)
4946 {
4947 hddLog(VOS_TRACE_LEVEL_FATAL,
4948 "%s: NULL pHddCtx", __func__);
4949 break;
4950 }
4951
4952 if (dev != pAdapter->dev)
4953 {
4954 hddLog(VOS_TRACE_LEVEL_FATAL,
4955 "%s: Invalid device reference", __func__);
4956 /* we haven't validated all cases so let this go for now */
4957 }
4958
4959 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4960
4961 /* after uninit our adapter structure will no longer be valid */
4962 pAdapter->dev = NULL;
4963 pAdapter->magic = 0;
4964 } while (0);
4965
4966 EXIT();
4967}
4968
4969/**---------------------------------------------------------------------------
4970
4971 \brief hdd_release_firmware() -
4972
4973 This function calls the release firmware API to free the firmware buffer.
4974
4975 \param - pFileName Pointer to the File Name.
4976 pCtx - Pointer to the adapter .
4977
4978
4979 \return - 0 for success, non zero for failure
4980
4981 --------------------------------------------------------------------------*/
4982
4983VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4984{
4985 VOS_STATUS status = VOS_STATUS_SUCCESS;
4986 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4987 ENTER();
4988
4989
4990 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4991
4992 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4993
4994 if(pHddCtx->fw) {
4995 release_firmware(pHddCtx->fw);
4996 pHddCtx->fw = NULL;
4997 }
4998 else
4999 status = VOS_STATUS_E_FAILURE;
5000 }
5001 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5002 if(pHddCtx->nv) {
5003 release_firmware(pHddCtx->nv);
5004 pHddCtx->nv = NULL;
5005 }
5006 else
5007 status = VOS_STATUS_E_FAILURE;
5008
5009 }
5010
5011 EXIT();
5012 return status;
5013}
5014
5015/**---------------------------------------------------------------------------
5016
5017 \brief hdd_request_firmware() -
5018
5019 This function reads the firmware file using the request firmware
5020 API and returns the the firmware data and the firmware file size.
5021
5022 \param - pfileName - Pointer to the file name.
5023 - pCtx - Pointer to the adapter .
5024 - ppfw_data - Pointer to the pointer of the firmware data.
5025 - pSize - Pointer to the file size.
5026
5027 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5028
5029 --------------------------------------------------------------------------*/
5030
5031
5032VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5033{
5034 int status;
5035 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5036 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5037 ENTER();
5038
5039 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5040
5041 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5042
5043 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5044 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5045 __func__, pfileName);
5046 retval = VOS_STATUS_E_FAILURE;
5047 }
5048
5049 else {
5050 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5051 *pSize = pHddCtx->fw->size;
5052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5053 __func__, *pSize);
5054 }
5055 }
5056 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5057
5058 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5059
5060 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5061 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5062 __func__, pfileName);
5063 retval = VOS_STATUS_E_FAILURE;
5064 }
5065
5066 else {
5067 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5068 *pSize = pHddCtx->nv->size;
5069 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5070 __func__, *pSize);
5071 }
5072 }
5073
5074 EXIT();
5075 return retval;
5076}
5077/**---------------------------------------------------------------------------
5078 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5079
5080 This is the function invoked by SME to inform the result of a full power
5081 request issued by HDD
5082
5083 \param - callbackcontext - Pointer to cookie
5084 status - result of request
5085
5086 \return - None
5087
5088--------------------------------------------------------------------------*/
5089void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5090{
5091 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5092
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005093 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 if(&pHddCtx->full_pwr_comp_var)
5095 {
5096 complete(&pHddCtx->full_pwr_comp_var);
5097 }
5098}
5099
5100/**---------------------------------------------------------------------------
5101
5102 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5103
5104 This is the function invoked by SME to inform the result of BMPS
5105 request issued by HDD
5106
5107 \param - callbackcontext - Pointer to cookie
5108 status - result of request
5109
5110 \return - None
5111
5112--------------------------------------------------------------------------*/
5113void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5114{
5115
5116 struct completion *completion_var = (struct completion*) callbackContext;
5117
Arif Hussain6d2a3322013-11-17 19:50:10 -08005118 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005119 if(completion_var != NULL)
5120 {
5121 complete(completion_var);
5122 }
5123}
5124
5125/**---------------------------------------------------------------------------
5126
5127 \brief hdd_get_cfg_file_size() -
5128
5129 This function reads the configuration file using the request firmware
5130 API and returns the configuration file size.
5131
5132 \param - pCtx - Pointer to the adapter .
5133 - pFileName - Pointer to the file name.
5134 - pBufSize - Pointer to the buffer size.
5135
5136 \return - 0 for success, non zero for failure
5137
5138 --------------------------------------------------------------------------*/
5139
5140VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5141{
5142 int status;
5143 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5144
5145 ENTER();
5146
5147 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5148
5149 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5151 status = VOS_STATUS_E_FAILURE;
5152 }
5153 else {
5154 *pBufSize = pHddCtx->fw->size;
5155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5156 release_firmware(pHddCtx->fw);
5157 pHddCtx->fw = NULL;
5158 }
5159
5160 EXIT();
5161 return VOS_STATUS_SUCCESS;
5162}
5163
5164/**---------------------------------------------------------------------------
5165
5166 \brief hdd_read_cfg_file() -
5167
5168 This function reads the configuration file using the request firmware
5169 API and returns the cfg data and the buffer size of the configuration file.
5170
5171 \param - pCtx - Pointer to the adapter .
5172 - pFileName - Pointer to the file name.
5173 - pBuffer - Pointer to the data buffer.
5174 - pBufSize - Pointer to the buffer size.
5175
5176 \return - 0 for success, non zero for failure
5177
5178 --------------------------------------------------------------------------*/
5179
5180VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5181 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5182{
5183 int status;
5184 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5185
5186 ENTER();
5187
5188 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5189
5190 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5192 return VOS_STATUS_E_FAILURE;
5193 }
5194 else {
5195 if(*pBufSize != pHddCtx->fw->size) {
5196 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5197 "file size", __func__);
5198 release_firmware(pHddCtx->fw);
5199 pHddCtx->fw = NULL;
5200 return VOS_STATUS_E_FAILURE;
5201 }
5202 else {
5203 if(pBuffer) {
5204 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5205 }
5206 release_firmware(pHddCtx->fw);
5207 pHddCtx->fw = NULL;
5208 }
5209 }
5210
5211 EXIT();
5212
5213 return VOS_STATUS_SUCCESS;
5214}
5215
5216/**---------------------------------------------------------------------------
5217
Jeff Johnson295189b2012-06-20 16:38:30 -07005218 \brief hdd_set_mac_address() -
5219
5220 This function sets the user specified mac address using
5221 the command ifconfig wlanX hw ether <mac adress>.
5222
5223 \param - dev - Pointer to the net device.
5224 - addr - Pointer to the sockaddr.
5225 \return - 0 for success, non zero for failure
5226
5227 --------------------------------------------------------------------------*/
5228
5229static int hdd_set_mac_address(struct net_device *dev, void *addr)
5230{
5231 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5232 struct sockaddr *psta_mac_addr = addr;
5233 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5234
5235 ENTER();
5236
5237 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5238
5239#ifdef HDD_SESSIONIZE
5240 // set the MAC address though the STA ID CFG.
5241 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5242 (v_U8_t *)&pAdapter->macAddressCurrent,
5243 sizeof( pAdapter->macAddressCurrent ),
5244 hdd_set_mac_addr_cb, VOS_FALSE );
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305245
5246 if(eHAL_STATUS_SUCCESS != halStatus)
5247 {
5248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5249 "%s: failed to set MAC address in CFG", __func__);
5250 }
5251
Jeff Johnson295189b2012-06-20 16:38:30 -07005252#endif
5253
5254 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5255
5256 EXIT();
5257 return halStatus;
5258}
5259
5260tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5261{
5262 int i;
5263 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5264 {
Abhishek Singheb183782014-02-06 13:37:21 +05305265 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005266 break;
5267 }
5268
5269 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5270 return NULL;
5271
5272 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5273 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5274}
5275
5276void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5277{
5278 int i;
5279 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5280 {
5281 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5282 {
5283 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5284 break;
5285 }
5286 }
5287 return;
5288}
5289
5290#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5291 static struct net_device_ops wlan_drv_ops = {
5292 .ndo_open = hdd_open,
5293 .ndo_stop = hdd_stop,
5294 .ndo_uninit = hdd_uninit,
5295 .ndo_start_xmit = hdd_hard_start_xmit,
5296 .ndo_tx_timeout = hdd_tx_timeout,
5297 .ndo_get_stats = hdd_stats,
5298 .ndo_do_ioctl = hdd_ioctl,
5299 .ndo_set_mac_address = hdd_set_mac_address,
5300 .ndo_select_queue = hdd_select_queue,
5301#ifdef WLAN_FEATURE_PACKET_FILTERING
5302#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5303 .ndo_set_rx_mode = hdd_set_multicast_list,
5304#else
5305 .ndo_set_multicast_list = hdd_set_multicast_list,
5306#endif //LINUX_VERSION_CODE
5307#endif
5308 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005309 static struct net_device_ops wlan_mon_drv_ops = {
5310 .ndo_open = hdd_mon_open,
5311 .ndo_stop = hdd_stop,
5312 .ndo_uninit = hdd_uninit,
5313 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5314 .ndo_tx_timeout = hdd_tx_timeout,
5315 .ndo_get_stats = hdd_stats,
5316 .ndo_do_ioctl = hdd_ioctl,
5317 .ndo_set_mac_address = hdd_set_mac_address,
5318 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005319
5320#endif
5321
5322void hdd_set_station_ops( struct net_device *pWlanDev )
5323{
5324#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005325 pWlanDev->netdev_ops = &wlan_drv_ops;
5326#else
5327 pWlanDev->open = hdd_open;
5328 pWlanDev->stop = hdd_stop;
5329 pWlanDev->uninit = hdd_uninit;
5330 pWlanDev->hard_start_xmit = NULL;
5331 pWlanDev->tx_timeout = hdd_tx_timeout;
5332 pWlanDev->get_stats = hdd_stats;
5333 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005334 pWlanDev->set_mac_address = hdd_set_mac_address;
5335#endif
5336}
5337
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005338static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005339{
5340 struct net_device *pWlanDev = NULL;
5341 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005342 /*
5343 * cfg80211 initialization and registration....
5344 */
5345 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5346
Jeff Johnson295189b2012-06-20 16:38:30 -07005347 if(pWlanDev != NULL)
5348 {
5349
5350 //Save the pointer to the net_device in the HDD adapter
5351 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5352
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5354
5355 pAdapter->dev = pWlanDev;
5356 pAdapter->pHddCtx = pHddCtx;
5357 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5358
5359 init_completion(&pAdapter->session_open_comp_var);
5360 init_completion(&pAdapter->session_close_comp_var);
5361 init_completion(&pAdapter->disconnect_comp_var);
5362 init_completion(&pAdapter->linkup_event_var);
5363 init_completion(&pAdapter->cancel_rem_on_chan_var);
5364 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305365 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5367 init_completion(&pAdapter->offchannel_tx_event);
5368#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005369 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005370#ifdef FEATURE_WLAN_TDLS
5371 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005372 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005373 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305374 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005375#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 init_completion(&pHddCtx->mc_sus_event_var);
5377 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305378 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005379 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005380 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005381
Rajeev79dbe4c2013-10-05 11:03:42 +05305382#ifdef FEATURE_WLAN_BATCH_SCAN
5383 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5384 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5385 pAdapter->pBatchScanRsp = NULL;
5386 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005387 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005388 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305389 mutex_init(&pAdapter->hdd_batch_scan_lock);
5390#endif
5391
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 pAdapter->isLinkUpSvcNeeded = FALSE;
5393 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5394 //Init the net_device structure
5395 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5396
5397 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5398 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5399 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5400 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5401
5402 hdd_set_station_ops( pAdapter->dev );
5403
5404 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005405 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5406 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5407 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 /* set pWlanDev's parent to underlying device */
5409 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5410 }
5411
5412 return pAdapter;
5413}
5414
5415VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5416{
5417 struct net_device *pWlanDev = pAdapter->dev;
5418 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5419 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5420 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5421
5422 if( rtnl_lock_held )
5423 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005424 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5426 {
5427 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5428 return VOS_STATUS_E_FAILURE;
5429 }
5430 }
5431 if (register_netdevice(pWlanDev))
5432 {
5433 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5434 return VOS_STATUS_E_FAILURE;
5435 }
5436 }
5437 else
5438 {
5439 if(register_netdev(pWlanDev))
5440 {
5441 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5442 return VOS_STATUS_E_FAILURE;
5443 }
5444 }
5445 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5446
5447 return VOS_STATUS_SUCCESS;
5448}
5449
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005450static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005451{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005452 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005453
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005454 if (NULL == pAdapter)
5455 {
5456 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5457 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005459
5460 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5461 {
5462 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5463 return eHAL_STATUS_NOT_INITIALIZED;
5464 }
5465
5466 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5467
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005468#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005469 /* need to make sure all of our scheduled work has completed.
5470 * This callback is called from MC thread context, so it is safe to
5471 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005472 *
5473 * Even though this is called from MC thread context, if there is a faulty
5474 * work item in the system, that can hang this call forever. So flushing
5475 * this global work queue is not safe; and now we make sure that
5476 * individual work queues are stopped correctly. But the cancel work queue
5477 * is a GPL only API, so the proprietary version of the driver would still
5478 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005479 */
5480 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005481#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005482
5483 /* We can be blocked while waiting for scheduled work to be
5484 * flushed, and the adapter structure can potentially be freed, in
5485 * which case the magic will have been reset. So make sure the
5486 * magic is still good, and hence the adapter structure is still
5487 * valid, before signaling completion */
5488 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5489 {
5490 complete(&pAdapter->session_close_comp_var);
5491 }
5492
Jeff Johnson295189b2012-06-20 16:38:30 -07005493 return eHAL_STATUS_SUCCESS;
5494}
5495
5496VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5497{
5498 struct net_device *pWlanDev = pAdapter->dev;
5499 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5500 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5501 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5502 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305503 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005504
5505 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005506 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 //Open a SME session for future operation
5508 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005509 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5511 {
5512 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005513 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 halStatus, halStatus );
5515 status = VOS_STATUS_E_FAILURE;
5516 goto error_sme_open;
5517 }
5518
5519 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305520 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 &pAdapter->session_open_comp_var,
5522 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305523 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 {
5525 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305526 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005527 status = VOS_STATUS_E_FAILURE;
5528 goto error_sme_open;
5529 }
5530
5531 // Register wireless extensions
5532 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5533 {
5534 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005535 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 halStatus, halStatus );
5537 status = VOS_STATUS_E_FAILURE;
5538 goto error_register_wext;
5539 }
5540 //Safe to register the hard_start_xmit function again
5541#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5542 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5543#else
5544 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5545#endif
5546
5547 //Set the Connection State to Not Connected
5548 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5549
5550 //Set the default operation channel
5551 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5552
5553 /* Make the default Auth Type as OPEN*/
5554 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5555
5556 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5557 {
5558 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005559 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 status, status );
5561 goto error_init_txrx;
5562 }
5563
5564 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5565
5566 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5567 {
5568 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005569 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 status, status );
5571 goto error_wmm_init;
5572 }
5573
5574 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5575
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005576#ifdef FEATURE_WLAN_TDLS
5577 if(0 != wlan_hdd_tdls_init(pAdapter))
5578 {
5579 status = VOS_STATUS_E_FAILURE;
5580 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5581 goto error_tdls_init;
5582 }
5583 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5584#endif
5585
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 return VOS_STATUS_SUCCESS;
5587
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005588#ifdef FEATURE_WLAN_TDLS
5589error_tdls_init:
5590 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5591 hdd_wmm_adapter_close(pAdapter);
5592#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005593error_wmm_init:
5594 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5595 hdd_deinit_tx_rx(pAdapter);
5596error_init_txrx:
5597 hdd_UnregisterWext(pWlanDev);
5598error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005599 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005600 {
5601 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005602 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005604 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305606 unsigned long rc;
5607
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305609 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005610 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005611 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305612 if (rc <= 0)
5613 hddLog(VOS_TRACE_LEVEL_ERROR,
5614 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 }
5616}
5617error_sme_open:
5618 return status;
5619}
5620
Jeff Johnson295189b2012-06-20 16:38:30 -07005621void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5622{
5623 hdd_cfg80211_state_t *cfgState;
5624
5625 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5626
5627 if( NULL != cfgState->buf )
5628 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305629 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5631 rc = wait_for_completion_interruptible_timeout(
5632 &pAdapter->tx_action_cnf_event,
5633 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305634 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005635 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005636 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305637 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5638 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005639 }
5640 }
5641 return;
5642}
Jeff Johnson295189b2012-06-20 16:38:30 -07005643
5644void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5645{
5646 ENTER();
5647 switch ( pAdapter->device_mode )
5648 {
5649 case WLAN_HDD_INFRA_STATION:
5650 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005651 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005652 {
5653 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5654 {
5655 hdd_deinit_tx_rx( pAdapter );
5656 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5657 }
5658
5659 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5660 {
5661 hdd_wmm_adapter_close( pAdapter );
5662 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5663 }
5664
Jeff Johnson295189b2012-06-20 16:38:30 -07005665 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005666#ifdef FEATURE_WLAN_TDLS
5667 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5668 {
5669 wlan_hdd_tdls_exit(pAdapter);
5670 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5671 }
5672#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005673
5674 break;
5675 }
5676
5677 case WLAN_HDD_SOFTAP:
5678 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005679 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305680
5681 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5682 {
5683 hdd_wmm_adapter_close( pAdapter );
5684 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5685 }
5686
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005688
5689 hdd_unregister_hostapd(pAdapter);
5690 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005691 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 break;
5693 }
5694
5695 case WLAN_HDD_MONITOR:
5696 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005697 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5699 {
5700 hdd_deinit_tx_rx( pAdapter );
5701 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 if(NULL != pAdapterforTx)
5704 {
5705 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5706 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005707 break;
5708 }
5709
5710
5711 default:
5712 break;
5713 }
5714
5715 EXIT();
5716}
5717
5718void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5719{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005720 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305721
5722 ENTER();
5723 if (NULL == pAdapter)
5724 {
5725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5726 "%s: HDD adapter is Null", __func__);
5727 return;
5728 }
5729
5730 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005731
Rajeev79dbe4c2013-10-05 11:03:42 +05305732#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305733 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5734 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005735 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305736 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5737 )
5738 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005739 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305740 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005741 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5742 {
5743 hdd_deinit_batch_scan(pAdapter);
5744 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305745 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005746 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305747#endif
5748
Jeff Johnson295189b2012-06-20 16:38:30 -07005749 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5750 if( rtnl_held )
5751 {
5752 unregister_netdevice(pWlanDev);
5753 }
5754 else
5755 {
5756 unregister_netdev(pWlanDev);
5757 }
5758 // note that the pAdapter is no longer valid at this point
5759 // since the memory has been reclaimed
5760 }
5761
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305762 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005763}
5764
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005765void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5766{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305767 VOS_STATUS status;
5768 hdd_adapter_t *pAdapter = NULL;
5769 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005770
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305771 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005772
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305773 /*loop through all adapters.*/
5774 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005775 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305776 pAdapter = pAdapterNode->pAdapter;
5777 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5778 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005779
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305780 { // we skip this registration for modes other than STA and P2P client modes.
5781 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5782 pAdapterNode = pNext;
5783 continue;
5784 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005785
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305786 //Apply Dynamic DTIM For P2P
5787 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5788 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5789 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5790 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5791 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5792 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5793 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5794 (eConnectionState_Associated ==
5795 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5796 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5797 {
5798 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005799
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305800 powerRequest.uIgnoreDTIM = 1;
5801 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5802
5803 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5804 {
5805 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5806 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5807 }
5808 else
5809 {
5810 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5811 }
5812
5813 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5814 * specified during Enter/Exit BMPS when LCD off*/
5815 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5816 NULL, eANI_BOOLEAN_FALSE);
5817 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5818 NULL, eANI_BOOLEAN_FALSE);
5819
5820 /* switch to the DTIM specified in cfg.ini */
5821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5822 "Switch to DTIM %d", powerRequest.uListenInterval);
5823 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5824 break;
5825
5826 }
5827
5828 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5829 pAdapterNode = pNext;
5830 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005831}
5832
5833void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5834{
5835 /*Switch back to DTIM 1*/
5836 tSirSetPowerParamsReq powerRequest = { 0 };
5837
5838 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5839 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005840 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005841
5842 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5843 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5844 NULL, eANI_BOOLEAN_FALSE);
5845 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5846 NULL, eANI_BOOLEAN_FALSE);
5847
5848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5849 "Switch to DTIM%d",powerRequest.uListenInterval);
5850 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5851
5852}
5853
Jeff Johnson295189b2012-06-20 16:38:30 -07005854VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5855{
5856 VOS_STATUS status = VOS_STATUS_SUCCESS;
5857
5858 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5859 {
5860 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5861 }
5862
5863 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5864 {
5865 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5866 }
5867
5868 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5869 {
5870 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5871 }
5872
5873 return status;
5874}
5875
5876VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5877{
5878 hdd_adapter_t *pAdapter = NULL;
5879 eHalStatus halStatus;
5880 VOS_STATUS status = VOS_STATUS_E_INVAL;
5881 v_BOOL_t disableBmps = FALSE;
5882 v_BOOL_t disableImps = FALSE;
5883
5884 switch(session_type)
5885 {
5886 case WLAN_HDD_INFRA_STATION:
5887 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 case WLAN_HDD_P2P_CLIENT:
5889 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 //Exit BMPS -> Is Sta/P2P Client is already connected
5891 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5892 if((NULL != pAdapter)&&
5893 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5894 {
5895 disableBmps = TRUE;
5896 }
5897
5898 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5899 if((NULL != pAdapter)&&
5900 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5901 {
5902 disableBmps = TRUE;
5903 }
5904
5905 //Exit both Bmps and Imps incase of Go/SAP Mode
5906 if((WLAN_HDD_SOFTAP == session_type) ||
5907 (WLAN_HDD_P2P_GO == session_type))
5908 {
5909 disableBmps = TRUE;
5910 disableImps = TRUE;
5911 }
5912
5913 if(TRUE == disableImps)
5914 {
5915 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5916 {
5917 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5918 }
5919 }
5920
5921 if(TRUE == disableBmps)
5922 {
5923 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5924 {
5925 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5926
5927 if(eHAL_STATUS_SUCCESS != halStatus)
5928 {
5929 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005930 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005931 VOS_ASSERT(0);
5932 return status;
5933 }
5934 }
5935
5936 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5937 {
5938 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5939
5940 if(eHAL_STATUS_SUCCESS != halStatus)
5941 {
5942 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005943 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 VOS_ASSERT(0);
5945 return status;
5946 }
5947 }
5948 }
5949
5950 if((TRUE == disableBmps) ||
5951 (TRUE == disableImps))
5952 {
5953 /* Now, get the chip into Full Power now */
5954 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5955 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5956 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5957
5958 if(halStatus != eHAL_STATUS_SUCCESS)
5959 {
5960 if(halStatus == eHAL_STATUS_PMC_PENDING)
5961 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305962 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305964 ret = wait_for_completion_interruptible_timeout(
5965 &pHddCtx->full_pwr_comp_var,
5966 msecs_to_jiffies(1000));
5967 if (ret <= 0)
5968 {
5969 hddLog(VOS_TRACE_LEVEL_ERROR,
5970 "%s: wait on full_pwr_comp_var failed %ld",
5971 __func__, ret);
5972 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005973 }
5974 else
5975 {
5976 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005977 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 VOS_ASSERT(0);
5979 return status;
5980 }
5981 }
5982
5983 status = VOS_STATUS_SUCCESS;
5984 }
5985
5986 break;
5987 }
5988 return status;
5989}
5990
5991hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005992 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 tANI_U8 rtnl_held )
5994{
5995 hdd_adapter_t *pAdapter = NULL;
5996 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5997 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5998 VOS_STATUS exitbmpsStatus;
5999
Arif Hussain6d2a3322013-11-17 19:50:10 -08006000 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006001
Nirav Shah436658f2014-02-28 17:05:45 +05306002 if(macAddr == NULL)
6003 {
6004 /* Not received valid macAddr */
6005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6006 "%s:Unable to add virtual intf: Not able to get"
6007 "valid mac address",__func__);
6008 return NULL;
6009 }
6010
Jeff Johnson295189b2012-06-20 16:38:30 -07006011 //Disable BMPS incase of Concurrency
6012 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6013
6014 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6015 {
6016 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306017 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 VOS_ASSERT(0);
6019 return NULL;
6020 }
6021
6022 switch(session_type)
6023 {
6024 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006025 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006026 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 {
6028 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6029
6030 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306031 {
6032 hddLog(VOS_TRACE_LEVEL_FATAL,
6033 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306035 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006036
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306037#ifdef FEATURE_WLAN_TDLS
6038 /* A Mutex Lock is introduced while changing/initializing the mode to
6039 * protect the concurrent access for the Adapters by TDLS module.
6040 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306041 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306042#endif
6043
Jeff Johnsone7245742012-09-05 17:12:55 -07006044 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6045 NL80211_IFTYPE_P2P_CLIENT:
6046 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006047
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306049#ifdef FEATURE_WLAN_TDLS
6050 mutex_unlock(&pHddCtx->tdls_lock);
6051#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306052
6053 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 if( VOS_STATUS_SUCCESS != status )
6055 goto err_free_netdev;
6056
6057 status = hdd_register_interface( pAdapter, rtnl_held );
6058 if( VOS_STATUS_SUCCESS != status )
6059 {
6060 hdd_deinit_adapter(pHddCtx, pAdapter);
6061 goto err_free_netdev;
6062 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306063
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306064 // Workqueue which gets scheduled in IPv4 notification callback.
6065 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6066
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306067#ifdef WLAN_NS_OFFLOAD
6068 // Workqueue which gets scheduled in IPv6 notification callback.
6069 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6070#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006071 //Stop the Interface TX queue.
6072 netif_tx_disable(pAdapter->dev);
6073 //netif_tx_disable(pWlanDev);
6074 netif_carrier_off(pAdapter->dev);
6075
6076 break;
6077 }
6078
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 case WLAN_HDD_SOFTAP:
6081 {
6082 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6083 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306084 {
6085 hddLog(VOS_TRACE_LEVEL_FATAL,
6086 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306088 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006089
Jeff Johnson295189b2012-06-20 16:38:30 -07006090 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6091 NL80211_IFTYPE_AP:
6092 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 pAdapter->device_mode = session_type;
6094
6095 status = hdd_init_ap_mode(pAdapter);
6096 if( VOS_STATUS_SUCCESS != status )
6097 goto err_free_netdev;
6098
6099 status = hdd_register_hostapd( pAdapter, rtnl_held );
6100 if( VOS_STATUS_SUCCESS != status )
6101 {
6102 hdd_deinit_adapter(pHddCtx, pAdapter);
6103 goto err_free_netdev;
6104 }
6105
6106 netif_tx_disable(pAdapter->dev);
6107 netif_carrier_off(pAdapter->dev);
6108
6109 hdd_set_conparam( 1 );
6110 break;
6111 }
6112 case WLAN_HDD_MONITOR:
6113 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006114 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6115 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306116 {
6117 hddLog(VOS_TRACE_LEVEL_FATAL,
6118 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006121
6122 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6123 pAdapter->device_mode = session_type;
6124 status = hdd_register_interface( pAdapter, rtnl_held );
6125#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6126 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6127#else
6128 pAdapter->dev->open = hdd_mon_open;
6129 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6130#endif
6131 hdd_init_tx_rx( pAdapter );
6132 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6133 //Set adapter to be used for data tx. It will use either GO or softap.
6134 pAdapter->sessionCtx.monitor.pAdapterForTx =
6135 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6137 {
6138 pAdapter->sessionCtx.monitor.pAdapterForTx =
6139 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 /* This workqueue will be used to transmit management packet over
6142 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006143 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6144 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6145 return NULL;
6146 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006147
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6149 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006150 }
6151 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 case WLAN_HDD_FTM:
6153 {
6154 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6155
6156 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306157 {
6158 hddLog(VOS_TRACE_LEVEL_FATAL,
6159 FL("failed to allocate adapter for session %d"), session_type);
6160 return NULL;
6161 }
6162
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6164 * message while loading driver in FTM mode. */
6165 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6166 pAdapter->device_mode = session_type;
6167 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306168
6169 hdd_init_tx_rx( pAdapter );
6170
6171 //Stop the Interface TX queue.
6172 netif_tx_disable(pAdapter->dev);
6173 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006174 }
6175 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 default:
6177 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306178 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6179 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 VOS_ASSERT(0);
6181 return NULL;
6182 }
6183 }
6184
Jeff Johnson295189b2012-06-20 16:38:30 -07006185 if( VOS_STATUS_SUCCESS == status )
6186 {
6187 //Add it to the hdd's session list.
6188 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6189 if( NULL == pHddAdapterNode )
6190 {
6191 status = VOS_STATUS_E_NOMEM;
6192 }
6193 else
6194 {
6195 pHddAdapterNode->pAdapter = pAdapter;
6196 status = hdd_add_adapter_back ( pHddCtx,
6197 pHddAdapterNode );
6198 }
6199 }
6200
6201 if( VOS_STATUS_SUCCESS != status )
6202 {
6203 if( NULL != pAdapter )
6204 {
6205 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6206 pAdapter = NULL;
6207 }
6208 if( NULL != pHddAdapterNode )
6209 {
6210 vos_mem_free( pHddAdapterNode );
6211 }
6212
6213 goto resume_bmps;
6214 }
6215
6216 if(VOS_STATUS_SUCCESS == status)
6217 {
6218 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6219
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006220 //Initialize the WoWL service
6221 if(!hdd_init_wowl(pAdapter))
6222 {
6223 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6224 goto err_free_netdev;
6225 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 return pAdapter;
6228
6229err_free_netdev:
6230 free_netdev(pAdapter->dev);
6231 wlan_hdd_release_intf_addr( pHddCtx,
6232 pAdapter->macAddressCurrent.bytes );
6233
6234resume_bmps:
6235 //If bmps disabled enable it
6236 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6237 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306238 if (pHddCtx->hdd_wlan_suspended)
6239 {
6240 hdd_set_pwrparams(pHddCtx);
6241 }
6242 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006243 }
6244 return NULL;
6245}
6246
6247VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6248 tANI_U8 rtnl_held )
6249{
6250 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6251 VOS_STATUS status;
6252
6253 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6254 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306255 {
6256 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6257 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006260
6261 while ( pCurrent->pAdapter != pAdapter )
6262 {
6263 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6264 if( VOS_STATUS_SUCCESS != status )
6265 break;
6266
6267 pCurrent = pNext;
6268 }
6269 pAdapterNode = pCurrent;
6270 if( VOS_STATUS_SUCCESS == status )
6271 {
6272 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6273 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306274
6275#ifdef FEATURE_WLAN_TDLS
6276
6277 /* A Mutex Lock is introduced while changing/initializing the mode to
6278 * protect the concurrent access for the Adapters by TDLS module.
6279 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306280 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306281#endif
6282
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 hdd_remove_adapter( pHddCtx, pAdapterNode );
6284 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006285 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006286
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306287#ifdef FEATURE_WLAN_TDLS
6288 mutex_unlock(&pHddCtx->tdls_lock);
6289#endif
6290
Jeff Johnson295189b2012-06-20 16:38:30 -07006291
6292 /* If there is a single session of STA/P2P client, re-enable BMPS */
6293 if ((!vos_concurrent_sessions_running()) &&
6294 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6295 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6296 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306297 if (pHddCtx->hdd_wlan_suspended)
6298 {
6299 hdd_set_pwrparams(pHddCtx);
6300 }
6301 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 }
6303
6304 return VOS_STATUS_SUCCESS;
6305 }
6306
6307 return VOS_STATUS_E_FAILURE;
6308}
6309
6310VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6311{
6312 hdd_adapter_list_node_t *pHddAdapterNode;
6313 VOS_STATUS status;
6314
6315 ENTER();
6316
6317 do
6318 {
6319 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6320 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6321 {
6322 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6323 vos_mem_free( pHddAdapterNode );
6324 }
6325 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6326
6327 EXIT();
6328
6329 return VOS_STATUS_SUCCESS;
6330}
6331
6332void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6333{
6334 v_U8_t addIE[1] = {0};
6335
6336 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6337 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6338 eANI_BOOLEAN_FALSE) )
6339 {
6340 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006341 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 }
6343
6344 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6345 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6346 eANI_BOOLEAN_FALSE) )
6347 {
6348 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006349 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006350 }
6351
6352 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6353 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6354 eANI_BOOLEAN_FALSE) )
6355 {
6356 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006357 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006358 }
6359}
6360
6361VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6362{
6363 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6364 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6365 union iwreq_data wrqu;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306366 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006367
6368 ENTER();
6369
6370 switch(pAdapter->device_mode)
6371 {
6372 case WLAN_HDD_INFRA_STATION:
6373 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006374 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306375 {
6376 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6377 if( hdd_connIsConnected(pstation) ||
6378 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006379 {
6380 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6381 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6382 pAdapter->sessionId,
6383 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6384 else
6385 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6386 pAdapter->sessionId,
6387 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6388 //success implies disconnect command got queued up successfully
6389 if(halStatus == eHAL_STATUS_SUCCESS)
6390 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306391 ret = wait_for_completion_interruptible_timeout(
6392 &pAdapter->disconnect_comp_var,
6393 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6394 if (ret <= 0)
6395 {
6396 hddLog(VOS_TRACE_LEVEL_ERROR,
6397 "%s: wait on disconnect_comp_var failed %ld",
6398 __func__, ret);
6399 }
6400 }
6401 else
6402 {
6403 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6404 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006405 }
6406 memset(&wrqu, '\0', sizeof(wrqu));
6407 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6408 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6409 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6410 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306411 else if(pstation->conn_info.connState ==
6412 eConnectionState_Disconnecting)
6413 {
6414 ret = wait_for_completion_interruptible_timeout(
6415 &pAdapter->disconnect_comp_var,
6416 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6417 if (ret <= 0)
6418 {
6419 hddLog(VOS_TRACE_LEVEL_ERROR,
6420 FL("wait on disconnect_comp_var failed %ld"), ret);
6421 }
6422 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006423 else
6424 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306425 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6426 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006427 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306428#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306429#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306430 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6431#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306432 if (pAdapter->ipv6_notifier_registered)
6433 {
6434 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6435 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6436 pAdapter->ipv6_notifier_registered = false;
6437 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306438#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306439 if (pAdapter->ipv4_notifier_registered)
6440 {
6441 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6442 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6443 pAdapter->ipv4_notifier_registered = false;
6444 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306445#ifdef WLAN_OPEN_SOURCE
6446 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6447#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006448 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6449 {
6450 INIT_COMPLETION(pAdapter->session_close_comp_var);
6451 if (eHAL_STATUS_SUCCESS ==
6452 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6453 hdd_smeCloseSessionCallback, pAdapter))
6454 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306455 unsigned long ret;
6456
Jeff Johnson295189b2012-06-20 16:38:30 -07006457 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306458 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 &pAdapter->session_close_comp_var,
6460 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306461 if ( 0 >= ret)
6462 {
6463 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6464 __func__, ret);
6465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 }
6467 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306468 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006469 break;
6470
6471 case WLAN_HDD_SOFTAP:
6472 case WLAN_HDD_P2P_GO:
6473 //Any softap specific cleanup here...
6474 mutex_lock(&pHddCtx->sap_lock);
6475 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6476 {
6477 VOS_STATUS status;
6478 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6479
6480 //Stop Bss.
6481 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6482 if (VOS_IS_STATUS_SUCCESS(status))
6483 {
6484 hdd_hostapd_state_t *pHostapdState =
6485 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6486
6487 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6488
6489 if (!VOS_IS_STATUS_SUCCESS(status))
6490 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306491 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6492 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 }
6494 }
6495 else
6496 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006497 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 }
6499 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6500
6501 if (eHAL_STATUS_FAILURE ==
6502 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6503 0, NULL, eANI_BOOLEAN_FALSE))
6504 {
6505 hddLog(LOGE,
6506 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006507 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006508 }
6509
6510 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6511 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6512 eANI_BOOLEAN_FALSE) )
6513 {
6514 hddLog(LOGE,
6515 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6516 }
6517
6518 // Reset WNI_CFG_PROBE_RSP Flags
6519 wlan_hdd_reset_prob_rspies(pAdapter);
6520 kfree(pAdapter->sessionCtx.ap.beacon);
6521 pAdapter->sessionCtx.ap.beacon = NULL;
6522 }
6523 mutex_unlock(&pHddCtx->sap_lock);
6524 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006525
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006527#ifdef WLAN_OPEN_SOURCE
6528 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6529#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006530 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006531
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 default:
6533 break;
6534 }
6535
6536 EXIT();
6537 return VOS_STATUS_SUCCESS;
6538}
6539
6540VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6541{
6542 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6543 VOS_STATUS status;
6544 hdd_adapter_t *pAdapter;
6545
6546 ENTER();
6547
6548 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6549
6550 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6551 {
6552 pAdapter = pAdapterNode->pAdapter;
6553 netif_tx_disable(pAdapter->dev);
6554 netif_carrier_off(pAdapter->dev);
6555
6556 hdd_stop_adapter( pHddCtx, pAdapter );
6557
6558 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6559 pAdapterNode = pNext;
6560 }
6561
6562 EXIT();
6563
6564 return VOS_STATUS_SUCCESS;
6565}
6566
Rajeev Kumarf999e582014-01-09 17:33:29 -08006567
6568#ifdef FEATURE_WLAN_BATCH_SCAN
6569/**---------------------------------------------------------------------------
6570
6571 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6572 structures
6573
6574 \param - pAdapter Pointer to HDD adapter
6575
6576 \return - None
6577
6578 --------------------------------------------------------------------------*/
6579void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6580{
6581 tHddBatchScanRsp *pNode;
6582 tHddBatchScanRsp *pPrev;
6583
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306584 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006585 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306586 hddLog(VOS_TRACE_LEVEL_ERROR,
6587 "%s: Adapter context is Null", __func__);
6588 return;
6589 }
6590
6591 pNode = pAdapter->pBatchScanRsp;
6592 while (pNode)
6593 {
6594 pPrev = pNode;
6595 pNode = pNode->pNext;
6596 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08006597 }
6598
6599 pAdapter->pBatchScanRsp = NULL;
6600 pAdapter->numScanList = 0;
6601 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6602 pAdapter->prev_batch_id = 0;
6603
6604 return;
6605}
6606#endif
6607
6608
Jeff Johnson295189b2012-06-20 16:38:30 -07006609VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6610{
6611 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6612 VOS_STATUS status;
6613 hdd_adapter_t *pAdapter;
6614
6615 ENTER();
6616
6617 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6618
6619 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6620 {
6621 pAdapter = pAdapterNode->pAdapter;
6622 netif_tx_disable(pAdapter->dev);
6623 netif_carrier_off(pAdapter->dev);
6624
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006625 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6626
Jeff Johnson295189b2012-06-20 16:38:30 -07006627 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306628 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6629 {
6630 hdd_wmm_adapter_close( pAdapter );
6631 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6632 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006633
Rajeev Kumarf999e582014-01-09 17:33:29 -08006634#ifdef FEATURE_WLAN_BATCH_SCAN
6635 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6636 {
6637 hdd_deinit_batch_scan(pAdapter);
6638 }
6639#endif
6640
Jeff Johnson295189b2012-06-20 16:38:30 -07006641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6642 pAdapterNode = pNext;
6643 }
6644
6645 EXIT();
6646
6647 return VOS_STATUS_SUCCESS;
6648}
6649
6650VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6651{
6652 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6653 VOS_STATUS status;
6654 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306655 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006656
6657 ENTER();
6658
6659 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6660
6661 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6662 {
6663 pAdapter = pAdapterNode->pAdapter;
6664
6665 switch(pAdapter->device_mode)
6666 {
6667 case WLAN_HDD_INFRA_STATION:
6668 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006669 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306670
6671 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6672
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 hdd_init_station_mode(pAdapter);
6674 /* Open the gates for HDD to receive Wext commands */
6675 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006676 pHddCtx->scan_info.mScanPending = FALSE;
6677 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006678
6679 //Trigger the initial scan
6680 hdd_wlan_initial_scan(pAdapter);
6681
6682 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306683 if (eConnectionState_Associated == connState ||
6684 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006685 {
6686 union iwreq_data wrqu;
6687 memset(&wrqu, '\0', sizeof(wrqu));
6688 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6689 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6690 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006691 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006692
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 /* indicate disconnected event to nl80211 */
6694 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6695 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006696 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306697 else if (eConnectionState_Connecting == connState)
6698 {
6699 /*
6700 * Indicate connect failure to supplicant if we were in the
6701 * process of connecting
6702 */
6703 cfg80211_connect_result(pAdapter->dev, NULL,
6704 NULL, 0, NULL, 0,
6705 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6706 GFP_KERNEL);
6707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006708 break;
6709
6710 case WLAN_HDD_SOFTAP:
6711 /* softAP can handle SSR */
6712 break;
6713
6714 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006716 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006717 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006718 break;
6719
6720 case WLAN_HDD_MONITOR:
6721 /* monitor interface start */
6722 break;
6723 default:
6724 break;
6725 }
6726
6727 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6728 pAdapterNode = pNext;
6729 }
6730
6731 EXIT();
6732
6733 return VOS_STATUS_SUCCESS;
6734}
6735
6736VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6737{
6738 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6739 hdd_adapter_t *pAdapter;
6740 VOS_STATUS status;
6741 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306742 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006743
6744 ENTER();
6745
6746 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6747
6748 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6749 {
6750 pAdapter = pAdapterNode->pAdapter;
6751
6752 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6753 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6754 {
6755 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6756 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6757
6758 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6759 init_completion(&pAdapter->disconnect_comp_var);
6760 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6761 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6762
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306763 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006764 &pAdapter->disconnect_comp_var,
6765 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306766 if (0 >= ret)
6767 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
6768 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07006769
6770 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6771 pHddCtx->isAmpAllowed = VOS_FALSE;
6772 sme_RoamConnect(pHddCtx->hHal,
6773 pAdapter->sessionId, &(pWextState->roamProfile),
6774 &roamId);
6775 }
6776
6777 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6778 pAdapterNode = pNext;
6779 }
6780
6781 EXIT();
6782
6783 return VOS_STATUS_SUCCESS;
6784}
6785
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006786void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6787{
6788 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6789 VOS_STATUS status;
6790 hdd_adapter_t *pAdapter;
6791 hdd_station_ctx_t *pHddStaCtx;
6792 hdd_ap_ctx_t *pHddApCtx;
6793 hdd_hostapd_state_t * pHostapdState;
6794 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6795 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6796 const char *p2pMode = "DEV";
6797 const char *ccMode = "Standalone";
6798 int n;
6799
6800 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6801 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6802 {
6803 pAdapter = pAdapterNode->pAdapter;
6804 switch (pAdapter->device_mode) {
6805 case WLAN_HDD_INFRA_STATION:
6806 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6807 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6808 staChannel = pHddStaCtx->conn_info.operationChannel;
6809 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6810 }
6811 break;
6812 case WLAN_HDD_P2P_CLIENT:
6813 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6814 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6815 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6816 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6817 p2pMode = "CLI";
6818 }
6819 break;
6820 case WLAN_HDD_P2P_GO:
6821 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6822 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6823 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6824 p2pChannel = pHddApCtx->operatingChannel;
6825 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6826 }
6827 p2pMode = "GO";
6828 break;
6829 case WLAN_HDD_SOFTAP:
6830 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6831 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6832 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6833 apChannel = pHddApCtx->operatingChannel;
6834 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6835 }
6836 break;
6837 default:
6838 break;
6839 }
6840 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6841 pAdapterNode = pNext;
6842 }
6843 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6844 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6845 }
6846 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6847 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6848 if (p2pChannel > 0) {
6849 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6850 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6851 }
6852 if (apChannel > 0) {
6853 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6854 apChannel, MAC_ADDR_ARRAY(apBssid));
6855 }
6856
6857 if (p2pChannel > 0 && apChannel > 0) {
6858 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6859 }
6860}
6861
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006862bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006863{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006864 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006865}
6866
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006867/* Once SSR is disabled then it cannot be set. */
6868void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006869{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006870 if (HDD_SSR_DISABLED == isSsrRequired)
6871 return;
6872
Jeff Johnson295189b2012-06-20 16:38:30 -07006873 isSsrRequired = value;
6874}
6875
6876VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6877 hdd_adapter_list_node_t** ppAdapterNode)
6878{
6879 VOS_STATUS status;
6880 spin_lock(&pHddCtx->hddAdapters.lock);
6881 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6882 (hdd_list_node_t**) ppAdapterNode );
6883 spin_unlock(&pHddCtx->hddAdapters.lock);
6884 return status;
6885}
6886
6887VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6888 hdd_adapter_list_node_t* pAdapterNode,
6889 hdd_adapter_list_node_t** pNextAdapterNode)
6890{
6891 VOS_STATUS status;
6892 spin_lock(&pHddCtx->hddAdapters.lock);
6893 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6894 (hdd_list_node_t*) pAdapterNode,
6895 (hdd_list_node_t**)pNextAdapterNode );
6896
6897 spin_unlock(&pHddCtx->hddAdapters.lock);
6898 return status;
6899}
6900
6901VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6902 hdd_adapter_list_node_t* pAdapterNode)
6903{
6904 VOS_STATUS status;
6905 spin_lock(&pHddCtx->hddAdapters.lock);
6906 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6907 &pAdapterNode->node );
6908 spin_unlock(&pHddCtx->hddAdapters.lock);
6909 return status;
6910}
6911
6912VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6913 hdd_adapter_list_node_t** ppAdapterNode)
6914{
6915 VOS_STATUS status;
6916 spin_lock(&pHddCtx->hddAdapters.lock);
6917 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6918 (hdd_list_node_t**) ppAdapterNode );
6919 spin_unlock(&pHddCtx->hddAdapters.lock);
6920 return status;
6921}
6922
6923VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6924 hdd_adapter_list_node_t* pAdapterNode)
6925{
6926 VOS_STATUS status;
6927 spin_lock(&pHddCtx->hddAdapters.lock);
6928 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6929 (hdd_list_node_t*) pAdapterNode );
6930 spin_unlock(&pHddCtx->hddAdapters.lock);
6931 return status;
6932}
6933
6934VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6935 hdd_adapter_list_node_t* pAdapterNode)
6936{
6937 VOS_STATUS status;
6938 spin_lock(&pHddCtx->hddAdapters.lock);
6939 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6940 (hdd_list_node_t*) pAdapterNode );
6941 spin_unlock(&pHddCtx->hddAdapters.lock);
6942 return status;
6943}
6944
6945hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6946 tSirMacAddr macAddr )
6947{
6948 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6949 hdd_adapter_t *pAdapter;
6950 VOS_STATUS status;
6951
6952 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6953
6954 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6955 {
6956 pAdapter = pAdapterNode->pAdapter;
6957
6958 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6959 macAddr, sizeof(tSirMacAddr) ) )
6960 {
6961 return pAdapter;
6962 }
6963 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6964 pAdapterNode = pNext;
6965 }
6966
6967 return NULL;
6968
6969}
6970
6971hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6972{
6973 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6974 hdd_adapter_t *pAdapter;
6975 VOS_STATUS status;
6976
6977 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6978
6979 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6980 {
6981 pAdapter = pAdapterNode->pAdapter;
6982
6983 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6984 IFNAMSIZ ) )
6985 {
6986 return pAdapter;
6987 }
6988 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6989 pAdapterNode = pNext;
6990 }
6991
6992 return NULL;
6993
6994}
6995
6996hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6997{
6998 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6999 hdd_adapter_t *pAdapter;
7000 VOS_STATUS status;
7001
7002 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7003
7004 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7005 {
7006 pAdapter = pAdapterNode->pAdapter;
7007
7008 if( pAdapter && (mode == pAdapter->device_mode) )
7009 {
7010 return pAdapter;
7011 }
7012 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7013 pAdapterNode = pNext;
7014 }
7015
7016 return NULL;
7017
7018}
7019
7020//Remove this function later
7021hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7022{
7023 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7024 hdd_adapter_t *pAdapter;
7025 VOS_STATUS status;
7026
7027 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7028
7029 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7030 {
7031 pAdapter = pAdapterNode->pAdapter;
7032
7033 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7034 {
7035 return pAdapter;
7036 }
7037
7038 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7039 pAdapterNode = pNext;
7040 }
7041
7042 return NULL;
7043
7044}
7045
Jeff Johnson295189b2012-06-20 16:38:30 -07007046/**---------------------------------------------------------------------------
7047
7048 \brief hdd_set_monitor_tx_adapter() -
7049
7050 This API initializes the adapter to be used while transmitting on monitor
7051 adapter.
7052
7053 \param - pHddCtx - Pointer to the HDD context.
7054 pAdapter - Adapter that will used for TX. This can be NULL.
7055 \return - None.
7056 --------------------------------------------------------------------------*/
7057void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7058{
7059 hdd_adapter_t *pMonAdapter;
7060
7061 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7062
7063 if( NULL != pMonAdapter )
7064 {
7065 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7066 }
7067}
Jeff Johnson295189b2012-06-20 16:38:30 -07007068/**---------------------------------------------------------------------------
7069
7070 \brief hdd_select_queue() -
7071
7072 This API returns the operating channel of the requested device mode
7073
7074 \param - pHddCtx - Pointer to the HDD context.
7075 - mode - Device mode for which operating channel is required
7076 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7077 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7078 \return - channel number. "0" id the requested device is not found OR it is not connected.
7079 --------------------------------------------------------------------------*/
7080v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7081{
7082 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7083 VOS_STATUS status;
7084 hdd_adapter_t *pAdapter;
7085 v_U8_t operatingChannel = 0;
7086
7087 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7088
7089 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7090 {
7091 pAdapter = pAdapterNode->pAdapter;
7092
7093 if( mode == pAdapter->device_mode )
7094 {
7095 switch(pAdapter->device_mode)
7096 {
7097 case WLAN_HDD_INFRA_STATION:
7098 case WLAN_HDD_P2P_CLIENT:
7099 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7100 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7101 break;
7102 case WLAN_HDD_SOFTAP:
7103 case WLAN_HDD_P2P_GO:
7104 /*softap connection info */
7105 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7106 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7107 break;
7108 default:
7109 break;
7110 }
7111
7112 break; //Found the device of interest. break the loop
7113 }
7114
7115 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7116 pAdapterNode = pNext;
7117 }
7118 return operatingChannel;
7119}
7120
7121#ifdef WLAN_FEATURE_PACKET_FILTERING
7122/**---------------------------------------------------------------------------
7123
7124 \brief hdd_set_multicast_list() -
7125
7126 This used to set the multicast address list.
7127
7128 \param - dev - Pointer to the WLAN device.
7129 - skb - Pointer to OS packet (sk_buff).
7130 \return - success/fail
7131
7132 --------------------------------------------------------------------------*/
7133static void hdd_set_multicast_list(struct net_device *dev)
7134{
7135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007136 int mc_count;
7137 int i = 0;
7138 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307139
7140 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 {
7142 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307143 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007144 return;
7145 }
7146
7147 if (dev->flags & IFF_ALLMULTI)
7148 {
7149 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007150 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307151 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007152 }
7153 else
7154 {
7155 mc_count = netdev_mc_count(dev);
7156 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007157 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007158 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7159 {
7160 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007161 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307162 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007163 return;
7164 }
7165
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307166 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007167
7168 netdev_for_each_mc_addr(ha, dev) {
7169 if (i == mc_count)
7170 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307171 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7172 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007173 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007174 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307175 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007176 i++;
7177 }
7178 }
7179 return;
7180}
7181#endif
7182
7183/**---------------------------------------------------------------------------
7184
7185 \brief hdd_select_queue() -
7186
7187 This function is registered with the Linux OS for network
7188 core to decide which queue to use first.
7189
7190 \param - dev - Pointer to the WLAN device.
7191 - skb - Pointer to OS packet (sk_buff).
7192 \return - ac, Queue Index/access category corresponding to UP in IP header
7193
7194 --------------------------------------------------------------------------*/
7195v_U16_t hdd_select_queue(struct net_device *dev,
7196 struct sk_buff *skb)
7197{
7198 return hdd_wmm_select_queue(dev, skb);
7199}
7200
7201
7202/**---------------------------------------------------------------------------
7203
7204 \brief hdd_wlan_initial_scan() -
7205
7206 This function triggers the initial scan
7207
7208 \param - pAdapter - Pointer to the HDD adapter.
7209
7210 --------------------------------------------------------------------------*/
7211void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7212{
7213 tCsrScanRequest scanReq;
7214 tCsrChannelInfo channelInfo;
7215 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007216 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007217 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7218
7219 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7220 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7221 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7222
7223 if(sme_Is11dSupported(pHddCtx->hHal))
7224 {
7225 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7226 if ( HAL_STATUS_SUCCESS( halStatus ) )
7227 {
7228 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7229 if( !scanReq.ChannelInfo.ChannelList )
7230 {
7231 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7232 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007233 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007234 return;
7235 }
7236 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7237 channelInfo.numOfChannels);
7238 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7239 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007240 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007241 }
7242
7243 scanReq.scanType = eSIR_PASSIVE_SCAN;
7244 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7245 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7246 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7247 }
7248 else
7249 {
7250 scanReq.scanType = eSIR_ACTIVE_SCAN;
7251 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7252 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7253 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7254 }
7255
7256 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7257 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7258 {
7259 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7260 __func__, halStatus );
7261 }
7262
7263 if(sme_Is11dSupported(pHddCtx->hHal))
7264 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7265}
7266
Jeff Johnson295189b2012-06-20 16:38:30 -07007267/**---------------------------------------------------------------------------
7268
7269 \brief hdd_full_power_callback() - HDD full power callback function
7270
7271 This is the function invoked by SME to inform the result of a full power
7272 request issued by HDD
7273
7274 \param - callbackcontext - Pointer to cookie
7275 \param - status - result of request
7276
7277 \return - None
7278
7279 --------------------------------------------------------------------------*/
7280static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7281{
Jeff Johnson72a40512013-12-19 10:14:15 -08007282 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007283
7284 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307285 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007286
7287 if (NULL == callbackContext)
7288 {
7289 hddLog(VOS_TRACE_LEVEL_ERROR,
7290 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007291 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007292 return;
7293 }
7294
Jeff Johnson72a40512013-12-19 10:14:15 -08007295 /* there is a race condition that exists between this callback
7296 function and the caller since the caller could time out either
7297 before or while this code is executing. we use a spinlock to
7298 serialize these actions */
7299 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007300
7301 if (POWER_CONTEXT_MAGIC != pContext->magic)
7302 {
7303 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007304 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 hddLog(VOS_TRACE_LEVEL_WARN,
7306 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007307 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007308 return;
7309 }
7310
Jeff Johnson72a40512013-12-19 10:14:15 -08007311 /* context is valid so caller is still waiting */
7312
7313 /* paranoia: invalidate the magic */
7314 pContext->magic = 0;
7315
7316 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007317 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007318
7319 /* serialization is complete */
7320 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007321}
7322
7323/**---------------------------------------------------------------------------
7324
7325 \brief hdd_wlan_exit() - HDD WLAN exit function
7326
7327 This is the driver exit point (invoked during rmmod)
7328
7329 \param - pHddCtx - Pointer to the HDD Context
7330
7331 \return - None
7332
7333 --------------------------------------------------------------------------*/
7334void hdd_wlan_exit(hdd_context_t *pHddCtx)
7335{
7336 eHalStatus halStatus;
7337 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7338 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307339 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007340 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007341 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007342 long lrc;
7343
7344 ENTER();
7345
Jeff Johnson88ba7742013-02-27 14:36:02 -08007346 if (VOS_FTM_MODE != hdd_get_conparam())
7347 {
7348 // Unloading, restart logic is no more required.
7349 wlan_hdd_restart_deinit(pHddCtx);
7350 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007351
Jeff Johnson295189b2012-06-20 16:38:30 -07007352 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007353 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007354 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007355 {
7356 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7357 WLAN_HDD_INFRA_STATION);
7358 if (pAdapter == NULL)
7359 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7360
7361 if (pAdapter != NULL)
7362 {
7363 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7364 hdd_UnregisterWext(pAdapter->dev);
7365 }
7366 }
7367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007368
Jeff Johnson295189b2012-06-20 16:38:30 -07007369 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007370 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307371 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007372 wlan_hdd_ftm_close(pHddCtx);
7373 goto free_hdd_ctx;
7374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007375 //Stop the Interface TX queue.
7376 //netif_tx_disable(pWlanDev);
7377 //netif_carrier_off(pWlanDev);
7378
Jeff Johnson295189b2012-06-20 16:38:30 -07007379 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7380 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307381 hddLog(VOS_TRACE_LEVEL_INFO,"%s: SAP MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007382 pAdapter = hdd_get_adapter(pHddCtx,
7383 WLAN_HDD_SOFTAP);
7384 }
7385 else
7386 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007387 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307389 hddLog(VOS_TRACE_LEVEL_INFO,"%s: STA MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007390 pAdapter = hdd_get_adapter(pHddCtx,
7391 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007392 if (pAdapter == NULL)
7393 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007395 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307396
7397 if(NULL == pAdapter)
7398 {
7399 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: pAdapter is NULL",__func__);
7400 goto free_hdd_ctx;
7401 }
7402
Jeff Johnson295189b2012-06-20 16:38:30 -07007403 /* DeRegister with platform driver as client for Suspend/Resume */
7404 vosStatus = hddDeregisterPmOps(pHddCtx);
7405 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7406 {
7407 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7408 VOS_ASSERT(0);
7409 }
7410
7411 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7412 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7413 {
7414 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7415 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007416
7417 // Cancel any outstanding scan requests. We are about to close all
7418 // of our adapters, but an adapter structure is what SME passes back
7419 // to our callback function. Hence if there are any outstanding scan
7420 // requests then there is a race condition between when the adapter
7421 // is closed and when the callback is invoked. We try to resolve that
7422 // race condition here by canceling any outstanding scans before we
7423 // close the adapters.
7424 // Note that the scans may be cancelled in an asynchronous manner, so
7425 // ideally there needs to be some kind of synchronization. Rather than
7426 // introduce a new synchronization here, we will utilize the fact that
7427 // we are about to Request Full Power, and since that is synchronized,
7428 // the expectation is that by the time Request Full Power has completed,
7429 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007430 if (NULL != pAdapter)
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05307431 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, eCSR_SCAN_ABORT_DEFAULT);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007432 else
7433 hddLog(VOS_TRACE_LEVEL_ERROR,
7434 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007435
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007436 //Stop the traffic monitor timer
7437 if ( VOS_TIMER_STATE_RUNNING ==
7438 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7439 {
7440 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7441 }
7442
7443 // Destroy the traffic monitor timer
7444 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7445 &pHddCtx->tx_rx_trafficTmr)))
7446 {
7447 hddLog(VOS_TRACE_LEVEL_ERROR,
7448 "%s: Cannot deallocate Traffic monitor timer", __func__);
7449 }
7450
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 //Disable IMPS/BMPS as we do not want the device to enter any power
7452 //save mode during shutdown
7453 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7454 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7455 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7456
7457 //Ensure that device is in full power as we will touch H/W during vos_Stop
7458 init_completion(&powerContext.completion);
7459 powerContext.magic = POWER_CONTEXT_MAGIC;
7460
7461 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7462 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7463
7464 if (eHAL_STATUS_SUCCESS != halStatus)
7465 {
7466 if (eHAL_STATUS_PMC_PENDING == halStatus)
7467 {
7468 /* request was sent -- wait for the response */
7469 lrc = wait_for_completion_interruptible_timeout(
7470 &powerContext.completion,
7471 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007472 if (lrc <= 0)
7473 {
7474 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007475 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007476 }
7477 }
7478 else
7479 {
7480 hddLog(VOS_TRACE_LEVEL_ERROR,
7481 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007482 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007483 /* continue -- need to clean up as much as possible */
7484 }
7485 }
7486
Jeff Johnson72a40512013-12-19 10:14:15 -08007487 /* either we never sent a request, we sent a request and received a
7488 response or we sent a request and timed out. if we never sent a
7489 request or if we sent a request and got a response, we want to
7490 clear the magic out of paranoia. if we timed out there is a
7491 race condition such that the callback function could be
7492 executing at the same time we are. of primary concern is if the
7493 callback function had already verified the "magic" but had not
7494 yet set the completion variable when a timeout occurred. we
7495 serialize these activities by invalidating the magic while
7496 holding a shared spinlock which will cause us to block if the
7497 callback is currently executing */
7498 spin_lock(&hdd_context_lock);
7499 powerContext.magic = 0;
7500 spin_unlock(&hdd_context_lock);
7501
Yue Ma0d4891e2013-08-06 17:01:45 -07007502 hdd_debugfs_exit(pHddCtx);
7503
Jeff Johnson295189b2012-06-20 16:38:30 -07007504 // Unregister the Net Device Notifier
7505 unregister_netdevice_notifier(&hdd_netdev_notifier);
7506
Jeff Johnson295189b2012-06-20 16:38:30 -07007507 hdd_stop_all_adapters( pHddCtx );
7508
Jeff Johnson295189b2012-06-20 16:38:30 -07007509#ifdef WLAN_BTAMP_FEATURE
7510 vosStatus = WLANBAP_Stop(pVosContext);
7511 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7512 {
7513 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7514 "%s: Failed to stop BAP",__func__);
7515 }
7516#endif //WLAN_BTAMP_FEATURE
7517
7518 //Stop all the modules
7519 vosStatus = vos_stop( pVosContext );
7520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7521 {
7522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7523 "%s: Failed to stop VOSS",__func__);
7524 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7525 }
7526
Jeff Johnson295189b2012-06-20 16:38:30 -07007527 //Assert Deep sleep signal now to put Libra HW in lowest power state
7528 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7529 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7530
7531 //Vote off any PMIC voltage supplies
7532 vos_chipPowerDown(NULL, NULL, NULL);
7533
7534 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7535
Leo Chang59cdc7e2013-07-10 10:08:21 -07007536
Jeff Johnson295189b2012-06-20 16:38:30 -07007537 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007538 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007539
7540 //Close the scheduler before calling vos_close to make sure no thread is
7541 // scheduled after the each module close is called i.e after all the data
7542 // structures are freed.
7543 vosStatus = vos_sched_close( pVosContext );
7544 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7545 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7546 "%s: Failed to close VOSS Scheduler",__func__);
7547 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7548 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007549#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007550#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7551 /* Destroy the wake lock */
7552 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7553#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007554 /* Destroy the wake lock */
7555 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007556#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007557
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307558#ifdef CONFIG_ENABLE_LINUX_REG
7559 vosStatus = vos_nv_close();
7560 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7561 {
7562 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7563 "%s: Failed to close NV", __func__);
7564 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7565 }
7566#endif
7567
Jeff Johnson295189b2012-06-20 16:38:30 -07007568 //Close VOSS
7569 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7570 vos_close(pVosContext);
7571
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 //Close Watchdog
7573 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7574 vos_watchdog_close(pVosContext);
7575
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307576 //Clean up HDD Nlink Service
7577 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007578#ifdef WLAN_KD_READY_NOTIFIER
7579 nl_srv_exit(pHddCtx->ptt_pid);
7580#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307581 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007582#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307583
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307584#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
7585 if(pHddCtx->cfg_ini->wlanLoggingEnable)
7586 {
7587 wlan_logging_sock_deactivate_svc();
7588 }
7589#endif
7590
Jeff Johnson295189b2012-06-20 16:38:30 -07007591 /* Cancel the vote for XO Core ON.
7592 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7593 * exited at this point
7594 */
7595 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007596 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007597 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7598 {
7599 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7600 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007601 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007602 }
7603
7604 hdd_close_all_adapters( pHddCtx );
7605
7606
7607 //Free up dynamically allocated members inside HDD Adapter
7608 kfree(pHddCtx->cfg_ini);
7609 pHddCtx->cfg_ini= NULL;
7610
7611 /* free the power on lock from platform driver */
7612 if (free_riva_power_on_lock("wlan"))
7613 {
7614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7615 __func__);
7616 }
7617
Jeff Johnson88ba7742013-02-27 14:36:02 -08007618free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007619 /* FTM mode, WIPHY did not registered
7620 If un-register here, system crash will happen */
7621 if (VOS_FTM_MODE != hdd_get_conparam())
7622 {
7623 wiphy_unregister(wiphy) ;
7624 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007625 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007626 if (hdd_is_ssr_required())
7627 {
7628 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007629 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 msleep(5000);
7631 }
7632 hdd_set_ssr_required (VOS_FALSE);
7633}
7634
7635
7636/**---------------------------------------------------------------------------
7637
7638 \brief hdd_update_config_from_nv() - Function to update the contents of
7639 the running configuration with parameters taken from NV storage
7640
7641 \param - pHddCtx - Pointer to the HDD global context
7642
7643 \return - VOS_STATUS_SUCCESS if successful
7644
7645 --------------------------------------------------------------------------*/
7646static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7647{
Jeff Johnson295189b2012-06-20 16:38:30 -07007648 v_BOOL_t itemIsValid = VOS_FALSE;
7649 VOS_STATUS status;
7650 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7651 v_U8_t macLoop;
7652
7653 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7654 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7655 if(status != VOS_STATUS_SUCCESS)
7656 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007657 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007658 return VOS_STATUS_E_FAILURE;
7659 }
7660
7661 if (itemIsValid == VOS_TRUE)
7662 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007663 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007664 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7665 VOS_MAX_CONCURRENCY_PERSONA);
7666 if(status != VOS_STATUS_SUCCESS)
7667 {
7668 /* Get MAC from NV fail, not update CFG info
7669 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007670 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007671 return VOS_STATUS_E_FAILURE;
7672 }
7673
7674 /* If first MAC is not valid, treat all others are not valid
7675 * Then all MACs will be got from ini file */
7676 if(vos_is_macaddr_zero(&macFromNV[0]))
7677 {
7678 /* MAC address in NV file is not configured yet */
7679 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7680 return VOS_STATUS_E_INVAL;
7681 }
7682
7683 /* Get MAC address from NV, update CFG info */
7684 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7685 {
7686 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7687 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307688 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007689 /* This MAC is not valid, skip it
7690 * This MAC will be got from ini file */
7691 }
7692 else
7693 {
7694 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7695 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7696 VOS_MAC_ADDR_SIZE);
7697 }
7698 }
7699 }
7700 else
7701 {
7702 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7703 return VOS_STATUS_E_FAILURE;
7704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007705
Jeff Johnson295189b2012-06-20 16:38:30 -07007706
7707 return VOS_STATUS_SUCCESS;
7708}
7709
7710/**---------------------------------------------------------------------------
7711
7712 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7713
7714 \param - pAdapter - Pointer to the HDD
7715
7716 \return - None
7717
7718 --------------------------------------------------------------------------*/
7719VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7720{
7721 eHalStatus halStatus;
7722 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307723 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007724
Jeff Johnson295189b2012-06-20 16:38:30 -07007725
7726 // Send ready indication to the HDD. This will kick off the MAC
7727 // into a 'running' state and should kick off an initial scan.
7728 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7729 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7730 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307731 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007732 "code %08d [x%08x]",__func__, halStatus, halStatus );
7733 return VOS_STATUS_E_FAILURE;
7734 }
7735
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307736 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007737 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7738 // And RIVA will crash
7739 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7740 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307741 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7742 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7743
7744
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 return VOS_STATUS_SUCCESS;
7746}
7747
Jeff Johnson295189b2012-06-20 16:38:30 -07007748/* wake lock APIs for HDD */
7749void hdd_prevent_suspend(void)
7750{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007751#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007752 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007753#else
7754 wcnss_prevent_suspend();
7755#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007756}
7757
7758void hdd_allow_suspend(void)
7759{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007760#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007761 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007762#else
7763 wcnss_allow_suspend();
7764#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007765}
7766
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05307767void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007768{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007769#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007770 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007771#else
7772 /* Do nothing as there is no API in wcnss for timeout*/
7773#endif
7774}
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776/**---------------------------------------------------------------------------
7777
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007778 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7779 information between Host and Riva
7780
7781 This function gets reported version of FW
7782 It also finds the version of Riva headers used to compile the host
7783 It compares the above two and prints a warning if they are different
7784 It gets the SW and HW version string
7785 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7786 indicating the features they support through a bitmap
7787
7788 \param - pHddCtx - Pointer to HDD context
7789
7790 \return - void
7791
7792 --------------------------------------------------------------------------*/
7793
7794void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7795{
7796
7797 tSirVersionType versionCompiled;
7798 tSirVersionType versionReported;
7799 tSirVersionString versionString;
7800 tANI_U8 fwFeatCapsMsgSupported = 0;
7801 VOS_STATUS vstatus;
7802
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007803 memset(&versionCompiled, 0, sizeof(versionCompiled));
7804 memset(&versionReported, 0, sizeof(versionReported));
7805
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007806 /* retrieve and display WCNSS version information */
7807 do {
7808
7809 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7810 &versionCompiled);
7811 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7812 {
7813 hddLog(VOS_TRACE_LEVEL_FATAL,
7814 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007815 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007816 break;
7817 }
7818
7819 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7820 &versionReported);
7821 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7822 {
7823 hddLog(VOS_TRACE_LEVEL_FATAL,
7824 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007825 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007826 break;
7827 }
7828
7829 if ((versionCompiled.major != versionReported.major) ||
7830 (versionCompiled.minor != versionReported.minor) ||
7831 (versionCompiled.version != versionReported.version) ||
7832 (versionCompiled.revision != versionReported.revision))
7833 {
7834 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7835 "Host expected %u.%u.%u.%u\n",
7836 WLAN_MODULE_NAME,
7837 (int)versionReported.major,
7838 (int)versionReported.minor,
7839 (int)versionReported.version,
7840 (int)versionReported.revision,
7841 (int)versionCompiled.major,
7842 (int)versionCompiled.minor,
7843 (int)versionCompiled.version,
7844 (int)versionCompiled.revision);
7845 }
7846 else
7847 {
7848 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7849 WLAN_MODULE_NAME,
7850 (int)versionReported.major,
7851 (int)versionReported.minor,
7852 (int)versionReported.version,
7853 (int)versionReported.revision);
7854 }
7855
7856 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7857 versionString,
7858 sizeof(versionString));
7859 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7860 {
7861 hddLog(VOS_TRACE_LEVEL_FATAL,
7862 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007863 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007864 break;
7865 }
7866
7867 pr_info("%s: WCNSS software version %s\n",
7868 WLAN_MODULE_NAME, versionString);
7869
7870 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7871 versionString,
7872 sizeof(versionString));
7873 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7874 {
7875 hddLog(VOS_TRACE_LEVEL_FATAL,
7876 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007877 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007878 break;
7879 }
7880
7881 pr_info("%s: WCNSS hardware version %s\n",
7882 WLAN_MODULE_NAME, versionString);
7883
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007884 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7885 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007886 send the message only if it the riva is 1.1
7887 minor numbers for different riva branches:
7888 0 -> (1.0)Mainline Build
7889 1 -> (1.1)Mainline Build
7890 2->(1.04) Stability Build
7891 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007892 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007893 ((versionReported.minor>=1) && (versionReported.version>=1)))
7894 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7895 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007896
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007897 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007898 {
7899#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7900 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7901 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7902#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007903 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7904 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7905 {
7906 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7907 }
7908
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007909 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007910 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007911
7912 } while (0);
7913
7914}
7915
7916/**---------------------------------------------------------------------------
7917
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307918 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7919
7920 \param - pHddCtx - Pointer to the hdd context
7921
7922 \return - true if hardware supports 5GHz
7923
7924 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05307925boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307926{
7927 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7928 * then hardware support 5Ghz.
7929 */
7930 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7931 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307932 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307933 return true;
7934 }
7935 else
7936 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307937 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307938 __func__);
7939 return false;
7940 }
7941}
7942
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307943/**---------------------------------------------------------------------------
7944
7945 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7946 generate function
7947
7948 This is generate the random mac address for WLAN interface
7949
7950 \param - pHddCtx - Pointer to HDD context
7951 idx - Start interface index to get auto
7952 generated mac addr.
7953 mac_addr - Mac address
7954
7955 \return - 0 for success, < 0 for failure
7956
7957 --------------------------------------------------------------------------*/
7958
7959static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7960 int idx, v_MACADDR_t mac_addr)
7961{
7962 int i;
7963 unsigned int serialno;
7964 serialno = wcnss_get_serial_number();
7965
7966 if (0 != serialno)
7967 {
7968 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7969 bytes of the serial number that can be used to generate
7970 the other 3 bytes of the MAC address. Mask off all but
7971 the lower 3 bytes (this will also make sure we don't
7972 overflow in the next step) */
7973 serialno &= 0x00FFFFFF;
7974
7975 /* we need a unique address for each session */
7976 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7977
7978 /* autogen other Mac addresses */
7979 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7980 {
7981 /* start with the entire default address */
7982 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7983 /* then replace the lower 3 bytes */
7984 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7985 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7986 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7987
7988 serialno++;
7989 hddLog(VOS_TRACE_LEVEL_ERROR,
7990 "%s: Derived Mac Addr: "
7991 MAC_ADDRESS_STR, __func__,
7992 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7993 }
7994
7995 }
7996 else
7997 {
7998 hddLog(LOGE, FL("Failed to Get Serial NO"));
7999 return -1;
8000 }
8001 return 0;
8002}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308003
8004/**---------------------------------------------------------------------------
8005
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308006 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8007 completed to flush out the scan results
8008
8009 11d scan is done during driver load and is a passive scan on all
8010 channels supported by the device, 11d scans may find some APs on
8011 frequencies which are forbidden to be used in the regulatory domain
8012 the device is operating in. If these APs are notified to the supplicant
8013 it may try to connect to these APs, thus flush out all the scan results
8014 which are present in SME after 11d scan is done.
8015
8016 \return - eHalStatus
8017
8018 --------------------------------------------------------------------------*/
8019static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8020 tANI_U32 scanId, eCsrScanStatus status)
8021{
8022 ENTER();
8023
8024 sme_ScanFlushResult(halHandle, 0);
8025
8026 EXIT();
8027
8028 return eHAL_STATUS_SUCCESS;
8029}
8030
8031/**---------------------------------------------------------------------------
8032
Jeff Johnson295189b2012-06-20 16:38:30 -07008033 \brief hdd_wlan_startup() - HDD init function
8034
8035 This is the driver startup code executed once a WLAN device has been detected
8036
8037 \param - dev - Pointer to the underlying device
8038
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008039 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008040
8041 --------------------------------------------------------------------------*/
8042
8043int hdd_wlan_startup(struct device *dev )
8044{
8045 VOS_STATUS status;
8046 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008047 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008048 hdd_context_t *pHddCtx = NULL;
8049 v_CONTEXT_t pVosContext= NULL;
8050#ifdef WLAN_BTAMP_FEATURE
8051 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8052 WLANBAP_ConfigType btAmpConfig;
8053 hdd_config_t *pConfig;
8054#endif
8055 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008056 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308057 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008058
8059 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 /*
8061 * cfg80211: wiphy allocation
8062 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308063 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008064
8065 if(wiphy == NULL)
8066 {
8067 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008068 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008069 }
8070
8071 pHddCtx = wiphy_priv(wiphy);
8072
Jeff Johnson295189b2012-06-20 16:38:30 -07008073 //Initialize the adapter context to zeros.
8074 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8075
Jeff Johnson295189b2012-06-20 16:38:30 -07008076 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008077 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308078 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008079
8080 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8081
8082 /*Get vos context here bcoz vos_open requires it*/
8083 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8084
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008085 if(pVosContext == NULL)
8086 {
8087 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8088 goto err_free_hdd_context;
8089 }
8090
Jeff Johnson295189b2012-06-20 16:38:30 -07008091 //Save the Global VOSS context in adapter context for future.
8092 pHddCtx->pvosContext = pVosContext;
8093
8094 //Save the adapter context in global context for future.
8095 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8096
Jeff Johnson295189b2012-06-20 16:38:30 -07008097 pHddCtx->parent_dev = dev;
8098
8099 init_completion(&pHddCtx->full_pwr_comp_var);
8100 init_completion(&pHddCtx->standby_comp_var);
8101 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008102 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008103 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308104 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308105 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008106
8107#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008108 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008109#else
8110 init_completion(&pHddCtx->driver_crda_req);
8111#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008112
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308113 spin_lock_init(&pHddCtx->schedScan_lock);
8114
Jeff Johnson295189b2012-06-20 16:38:30 -07008115 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8116
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308117#ifdef FEATURE_WLAN_TDLS
8118 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8119 * invoked by other instances also) to protect the concurrent
8120 * access for the Adapters by TDLS module.
8121 */
8122 mutex_init(&pHddCtx->tdls_lock);
8123#endif
8124
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308125 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008126 // Load all config first as TL config is needed during vos_open
8127 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8128 if(pHddCtx->cfg_ini == NULL)
8129 {
8130 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8131 goto err_free_hdd_context;
8132 }
8133
8134 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8135
8136 // Read and parse the qcom_cfg.ini file
8137 status = hdd_parse_config_ini( pHddCtx );
8138 if ( VOS_STATUS_SUCCESS != status )
8139 {
8140 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8141 __func__, WLAN_INI_FILE);
8142 goto err_config;
8143 }
Arif Hussaind5218912013-12-05 01:10:55 -08008144#ifdef MEMORY_DEBUG
8145 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8146 vos_mem_init();
8147
8148 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8149 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008151
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308152 /* INI has been read, initialise the configuredMcastBcastFilter with
8153 * INI value as this will serve as the default value
8154 */
8155 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8156 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8157 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308158
8159 if (false == hdd_is_5g_supported(pHddCtx))
8160 {
8161 //5Ghz is not supported.
8162 if (1 != pHddCtx->cfg_ini->nBandCapability)
8163 {
8164 hddLog(VOS_TRACE_LEVEL_INFO,
8165 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8166 pHddCtx->cfg_ini->nBandCapability = 1;
8167 }
8168 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308169
8170 /* If SNR Monitoring is enabled, FW has to parse all beacons
8171 * for calcaluting and storing the average SNR, so set Nth beacon
8172 * filter to 1 to enable FW to parse all the beaocons
8173 */
8174 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8175 {
8176 /* The log level is deliberately set to WARN as overriding
8177 * nthBeaconFilter to 1 will increase power cosumption and this
8178 * might just prove helpful to detect the power issue.
8179 */
8180 hddLog(VOS_TRACE_LEVEL_WARN,
8181 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8182 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8183 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008184 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308185 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008186 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008187 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008188 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008189 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8190 {
8191 hddLog(VOS_TRACE_LEVEL_FATAL,
8192 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8193 goto err_config;
8194 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008196
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008197 // Update VOS trace levels based upon the cfg.ini
8198 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8199 pHddCtx->cfg_ini->vosTraceEnableBAP);
8200 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8201 pHddCtx->cfg_ini->vosTraceEnableTL);
8202 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8203 pHddCtx->cfg_ini->vosTraceEnableWDI);
8204 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8205 pHddCtx->cfg_ini->vosTraceEnableHDD);
8206 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8207 pHddCtx->cfg_ini->vosTraceEnableSME);
8208 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8209 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308210 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8211 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008212 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8213 pHddCtx->cfg_ini->vosTraceEnableWDA);
8214 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8215 pHddCtx->cfg_ini->vosTraceEnableSYS);
8216 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8217 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008218 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8219 pHddCtx->cfg_ini->vosTraceEnableSAP);
8220 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8221 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008222
Jeff Johnson295189b2012-06-20 16:38:30 -07008223 // Update WDI trace levels based upon the cfg.ini
8224 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8225 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8226 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8227 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8228 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8229 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8230 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8231 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008232
Jeff Johnson88ba7742013-02-27 14:36:02 -08008233 if (VOS_FTM_MODE == hdd_get_conparam())
8234 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008235 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8236 {
8237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8238 goto err_free_hdd_context;
8239 }
8240 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
8241 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008242 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008243
Jeff Johnson88ba7742013-02-27 14:36:02 -08008244 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008245 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8246 {
8247 status = vos_watchdog_open(pVosContext,
8248 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8249
8250 if(!VOS_IS_STATUS_SUCCESS( status ))
8251 {
8252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308253 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008254 }
8255 }
8256
8257 pHddCtx->isLogpInProgress = FALSE;
8258 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8259
Jeff Johnson295189b2012-06-20 16:38:30 -07008260 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8261 if(!VOS_IS_STATUS_SUCCESS(status))
8262 {
8263 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008264 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008265 }
8266
Amar Singhala49cbc52013-10-08 18:37:44 -07008267#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008268 /* initialize the NV module. This is required so that
8269 we can initialize the channel information in wiphy
8270 from the NV.bin data. The channel information in
8271 wiphy needs to be initialized before wiphy registration */
8272
8273 status = vos_nv_open();
8274 if (!VOS_IS_STATUS_SUCCESS(status))
8275 {
8276 /* NV module cannot be initialized */
8277 hddLog( VOS_TRACE_LEVEL_FATAL,
8278 "%s: vos_nv_open failed", __func__);
8279 goto err_clkvote;
8280 }
8281
8282 status = vos_init_wiphy_from_nv_bin();
8283 if (!VOS_IS_STATUS_SUCCESS(status))
8284 {
8285 /* NV module cannot be initialized */
8286 hddLog( VOS_TRACE_LEVEL_FATAL,
8287 "%s: vos_init_wiphy failed", __func__);
8288 goto err_vos_nv_close;
8289 }
8290
Amar Singhala49cbc52013-10-08 18:37:44 -07008291#endif
8292
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308293 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008294 if ( !VOS_IS_STATUS_SUCCESS( status ))
8295 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008296 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308297 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008298 }
8299
Jeff Johnson295189b2012-06-20 16:38:30 -07008300 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8301
8302 if ( NULL == pHddCtx->hHal )
8303 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008304 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008305 goto err_vosclose;
8306 }
8307
Mihir Shetee1093ba2014-01-21 20:13:32 +05308308#ifdef CONFIG_ENABLE_LINUX_REG
8309 /* registration of wiphy dev with cfg80211 */
8310 if (0 > wlan_hdd_cfg80211_register(wiphy))
8311 {
8312 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8313 goto err_vosclose;
8314 }
8315
8316 status = wlan_hdd_init_channels(pHddCtx);
8317 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8318 {
8319 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8320 __func__);
8321 goto err_wiphy_unregister;
8322 }
8323#endif
8324
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008325 status = vos_preStart( pHddCtx->pvosContext );
8326 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8327 {
8328 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308329 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008330 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008331
Arif Hussaineaf68602013-12-30 23:10:44 -08008332 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8333 {
8334 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8335 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8336 __func__, enable_dfs_chan_scan);
8337 }
8338 if (0 == enable_11d || 1 == enable_11d)
8339 {
8340 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8341 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8342 __func__, enable_11d);
8343 }
8344
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008345 /* Note that the vos_preStart() sequence triggers the cfg download.
8346 The cfg download must occur before we update the SME config
8347 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008348 status = hdd_set_sme_config( pHddCtx );
8349
8350 if ( VOS_STATUS_SUCCESS != status )
8351 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008352 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308353 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008354 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008355
8356 //Initialize the WMM module
8357 status = hdd_wmm_init(pHddCtx);
8358 if (!VOS_IS_STATUS_SUCCESS(status))
8359 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008360 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308361 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008362 }
8363
Jeff Johnson295189b2012-06-20 16:38:30 -07008364 /* In the integrated architecture we update the configuration from
8365 the INI file and from NV before vOSS has been started so that
8366 the final contents are available to send down to the cCPU */
8367
8368 // Apply the cfg.ini to cfg.dat
8369 if (FALSE == hdd_update_config_dat(pHddCtx))
8370 {
8371 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308372 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008373 }
8374
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308375 // Get mac addr from platform driver
8376 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8377
8378 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008379 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308380 /* Store the mac addr for first interface */
8381 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8382
8383 hddLog(VOS_TRACE_LEVEL_ERROR,
8384 "%s: WLAN Mac Addr: "
8385 MAC_ADDRESS_STR, __func__,
8386 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8387
8388 /* Here, passing Arg2 as 1 because we do not want to change the
8389 last 3 bytes (means non OUI bytes) of first interface mac
8390 addr.
8391 */
8392 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8393 {
8394 hddLog(VOS_TRACE_LEVEL_ERROR,
8395 "%s: Failed to generate wlan interface mac addr "
8396 "using MAC from ini file ", __func__);
8397 }
8398 }
8399 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8400 {
8401 // Apply the NV to cfg.dat
8402 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008403#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8404 /* There was not a valid set of MAC Addresses in NV. See if the
8405 default addresses were modified by the cfg.ini settings. If so,
8406 we'll use them, but if not, we'll autogenerate a set of MAC
8407 addresses based upon the device serial number */
8408
8409 static const v_MACADDR_t default_address =
8410 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008411
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308412 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8413 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008414 {
8415 /* cfg.ini has the default address, invoke autogen logic */
8416
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308417 /* Here, passing Arg2 as 0 because we want to change the
8418 last 3 bytes (means non OUI bytes) of all the interfaces
8419 mac addr.
8420 */
8421 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8422 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008423 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308424 hddLog(VOS_TRACE_LEVEL_ERROR,
8425 "%s: Failed to generate wlan interface mac addr "
8426 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8427 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008428 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008429 }
8430 else
8431#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8432 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008433 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008434 "%s: Invalid MAC address in NV, using MAC from ini file "
8435 MAC_ADDRESS_STR, __func__,
8436 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8437 }
8438 }
8439 {
8440 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308441
8442 /* Set the MAC Address Currently this is used by HAL to
8443 * add self sta. Remove this once self sta is added as
8444 * part of session open.
8445 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008446 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8447 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8448 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308449
Jeff Johnson295189b2012-06-20 16:38:30 -07008450 if (!HAL_STATUS_SUCCESS( halStatus ))
8451 {
8452 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8453 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308454 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008455 }
8456 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008457
8458 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8459 Note: Firmware image will be read and downloaded inside vos_start API */
8460 status = vos_start( pHddCtx->pvosContext );
8461 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8462 {
8463 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308464 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008465 }
8466
Leo Chang6cec3e22014-01-21 15:33:49 -08008467#ifdef FEATURE_WLAN_CH_AVOID
8468 /* Plug in avoid channel notification callback
8469 * This should happen before ADD_SELF_STA
8470 * FW will send first IND with ADD_SELF_STA REQ from host */
8471 sme_AddChAvoidCallback(pHddCtx->hHal,
8472 hdd_hostapd_ch_avoid_cb);
8473#endif /* FEATURE_WLAN_CH_AVOID */
8474
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008475 /* Exchange capability info between Host and FW and also get versioning info from FW */
8476 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008477
8478 status = hdd_post_voss_start_config( pHddCtx );
8479 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8480 {
8481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8482 __func__);
8483 goto err_vosstop;
8484 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008485
8486#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308487 wlan_hdd_cfg80211_update_reg_info( wiphy );
8488
8489 /* registration of wiphy dev with cfg80211 */
8490 if (0 > wlan_hdd_cfg80211_register(wiphy))
8491 {
8492 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8493 goto err_vosstop;
8494 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008495#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008496
Jeff Johnson295189b2012-06-20 16:38:30 -07008497 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8498 {
8499 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8500 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8501 }
8502 else
8503 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008504 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8505 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8506 if (pAdapter != NULL)
8507 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308508 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008509 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308510 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8511 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8512 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008513
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308514 /* Generate the P2P Device Address. This consists of the device's
8515 * primary MAC address with the locally administered bit set.
8516 */
8517 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008518 }
8519 else
8520 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308521 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8522 if (p2p_dev_addr != NULL)
8523 {
8524 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8525 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8526 }
8527 else
8528 {
8529 hddLog(VOS_TRACE_LEVEL_FATAL,
8530 "%s: Failed to allocate mac_address for p2p_device",
8531 __func__);
8532 goto err_close_adapter;
8533 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008534 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008535
8536 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8537 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8538 if ( NULL == pP2pAdapter )
8539 {
8540 hddLog(VOS_TRACE_LEVEL_FATAL,
8541 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008542 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008543 goto err_close_adapter;
8544 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008545 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008547
8548 if( pAdapter == NULL )
8549 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008550 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8551 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008552 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008553
Arif Hussain66559122013-11-21 10:11:40 -08008554 if (country_code)
8555 {
8556 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008557 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008558 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8559#ifndef CONFIG_ENABLE_LINUX_REG
8560 hdd_checkandupdate_phymode(pAdapter, country_code);
8561#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008562 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8563 (void *)(tSmeChangeCountryCallback)
8564 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008565 country_code,
8566 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308567 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008568 if (eHAL_STATUS_SUCCESS == ret)
8569 {
Arif Hussaincb607082013-12-20 11:57:42 -08008570 ret = wait_for_completion_interruptible_timeout(
8571 &pAdapter->change_country_code,
8572 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8573
8574 if (0 >= ret)
8575 {
8576 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8577 "%s: SME while setting country code timed out", __func__);
8578 }
Arif Hussain66559122013-11-21 10:11:40 -08008579 }
8580 else
8581 {
Arif Hussaincb607082013-12-20 11:57:42 -08008582 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8583 "%s: SME Change Country code from module param fail ret=%d",
8584 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008585 }
8586 }
8587
Jeff Johnson295189b2012-06-20 16:38:30 -07008588#ifdef WLAN_BTAMP_FEATURE
8589 vStatus = WLANBAP_Open(pVosContext);
8590 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8591 {
8592 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8593 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008594 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008595 }
8596
8597 vStatus = BSL_Init(pVosContext);
8598 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8599 {
8600 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8601 "%s: Failed to Init BSL",__func__);
8602 goto err_bap_close;
8603 }
8604 vStatus = WLANBAP_Start(pVosContext);
8605 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8606 {
8607 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8608 "%s: Failed to start TL",__func__);
8609 goto err_bap_close;
8610 }
8611
8612 pConfig = pHddCtx->cfg_ini;
8613 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8614 status = WLANBAP_SetConfig(&btAmpConfig);
8615
8616#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008617
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008618#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8619 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8620 {
8621 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8622 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8623 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8624 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8625 }
8626#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008627#ifdef FEATURE_WLAN_SCAN_PNO
8628 /*SME must send channel update configuration to RIVA*/
8629 sme_UpdateChannelConfig(pHddCtx->hHal);
8630#endif
8631
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308632 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8633
Jeff Johnson295189b2012-06-20 16:38:30 -07008634 /* Register with platform driver as client for Suspend/Resume */
8635 status = hddRegisterPmOps(pHddCtx);
8636 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8637 {
8638 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8639#ifdef WLAN_BTAMP_FEATURE
8640 goto err_bap_stop;
8641#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008642 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008643#endif //WLAN_BTAMP_FEATURE
8644 }
8645
Yue Ma0d4891e2013-08-06 17:01:45 -07008646 /* Open debugfs interface */
8647 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8648 {
8649 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8650 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008651 }
8652
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 /* Register TM level change handler function to the platform */
8654 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8655 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8656 {
8657 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8658 goto err_unregister_pmops;
8659 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008660
8661 /* register for riva power on lock to platform driver */
8662 if (req_riva_power_on_lock("wlan"))
8663 {
8664 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8665 __func__);
8666 goto err_unregister_pmops;
8667 }
8668
Jeff Johnson295189b2012-06-20 16:38:30 -07008669 // register net device notifier for device change notification
8670 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8671
8672 if(ret < 0)
8673 {
8674 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8675 goto err_free_power_on_lock;
8676 }
8677
8678 //Initialize the nlink service
8679 if(nl_srv_init() != 0)
8680 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308681 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008682 goto err_reg_netdev;
8683 }
8684
Leo Chang4ce1cc52013-10-21 18:27:15 -07008685#ifdef WLAN_KD_READY_NOTIFIER
8686 pHddCtx->kd_nl_init = 1;
8687#endif /* WLAN_KD_READY_NOTIFIER */
8688
Jeff Johnson295189b2012-06-20 16:38:30 -07008689 //Initialize the BTC service
8690 if(btc_activate_service(pHddCtx) != 0)
8691 {
8692 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8693 goto err_nl_srv;
8694 }
8695
8696#ifdef PTT_SOCK_SVC_ENABLE
8697 //Initialize the PTT service
8698 if(ptt_sock_activate_svc(pHddCtx) != 0)
8699 {
8700 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8701 goto err_nl_srv;
8702 }
8703#endif
8704
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308705#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8706 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
8707 {
8708 if(wlan_logging_sock_activate_svc(
8709 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
8710 pHddCtx->cfg_ini->wlanLoggingNumBuf))
8711 {
8712 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
8713 " failed", __func__);
8714 goto err_nl_srv;
8715 }
8716 }
8717#endif
8718
Jeff Johnson295189b2012-06-20 16:38:30 -07008719 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008720 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008721 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008722 /* Action frame registered in one adapter which will
8723 * applicable to all interfaces
8724 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008725 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008726 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008727
8728 mutex_init(&pHddCtx->sap_lock);
8729
Mihir Shete18156292014-03-11 15:38:30 +05308730 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008731
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008732#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008733#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8734 /* Initialize the wake lcok */
8735 wake_lock_init(&pHddCtx->rx_wake_lock,
8736 WAKE_LOCK_SUSPEND,
8737 "qcom_rx_wakelock");
8738#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008739 /* Initialize the wake lcok */
8740 wake_lock_init(&pHddCtx->sap_wake_lock,
8741 WAKE_LOCK_SUSPEND,
8742 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008743#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008744
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008745 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8746 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008747
8748 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8749 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308750#ifndef CONFIG_ENABLE_LINUX_REG
8751 /*updating wiphy so that regulatory user hints can be processed*/
8752 if (wiphy)
8753 {
8754 regulatory_hint(wiphy, "00");
8755 }
8756#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008757 // Initialize the restart logic
8758 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308759
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008760 //Register the traffic monitor timer now
8761 if ( pHddCtx->cfg_ini->dynSplitscan)
8762 {
8763 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8764 VOS_TIMER_TYPE_SW,
8765 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8766 (void *)pHddCtx);
8767 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008768 goto success;
8769
8770err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008771#ifdef WLAN_KD_READY_NOTIFIER
8772 nl_srv_exit(pHddCtx->ptt_pid);
8773#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008774 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008775#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008776err_reg_netdev:
8777 unregister_netdevice_notifier(&hdd_netdev_notifier);
8778
8779err_free_power_on_lock:
8780 free_riva_power_on_lock("wlan");
8781
8782err_unregister_pmops:
8783 hddDevTmUnregisterNotifyCallback(pHddCtx);
8784 hddDeregisterPmOps(pHddCtx);
8785
Yue Ma0d4891e2013-08-06 17:01:45 -07008786 hdd_debugfs_exit(pHddCtx);
8787
Jeff Johnson295189b2012-06-20 16:38:30 -07008788#ifdef WLAN_BTAMP_FEATURE
8789err_bap_stop:
8790 WLANBAP_Stop(pVosContext);
8791#endif
8792
8793#ifdef WLAN_BTAMP_FEATURE
8794err_bap_close:
8795 WLANBAP_Close(pVosContext);
8796#endif
8797
Jeff Johnson295189b2012-06-20 16:38:30 -07008798err_close_adapter:
8799 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008800
8801#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308802 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008803#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008804
8805err_vosstop:
8806 vos_stop(pVosContext);
8807
Mihir Shetee1093ba2014-01-21 20:13:32 +05308808err_wiphy_unregister:
8809#ifdef CONFIG_ENABLE_LINUX_REG
8810 wiphy_unregister(wiphy);
8811#endif
8812
Amar Singhala49cbc52013-10-08 18:37:44 -07008813err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008814 status = vos_sched_close( pVosContext );
8815 if (!VOS_IS_STATUS_SUCCESS(status)) {
8816 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8817 "%s: Failed to close VOSS Scheduler", __func__);
8818 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8819 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008820 vos_close(pVosContext );
8821
Amar Singhal0a402232013-10-11 20:57:16 -07008822err_vos_nv_close:
8823
c_hpothue6a36282014-03-19 12:27:38 +05308824#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008825 vos_nv_close();
8826
Jeff Johnson295189b2012-06-20 16:38:30 -07008827err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05308828#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008829 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008830
8831err_wdclose:
8832 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8833 vos_watchdog_close(pVosContext);
8834
Jeff Johnson295189b2012-06-20 16:38:30 -07008835err_config:
8836 kfree(pHddCtx->cfg_ini);
8837 pHddCtx->cfg_ini= NULL;
8838
8839err_free_hdd_context:
8840 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008841 wiphy_free(wiphy) ;
8842 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008843 VOS_BUG(1);
8844
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008845 if (hdd_is_ssr_required())
8846 {
8847 /* WDI timeout had happened during load, so SSR is needed here */
8848 subsystem_restart("wcnss");
8849 msleep(5000);
8850 }
8851 hdd_set_ssr_required (VOS_FALSE);
8852
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008853 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008854
8855success:
8856 EXIT();
8857 return 0;
8858}
8859
8860/**---------------------------------------------------------------------------
8861
Jeff Johnson32d95a32012-09-10 13:15:23 -07008862 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008863
Jeff Johnson32d95a32012-09-10 13:15:23 -07008864 This is the driver entry point - called in different timeline depending
8865 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008866
8867 \param - None
8868
8869 \return - 0 for success, non zero for failure
8870
8871 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008872static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008873{
8874 VOS_STATUS status;
8875 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008876 struct device *dev = NULL;
8877 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008878#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8879 int max_retries = 0;
8880#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008881
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308882#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8883 vos_wconn_trace_init();
8884#endif
8885
Jeff Johnson295189b2012-06-20 16:38:30 -07008886 ENTER();
8887
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008888#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008889 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008890#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008891
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05308892 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07008893 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8894 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8895
8896 //Power Up Libra WLAN card first if not already powered up
8897 status = vos_chipPowerUp(NULL,NULL,NULL);
8898 if (!VOS_IS_STATUS_SUCCESS(status))
8899 {
8900 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8901 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308902#ifdef WLAN_OPEN_SOURCE
8903 wake_lock_destroy(&wlan_wake_lock);
8904#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008905 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008906 }
8907
Jeff Johnson295189b2012-06-20 16:38:30 -07008908#ifdef ANI_BUS_TYPE_PCI
8909
8910 dev = wcnss_wlan_get_device();
8911
8912#endif // ANI_BUS_TYPE_PCI
8913
8914#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008915
8916#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8917 /* wait until WCNSS driver downloads NV */
8918 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8919 msleep(1000);
8920 }
8921 if (max_retries >= 5) {
8922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308923#ifdef WLAN_OPEN_SOURCE
8924 wake_lock_destroy(&wlan_wake_lock);
8925#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008926 return -ENODEV;
8927 }
8928#endif
8929
Jeff Johnson295189b2012-06-20 16:38:30 -07008930 dev = wcnss_wlan_get_device();
8931#endif // ANI_BUS_TYPE_PLATFORM
8932
8933
8934 do {
8935 if (NULL == dev) {
8936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8937 ret_status = -1;
8938 break;
8939 }
8940
Jeff Johnson295189b2012-06-20 16:38:30 -07008941#ifdef TIMER_MANAGER
8942 vos_timer_manager_init();
8943#endif
8944
8945 /* Preopen VOSS so that it is ready to start at least SAL */
8946 status = vos_preOpen(&pVosContext);
8947
8948 if (!VOS_IS_STATUS_SUCCESS(status))
8949 {
8950 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8951 ret_status = -1;
8952 break;
8953 }
8954
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008955#ifndef MODULE
8956 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8957 */
8958 hdd_set_conparam((v_UINT_t)con_mode);
8959#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008960
8961 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008962 if (hdd_wlan_startup(dev))
8963 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008965 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008966 vos_preClose( &pVosContext );
8967 ret_status = -1;
8968 break;
8969 }
8970
8971 /* Cancel the vote for XO Core ON
8972 * This is done here for safety purposes in case we re-initialize without turning
8973 * it OFF in any error scenario.
8974 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008975 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008976 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008977 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008978 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8979 {
8980 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008981 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008982 }
8983 } while (0);
8984
8985 if (0 != ret_status)
8986 {
8987 //Assert Deep sleep signal now to put Libra HW in lowest power state
8988 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8989 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8990
8991 //Vote off any PMIC voltage supplies
8992 vos_chipPowerDown(NULL, NULL, NULL);
8993#ifdef TIMER_MANAGER
8994 vos_timer_exit();
8995#endif
8996#ifdef MEMORY_DEBUG
8997 vos_mem_exit();
8998#endif
8999
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009000#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009001 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009002#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009003 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9004 }
9005 else
9006 {
9007 //Send WLAN UP indication to Nlink Service
9008 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9009
9010 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009011 }
9012
9013 EXIT();
9014
9015 return ret_status;
9016}
9017
Jeff Johnson32d95a32012-09-10 13:15:23 -07009018/**---------------------------------------------------------------------------
9019
9020 \brief hdd_module_init() - Init Function
9021
9022 This is the driver entry point (invoked when module is loaded using insmod)
9023
9024 \param - None
9025
9026 \return - 0 for success, non zero for failure
9027
9028 --------------------------------------------------------------------------*/
9029#ifdef MODULE
9030static int __init hdd_module_init ( void)
9031{
9032 return hdd_driver_init();
9033}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009034#else /* #ifdef MODULE */
9035static int __init hdd_module_init ( void)
9036{
9037 /* Driver initialization is delayed to fwpath_changed_handler */
9038 return 0;
9039}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009040#endif /* #ifdef MODULE */
9041
Jeff Johnson295189b2012-06-20 16:38:30 -07009042
9043/**---------------------------------------------------------------------------
9044
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009045 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009046
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009047 This is the driver exit point (invoked when module is unloaded using rmmod
9048 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009049
9050 \param - None
9051
9052 \return - None
9053
9054 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009055static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009056{
9057 hdd_context_t *pHddCtx = NULL;
9058 v_CONTEXT_t pVosContext = NULL;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309059 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009060
9061 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9062
9063 //Get the global vos context
9064 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9065
9066 if(!pVosContext)
9067 {
9068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9069 goto done;
9070 }
9071
9072 //Get the HDD context.
9073 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9074
9075 if(!pHddCtx)
9076 {
9077 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9078 }
9079 else
9080 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309081 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9082
9083 if (pHddCtx->isLogpInProgress)
9084 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309086 "%s:SSR in Progress; block rmmod !!!", __func__);
9087 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9088 msecs_to_jiffies(30000));
9089 if(!rc)
9090 {
9091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9092 "%s:SSR timedout, fatal error", __func__);
9093 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009094 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009096
Mihir Shete18156292014-03-11 15:38:30 +05309097 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009098 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9099
9100 //Do all the cleanup before deregistering the driver
9101 hdd_wlan_exit(pHddCtx);
9102 }
9103
Jeff Johnson295189b2012-06-20 16:38:30 -07009104 vos_preClose( &pVosContext );
9105
9106#ifdef TIMER_MANAGER
9107 vos_timer_exit();
9108#endif
9109#ifdef MEMORY_DEBUG
9110 vos_mem_exit();
9111#endif
9112
Gopichand Nakkalad0774962013-05-24 11:32:21 +05309113#ifdef WCONN_TRACE_KMSG_LOG_BUFF
9114 vos_wconn_trace_exit();
9115#endif
9116
Jeff Johnson295189b2012-06-20 16:38:30 -07009117done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009118#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009119 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009121 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9122}
9123
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009124/**---------------------------------------------------------------------------
9125
9126 \brief hdd_module_exit() - Exit function
9127
9128 This is the driver exit point (invoked when module is unloaded using rmmod)
9129
9130 \param - None
9131
9132 \return - None
9133
9134 --------------------------------------------------------------------------*/
9135static void __exit hdd_module_exit(void)
9136{
9137 hdd_driver_exit();
9138}
9139
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009140#ifdef MODULE
9141static int fwpath_changed_handler(const char *kmessage,
9142 struct kernel_param *kp)
9143{
Jeff Johnson76052702013-04-16 13:55:05 -07009144 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009145}
9146
9147static int con_mode_handler(const char *kmessage,
9148 struct kernel_param *kp)
9149{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009150 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009151}
9152#else /* #ifdef MODULE */
9153/**---------------------------------------------------------------------------
9154
Jeff Johnson76052702013-04-16 13:55:05 -07009155 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009156
Jeff Johnson76052702013-04-16 13:55:05 -07009157 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009158 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009159 - invoked when module parameter fwpath is modified from userspace to signal
9160 initializing the WLAN driver or when con_mode is modified from userspace
9161 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009162
9163 \return - 0 for success, non zero for failure
9164
9165 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009166static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009167{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009168 int ret_status;
9169
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009170 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009171 ret_status = hdd_driver_init();
9172 wlan_hdd_inited = ret_status ? 0 : 1;
9173 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009174 }
9175
9176 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009177
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009178 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009179
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009180 ret_status = hdd_driver_init();
9181 wlan_hdd_inited = ret_status ? 0 : 1;
9182 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009183}
9184
Jeff Johnson295189b2012-06-20 16:38:30 -07009185/**---------------------------------------------------------------------------
9186
Jeff Johnson76052702013-04-16 13:55:05 -07009187 \brief fwpath_changed_handler() - Handler Function
9188
9189 Handle changes to the fwpath parameter
9190
9191 \return - 0 for success, non zero for failure
9192
9193 --------------------------------------------------------------------------*/
9194static int fwpath_changed_handler(const char *kmessage,
9195 struct kernel_param *kp)
9196{
9197 int ret;
9198
9199 ret = param_set_copystring(kmessage, kp);
9200 if (0 == ret)
9201 ret = kickstart_driver();
9202 return ret;
9203}
9204
9205/**---------------------------------------------------------------------------
9206
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009207 \brief con_mode_handler() -
9208
9209 Handler function for module param con_mode when it is changed by userspace
9210 Dynamically linked - do nothing
9211 Statically linked - exit and init driver, as in rmmod and insmod
9212
Jeff Johnson76052702013-04-16 13:55:05 -07009213 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009214
Jeff Johnson76052702013-04-16 13:55:05 -07009215 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009216
9217 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009218static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009219{
Jeff Johnson76052702013-04-16 13:55:05 -07009220 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009221
Jeff Johnson76052702013-04-16 13:55:05 -07009222 ret = param_set_int(kmessage, kp);
9223 if (0 == ret)
9224 ret = kickstart_driver();
9225 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009226}
9227#endif /* #ifdef MODULE */
9228
9229/**---------------------------------------------------------------------------
9230
Jeff Johnson295189b2012-06-20 16:38:30 -07009231 \brief hdd_get_conparam() -
9232
9233 This is the driver exit point (invoked when module is unloaded using rmmod)
9234
9235 \param - None
9236
9237 \return - tVOS_CON_MODE
9238
9239 --------------------------------------------------------------------------*/
9240tVOS_CON_MODE hdd_get_conparam ( void )
9241{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009242#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009243 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009244#else
9245 return (tVOS_CON_MODE)curr_con_mode;
9246#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009247}
9248void hdd_set_conparam ( v_UINT_t newParam )
9249{
9250 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009251#ifndef MODULE
9252 curr_con_mode = con_mode;
9253#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009254}
9255/**---------------------------------------------------------------------------
9256
9257 \brief hdd_softap_sta_deauth() - function
9258
9259 This to take counter measure to handle deauth req from HDD
9260
9261 \param - pAdapter - Pointer to the HDD
9262
9263 \param - enable - boolean value
9264
9265 \return - None
9266
9267 --------------------------------------------------------------------------*/
9268
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009269VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009270{
Jeff Johnson295189b2012-06-20 16:38:30 -07009271 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009272 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009273
9274 ENTER();
9275
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009276 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9277 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009278
9279 //Ignore request to deauth bcmc station
9280 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009281 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009282
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009283 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009284
9285 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009286 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009287}
9288
9289/**---------------------------------------------------------------------------
9290
9291 \brief hdd_softap_sta_disassoc() - function
9292
9293 This to take counter measure to handle deauth req from HDD
9294
9295 \param - pAdapter - Pointer to the HDD
9296
9297 \param - enable - boolean value
9298
9299 \return - None
9300
9301 --------------------------------------------------------------------------*/
9302
9303void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9304{
9305 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9306
9307 ENTER();
9308
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309309 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009310
9311 //Ignore request to disassoc bcmc station
9312 if( pDestMacAddress[0] & 0x1 )
9313 return;
9314
9315 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9316}
9317
9318void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9319{
9320 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9321
9322 ENTER();
9323
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309324 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009325
9326 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9327}
9328
Jeff Johnson295189b2012-06-20 16:38:30 -07009329/**---------------------------------------------------------------------------
9330 *
9331 * \brief hdd_get__concurrency_mode() -
9332 *
9333 *
9334 * \param - None
9335 *
9336 * \return - CONCURRENCY MODE
9337 *
9338 * --------------------------------------------------------------------------*/
9339tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9340{
9341 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9342 hdd_context_t *pHddCtx;
9343
9344 if (NULL != pVosContext)
9345 {
9346 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9347 if (NULL != pHddCtx)
9348 {
9349 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9350 }
9351 }
9352
9353 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009354 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009355 return VOS_STA;
9356}
9357
9358/* Decide whether to allow/not the apps power collapse.
9359 * Allow apps power collapse if we are in connected state.
9360 * if not, allow only if we are in IMPS */
9361v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9362{
9363 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009364 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009365 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009366 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9367 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9368 hdd_adapter_t *pAdapter = NULL;
9369 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009370 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009371
Jeff Johnson295189b2012-06-20 16:38:30 -07009372 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9373 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009374
Yathish9f22e662012-12-10 14:21:35 -08009375 concurrent_state = hdd_get_concurrency_mode();
9376
9377#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9378 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9379 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9380 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9381 return TRUE;
9382#endif
9383
Jeff Johnson295189b2012-06-20 16:38:30 -07009384 /*loop through all adapters. TBD fix for Concurrency */
9385 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9386 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9387 {
9388 pAdapter = pAdapterNode->pAdapter;
9389 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9390 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9391 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009392 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009393 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009394 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009395 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9396 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009397 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009398 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009399 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9400 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009401 return FALSE;
9402 }
9403 }
9404 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9405 pAdapterNode = pNext;
9406 }
9407 return TRUE;
9408}
9409
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009410/* Decides whether to send suspend notification to Riva
9411 * if any adapter is in BMPS; then it is required */
9412v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9413{
9414 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9415 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9416
9417 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9418 {
9419 return TRUE;
9420 }
9421 return FALSE;
9422}
9423
Jeff Johnson295189b2012-06-20 16:38:30 -07009424void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9425{
9426 switch(mode)
9427 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009428 case VOS_STA_MODE:
9429 case VOS_P2P_CLIENT_MODE:
9430 case VOS_P2P_GO_MODE:
9431 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009432 pHddCtx->concurrency_mode |= (1 << mode);
9433 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009434 break;
9435 default:
9436 break;
9437
9438 }
9439 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9440 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9441}
9442
9443
9444void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9445{
9446 switch(mode)
9447 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009448 case VOS_STA_MODE:
9449 case VOS_P2P_CLIENT_MODE:
9450 case VOS_P2P_GO_MODE:
9451 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009452 pHddCtx->no_of_sessions[mode]--;
9453 if (!(pHddCtx->no_of_sessions[mode]))
9454 pHddCtx->concurrency_mode &= (~(1 << mode));
9455 break;
9456 default:
9457 break;
9458 }
9459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9460 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9461}
9462
Jeff Johnsone7245742012-09-05 17:12:55 -07009463/**---------------------------------------------------------------------------
9464 *
9465 * \brief wlan_hdd_restart_init
9466 *
9467 * This function initalizes restart timer/flag. An internal function.
9468 *
9469 * \param - pHddCtx
9470 *
9471 * \return - None
9472 *
9473 * --------------------------------------------------------------------------*/
9474
9475static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9476{
9477 /* Initialize */
9478 pHddCtx->hdd_restart_retries = 0;
9479 atomic_set(&pHddCtx->isRestartInProgress, 0);
9480 vos_timer_init(&pHddCtx->hdd_restart_timer,
9481 VOS_TIMER_TYPE_SW,
9482 wlan_hdd_restart_timer_cb,
9483 pHddCtx);
9484}
9485/**---------------------------------------------------------------------------
9486 *
9487 * \brief wlan_hdd_restart_deinit
9488 *
9489 * This function cleans up the resources used. An internal function.
9490 *
9491 * \param - pHddCtx
9492 *
9493 * \return - None
9494 *
9495 * --------------------------------------------------------------------------*/
9496
9497static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9498{
9499
9500 VOS_STATUS vos_status;
9501 /* Block any further calls */
9502 atomic_set(&pHddCtx->isRestartInProgress, 1);
9503 /* Cleanup */
9504 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9505 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309506 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009507 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9508 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309509 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009510
9511}
9512
9513/**---------------------------------------------------------------------------
9514 *
9515 * \brief wlan_hdd_framework_restart
9516 *
9517 * This function uses a cfg80211 API to start a framework initiated WLAN
9518 * driver module unload/load.
9519 *
9520 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9521 *
9522 *
9523 * \param - pHddCtx
9524 *
9525 * \return - VOS_STATUS_SUCCESS: Success
9526 * VOS_STATUS_E_EMPTY: Adapter is Empty
9527 * VOS_STATUS_E_NOMEM: No memory
9528
9529 * --------------------------------------------------------------------------*/
9530
9531static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9532{
9533 VOS_STATUS status = VOS_STATUS_SUCCESS;
9534 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009535 int len = (sizeof (struct ieee80211_mgmt));
9536 struct ieee80211_mgmt *mgmt = NULL;
9537
9538 /* Prepare the DEAUTH managment frame with reason code */
9539 mgmt = kzalloc(len, GFP_KERNEL);
9540 if(mgmt == NULL)
9541 {
9542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9543 "%s: memory allocation failed (%d bytes)", __func__, len);
9544 return VOS_STATUS_E_NOMEM;
9545 }
9546 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009547
9548 /* Iterate over all adapters/devices */
9549 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9550 do
9551 {
9552 if( (status == VOS_STATUS_SUCCESS) &&
9553 pAdapterNode &&
9554 pAdapterNode->pAdapter)
9555 {
9556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9557 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9558 pAdapterNode->pAdapter->dev->name,
9559 pAdapterNode->pAdapter->device_mode,
9560 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009561 /*
9562 * CFG80211 event to restart the driver
9563 *
9564 * 'cfg80211_send_unprot_deauth' sends a
9565 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9566 * of SME(Linux Kernel) state machine.
9567 *
9568 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9569 * the driver.
9570 *
9571 */
9572
9573 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009574 }
9575 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9576 pAdapterNode = pNext;
9577 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9578
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009579
9580 /* Free the allocated management frame */
9581 kfree(mgmt);
9582
Jeff Johnsone7245742012-09-05 17:12:55 -07009583 /* Retry until we unload or reach max count */
9584 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9585 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9586
9587 return status;
9588
9589}
9590/**---------------------------------------------------------------------------
9591 *
9592 * \brief wlan_hdd_restart_timer_cb
9593 *
9594 * Restart timer callback. An internal function.
9595 *
9596 * \param - User data:
9597 *
9598 * \return - None
9599 *
9600 * --------------------------------------------------------------------------*/
9601
9602void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9603{
9604 hdd_context_t *pHddCtx = usrDataForCallback;
9605 wlan_hdd_framework_restart(pHddCtx);
9606 return;
9607
9608}
9609
9610
9611/**---------------------------------------------------------------------------
9612 *
9613 * \brief wlan_hdd_restart_driver
9614 *
9615 * This function sends an event to supplicant to restart the WLAN driver.
9616 *
9617 * This function is called from vos_wlanRestart.
9618 *
9619 * \param - pHddCtx
9620 *
9621 * \return - VOS_STATUS_SUCCESS: Success
9622 * VOS_STATUS_E_EMPTY: Adapter is Empty
9623 * VOS_STATUS_E_ALREADY: Request already in progress
9624
9625 * --------------------------------------------------------------------------*/
9626VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9627{
9628 VOS_STATUS status = VOS_STATUS_SUCCESS;
9629
9630 /* A tight check to make sure reentrancy */
9631 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9632 {
9633 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9634 "%s: WLAN restart is already in progress", __func__);
9635
9636 return VOS_STATUS_E_ALREADY;
9637 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009638 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009639#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009640 wcnss_reset_intr();
9641#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009642
Jeff Johnsone7245742012-09-05 17:12:55 -07009643 return status;
9644}
9645
Mihir Shetee1093ba2014-01-21 20:13:32 +05309646/**---------------------------------------------------------------------------
9647 *
9648 * \brief wlan_hdd_init_channels
9649 *
9650 * This function is used to initialize the channel list in CSR
9651 *
9652 * This function is called from hdd_wlan_startup
9653 *
9654 * \param - pHddCtx: HDD context
9655 *
9656 * \return - VOS_STATUS_SUCCESS: Success
9657 * VOS_STATUS_E_FAULT: Failure reported by SME
9658
9659 * --------------------------------------------------------------------------*/
9660static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9661{
9662 eHalStatus status;
9663
9664 status = sme_InitChannels(pHddCtx->hHal);
9665 if (HAL_STATUS_SUCCESS(status))
9666 {
9667 return VOS_STATUS_SUCCESS;
9668 }
9669 else
9670 {
9671 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9672 __func__, status);
9673 return VOS_STATUS_E_FAULT;
9674 }
9675}
9676
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009677/*
9678 * API to find if there is any STA or P2P-Client is connected
9679 */
9680VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9681{
9682 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9683}
Jeff Johnsone7245742012-09-05 17:12:55 -07009684
Jeff Johnson295189b2012-06-20 16:38:30 -07009685//Register the module init/exit functions
9686module_init(hdd_module_init);
9687module_exit(hdd_module_exit);
9688
9689MODULE_LICENSE("Dual BSD/GPL");
9690MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9691MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9692
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009693module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9694 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009695
Jeff Johnson76052702013-04-16 13:55:05 -07009696module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009697 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009698
9699module_param(enable_dfs_chan_scan, int,
9700 S_IRUSR | S_IRGRP | S_IROTH);
9701
9702module_param(enable_11d, int,
9703 S_IRUSR | S_IRGRP | S_IROTH);
9704
9705module_param(country_code, charp,
9706 S_IRUSR | S_IRGRP | S_IROTH);