blob: 6abc8ba29429c5a1ecdeef8720edc72cd8b1ec49 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lama7f454d2014-07-24 12:04:06 -070023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080026 */
Kiet Lam842dad02014-02-18 18:44:02 -080027
28
Kiet Lama7f454d2014-07-24 12:04:06 -070029
30
Jeff Johnson295189b2012-06-20 16:38:30 -070031/*========================================================================
32
33 \file wlan_hdd_main.c
34
35 \brief WLAN Host Device Driver implementation
36
37 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
38
39 Qualcomm Confidential and Proprietary.
40
41 ========================================================================*/
42
43/**=========================================================================
44
45 EDIT HISTORY FOR FILE
46
47
48 This section contains comments describing changes made to the module.
49 Notice that changes are listed in reverse chronological order.
50
51
52 $Header:$ $DateTime: $ $Author: $
53
54
55 when who what, where, why
56 -------- --- --------------------------------------------------------
57 04/5/09 Shailender Created module.
58 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
59 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
60 ==========================================================================*/
61
62/*--------------------------------------------------------------------------
63 Include Files
64 ------------------------------------------------------------------------*/
65//#include <wlan_qct_driver.h>
66#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070067#include <vos_api.h>
68#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070069#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
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530143#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700144/* 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;
c_hpothu92367912014-05-01 15:18:17 +0530155static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800156
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700157#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700158static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700159#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700160
Jeff Johnsone7245742012-09-05 17:12:55 -0700161/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800162 * spinlock for synchronizing asynchronous request/response
163 * (full description of use in wlan_hdd_main.h)
164 */
165DEFINE_SPINLOCK(hdd_context_lock);
166
167/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700168 * The rate at which the driver sends RESTART event to supplicant
169 * once the function 'vos_wlanRestart()' is called
170 *
171 */
172#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
173#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700174
175/*
176 * Size of Driver command strings from upper layer
177 */
178#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
179#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
180
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800181#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700182#define TID_MIN_VALUE 0
183#define TID_MAX_VALUE 15
184static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
185 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800186static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
187 tCsrEseBeaconReq *pEseBcnReq);
188#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700189
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +0530190static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx);
Atul Mittal1d722422014-03-19 11:15:07 +0530191/*
192 * Maximum buffer size used for returning the data back to user space
193 */
194#define WLAN_MAX_BUF_SIZE 1024
195#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700196
c_hpothu92367912014-05-01 15:18:17 +0530197//wait time for beacon miss rate.
198#define BCN_MISS_RATE_TIME 500
199
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800200#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700201static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700202#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700203/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700204static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700205
206//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700207static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
208static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
209static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
210void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800211void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700212
Jeff Johnson295189b2012-06-20 16:38:30 -0700213v_U16_t hdd_select_queue(struct net_device *dev,
214 struct sk_buff *skb);
215
216#ifdef WLAN_FEATURE_PACKET_FILTERING
217static void hdd_set_multicast_list(struct net_device *dev);
218#endif
219
220void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
221
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800222#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800223void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
224static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700225static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
226 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
227 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700228static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
229 tANI_U8 *pTargetApBssid,
230 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800231#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800232#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700233VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800234#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700235
Mihir Shetee1093ba2014-01-21 20:13:32 +0530236static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530237const char * hdd_device_modetoString(v_U8_t device_mode)
238{
239 switch(device_mode)
240 {
241 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
242 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
243 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
244 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
245 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
246 CASE_RETURN_STRING( WLAN_HDD_FTM );
247 CASE_RETURN_STRING( WLAN_HDD_IBSS );
248 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
249 default:
250 return "device_mode Unknown";
251 }
252}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530253
Jeff Johnson295189b2012-06-20 16:38:30 -0700254static int hdd_netdev_notifier_call(struct notifier_block * nb,
255 unsigned long state,
256 void *ndev)
257{
258 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700259 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700260 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700261#ifdef WLAN_BTAMP_FEATURE
262 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700263#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530264 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700265
266 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700267 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700268 (strncmp(dev->name, "p2p", 3)))
269 return NOTIFY_DONE;
270
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700272 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700273
Jeff Johnson27cee452013-03-27 11:10:24 -0700274 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800276 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 VOS_ASSERT(0);
278 return NOTIFY_DONE;
279 }
280
Jeff Johnson27cee452013-03-27 11:10:24 -0700281 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
282 if (NULL == pHddCtx)
283 {
284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
285 VOS_ASSERT(0);
286 return NOTIFY_DONE;
287 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800288 if (pHddCtx->isLogpInProgress)
289 return NOTIFY_DONE;
290
Jeff Johnson27cee452013-03-27 11:10:24 -0700291
292 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
293 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294
295 switch (state) {
296 case NETDEV_REGISTER:
297 break;
298
299 case NETDEV_UNREGISTER:
300 break;
301
302 case NETDEV_UP:
303 break;
304
305 case NETDEV_DOWN:
306 break;
307
308 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700309 if(TRUE == pAdapter->isLinkUpSvcNeeded)
310 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 break;
312
313 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530314 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530315 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530316 {
317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
318 "%s: Timeout occurred while waiting for abortscan %ld",
319 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 }
321 else
322 {
323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530324 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 }
326#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700327 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 status = WLANBAP_StopAmp();
329 if(VOS_STATUS_SUCCESS != status )
330 {
331 pHddCtx->isAmpAllowed = VOS_TRUE;
332 hddLog(VOS_TRACE_LEVEL_FATAL,
333 "%s: Failed to stop AMP", __func__);
334 }
335 else
336 {
337 //a state m/c implementation in PAL is TBD to avoid this delay
338 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700339 if ( pHddCtx->isAmpAllowed )
340 {
341 WLANBAP_DeregisterFromHCI();
342 pHddCtx->isAmpAllowed = VOS_FALSE;
343 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 }
345#endif //WLAN_BTAMP_FEATURE
346 break;
347
348 default:
349 break;
350 }
351
352 return NOTIFY_DONE;
353}
354
355struct notifier_block hdd_netdev_notifier = {
356 .notifier_call = hdd_netdev_notifier_call,
357};
358
359/*---------------------------------------------------------------------------
360 * Function definitions
361 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700362void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
363void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700364//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700365static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700366#ifndef MODULE
367/* current con_mode - used only for statically linked driver
368 * con_mode is changed by userspace to indicate a mode change which will
369 * result in calling the module exit and init functions. The module
370 * exit function will clean up based on the value of con_mode prior to it
371 * being changed by userspace. So curr_con_mode records the current con_mode
372 * for exit when con_mode becomes the next mode for init
373 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700374static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700375#endif
376
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800377/**---------------------------------------------------------------------------
378
379 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
380
381 Called immediately after the cfg.ini is read in order to configure
382 the desired trace levels.
383
384 \param - moduleId - module whose trace level is being configured
385 \param - bitmask - bitmask of log levels to be enabled
386
387 \return - void
388
389 --------------------------------------------------------------------------*/
390static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
391{
392 wpt_tracelevel level;
393
394 /* if the bitmask is the default value, then a bitmask was not
395 specified in cfg.ini, so leave the logging level alone (it
396 will remain at the "compiled in" default value) */
397 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
398 {
399 return;
400 }
401
402 /* a mask was specified. start by disabling all logging */
403 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
404
405 /* now cycle through the bitmask until all "set" bits are serviced */
406 level = VOS_TRACE_LEVEL_FATAL;
407 while (0 != bitmask)
408 {
409 if (bitmask & 1)
410 {
411 vos_trace_setValue(moduleId, level, 1);
412 }
413 level++;
414 bitmask >>= 1;
415 }
416}
417
418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419/**---------------------------------------------------------------------------
420
421 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
422
423 Called immediately after the cfg.ini is read in order to configure
424 the desired trace levels in the WDI.
425
426 \param - moduleId - module whose trace level is being configured
427 \param - bitmask - bitmask of log levels to be enabled
428
429 \return - void
430
431 --------------------------------------------------------------------------*/
432static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
433{
434 wpt_tracelevel level;
435
436 /* if the bitmask is the default value, then a bitmask was not
437 specified in cfg.ini, so leave the logging level alone (it
438 will remain at the "compiled in" default value) */
439 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
440 {
441 return;
442 }
443
444 /* a mask was specified. start by disabling all logging */
445 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
446
447 /* now cycle through the bitmask until all "set" bits are serviced */
448 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
449 while (0 != bitmask)
450 {
451 if (bitmask & 1)
452 {
453 wpalTraceSetLevel(moduleId, level, 1);
454 }
455 level++;
456 bitmask >>= 1;
457 }
458}
Jeff Johnson295189b2012-06-20 16:38:30 -0700459
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530460/*
461 * FUNCTION: wlan_hdd_validate_context
462 * This function is used to check the HDD context
463 */
464int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
465{
466 ENTER();
467
468 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
469 {
470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
471 "%s: HDD context is Null", __func__);
472 return -ENODEV;
473 }
474
475 if (pHddCtx->isLogpInProgress)
476 {
477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
478 "%s: LOGP in Progress. Ignore!!!", __func__);
479 return -EAGAIN;
480 }
481
Mihir Shete18156292014-03-11 15:38:30 +0530482 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530483 {
484 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
485 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
486 return -EAGAIN;
487 }
488 return 0;
489}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700490#ifdef CONFIG_ENABLE_LINUX_REG
491void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
492{
493 hdd_adapter_t *pAdapter = NULL;
494 hdd_station_ctx_t *pHddStaCtx = NULL;
495 eCsrPhyMode phyMode;
496 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530497
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700498 if (NULL == pHddCtx)
499 {
500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
501 "HDD Context is null !!");
502 return ;
503 }
504
505 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
506 if (NULL == pAdapter)
507 {
508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
509 "pAdapter is null !!");
510 return ;
511 }
512
513 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
514 if (NULL == pHddStaCtx)
515 {
516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
517 "pHddStaCtx is null !!");
518 return ;
519 }
520
521 cfg_param = pHddCtx->cfg_ini;
522 if (NULL == cfg_param)
523 {
524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
525 "cfg_params not available !!");
526 return ;
527 }
528
529 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
530
531 if (!pHddCtx->isVHT80Allowed)
532 {
533 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
534 (eCSR_DOT11_MODE_11ac == phyMode) ||
535 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
536 {
537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
538 "Setting phymode to 11n!!");
539 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
540 }
541 }
542 else
543 {
544 /*New country Supports 11ac as well resetting value back from .ini*/
545 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
546 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
547 return ;
548 }
549
550 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
551 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
552 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
553 {
554 VOS_STATUS vosStatus;
555
556 // need to issue a disconnect to CSR.
557 INIT_COMPLETION(pAdapter->disconnect_comp_var);
558 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
559 pAdapter->sessionId,
560 eCSR_DISCONNECT_REASON_UNSPECIFIED );
561
562 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530563 {
564 long ret;
565
566 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700567 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530568 if (0 >= ret)
569 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
570 ret);
571 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700572
573 }
574}
575#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530576void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
577{
578 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
579 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
580 hdd_config_t *cfg_param;
581 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530582 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530583
584 if (NULL == pHddCtx)
585 {
586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
587 "HDD Context is null !!");
588 return ;
589 }
590
591 cfg_param = pHddCtx->cfg_ini;
592
593 if (NULL == cfg_param)
594 {
595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
596 "cfg_params not available !!");
597 return ;
598 }
599
600 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
601
602 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
603 {
604 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
605 (eCSR_DOT11_MODE_11ac == phyMode) ||
606 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
607 {
608 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
609 "Setting phymode to 11n!!");
610 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
611 }
612 }
613 else
614 {
615 /*New country Supports 11ac as well resetting value back from .ini*/
616 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
617 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
618 return ;
619 }
620
621 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
622 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
623 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
624 {
625 VOS_STATUS vosStatus;
626
627 // need to issue a disconnect to CSR.
628 INIT_COMPLETION(pAdapter->disconnect_comp_var);
629 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
630 pAdapter->sessionId,
631 eCSR_DISCONNECT_REASON_UNSPECIFIED );
632
633 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530634 {
635 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530636 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530637 if (ret <= 0)
638 {
639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
640 "wait on disconnect_comp_var is failed %ld", ret);
641 }
642 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530643
644 }
645}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700646#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530647
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700648void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
649{
650 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
651 hdd_config_t *cfg_param;
652
653 if (NULL == pHddCtx)
654 {
655 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
656 "HDD Context is null !!");
657 return ;
658 }
659
660 cfg_param = pHddCtx->cfg_ini;
661
662 if (NULL == cfg_param)
663 {
664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
665 "cfg_params not available !!");
666 return ;
667 }
668
Agarwal Ashish738843c2014-09-25 12:27:56 +0530669 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
670 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700671 {
672 /*New country doesn't support DFS */
673 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
674 }
675 else
676 {
677 /*New country Supports DFS as well resetting value back from .ini*/
678 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
679 }
680
681}
682
Rajeev79dbe4c2013-10-05 11:03:42 +0530683#ifdef FEATURE_WLAN_BATCH_SCAN
684
685/**---------------------------------------------------------------------------
686
687 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
688 input string
689
690 This function extracts assigned integer from string in below format:
691 "STRING=10" : extracts integer 10 from this string
692
693 \param - pInPtr Pointer to input string
694 \param - base Base for string to int conversion(10 for decimal 16 for hex)
695 \param - pOutPtr Pointer to variable in which extracted integer needs to be
696 assigned
697 \param - pLastArg to tell whether it is last arguement in input string or
698 not
699
700 \return - NULL for failure cases
701 pointer to next arguement in input string for success cases
702 --------------------------------------------------------------------------*/
703static tANI_U8 *
704hdd_extract_assigned_int_from_str
705(
706 tANI_U8 *pInPtr,
707 tANI_U8 base,
708 tANI_U32 *pOutPtr,
709 tANI_U8 *pLastArg
710)
711{
712 int tempInt;
713 int v = 0;
714 char buf[32];
715 int val = 0;
716 *pLastArg = FALSE;
717
718 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
719 if (NULL == pInPtr)
720 {
721 return NULL;
722 }
723
724 pInPtr++;
725
726 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
727
728 val = sscanf(pInPtr, "%32s ", buf);
729 if (val < 0 && val > strlen(pInPtr))
730 {
731 return NULL;
732 }
733 pInPtr += val;
734 v = kstrtos32(buf, base, &tempInt);
735 if (v < 0)
736 {
737 return NULL;
738 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800739 if (tempInt < 0)
740 {
741 tempInt = 0;
742 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530743 *pOutPtr = tempInt;
744
745 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
746 if (NULL == pInPtr)
747 {
748 *pLastArg = TRUE;
749 return NULL;
750 }
751 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
752
753 return pInPtr;
754}
755
756/**---------------------------------------------------------------------------
757
758 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
759 input string
760
761 This function extracts assigned character from string in below format:
762 "STRING=A" : extracts char 'A' from this string
763
764 \param - pInPtr Pointer to input string
765 \param - pOutPtr Pointer to variable in which extracted char needs to be
766 assigned
767 \param - pLastArg to tell whether it is last arguement in input string or
768 not
769
770 \return - NULL for failure cases
771 pointer to next arguement in input string for success cases
772 --------------------------------------------------------------------------*/
773static tANI_U8 *
774hdd_extract_assigned_char_from_str
775(
776 tANI_U8 *pInPtr,
777 tANI_U8 *pOutPtr,
778 tANI_U8 *pLastArg
779)
780{
781 *pLastArg = FALSE;
782
783 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
784 if (NULL == pInPtr)
785 {
786 return NULL;
787 }
788
789 pInPtr++;
790
791 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
792
793 *pOutPtr = *pInPtr;
794
795 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
796 if (NULL == pInPtr)
797 {
798 *pLastArg = TRUE;
799 return NULL;
800 }
801 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
802
803 return pInPtr;
804}
805
806
807/**---------------------------------------------------------------------------
808
809 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
810
811 This function parses set batch scan command in below format:
812 WLS_BATCHING_SET <space> followed by below arguements
813 "SCANFREQ=XX" : Optional defaults to 30 sec
814 "MSCAN=XX" : Required number of scans to attempt to batch
815 "BESTN=XX" : Best Network (RSSI) defaults to 16
816 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
817 A. implies only 5 GHz , B. implies only 2.4GHz
818 "RTT=X" : optional defaults to 0
819 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
820 error
821
822 For example input commands:
823 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
824 translated into set batch scan with following parameters:
825 a) Frequence 60 seconds
826 b) Batch 10 scans together
827 c) Best RSSI to be 20
828 d) 5GHz band only
829 e) RTT is equal to 0
830
831 \param - pValue Pointer to input channel list
832 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
833
834 \return - 0 for success non-zero for failure
835
836 --------------------------------------------------------------------------*/
837static int
838hdd_parse_set_batchscan_command
839(
840 tANI_U8 *pValue,
841 tSirSetBatchScanReq *pHddSetBatchScanReq
842)
843{
844 tANI_U8 *inPtr = pValue;
845 tANI_U8 val = 0;
846 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800847 tANI_U32 nScanFreq;
848 tANI_U32 nMscan;
849 tANI_U32 nBestN;
850 tANI_U8 ucRfBand;
851 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800852 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530853
854 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800855 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
856 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
857 nRtt = 0;
858 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530859
860 /*go to space after WLS_BATCHING_SET command*/
861 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
862 /*no argument after the command*/
863 if (NULL == inPtr)
864 {
865 return -EINVAL;
866 }
867
868 /*no space after the command*/
869 else if (SPACE_ASCII_VALUE != *inPtr)
870 {
871 return -EINVAL;
872 }
873
874 /*removing empty spaces*/
875 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
876
877 /*no argument followed by spaces*/
878 if ('\0' == *inPtr)
879 {
880 return -EINVAL;
881 }
882
883 /*check and parse SCANFREQ*/
884 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
885 {
886 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800887 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800888
Rajeev Kumarc933d982013-11-18 20:04:20 -0800889 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800890 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800891 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800892 }
893
Rajeev79dbe4c2013-10-05 11:03:42 +0530894 if ( (NULL == inPtr) || (TRUE == lastArg))
895 {
896 return -EINVAL;
897 }
898 }
899
900 /*check and parse MSCAN*/
901 if ((strncmp(inPtr, "MSCAN", 5) == 0))
902 {
903 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800904 &nMscan, &lastArg);
905
906 if (0 == nMscan)
907 {
908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
909 "invalid MSCAN=%d", nMscan);
910 return -EINVAL;
911 }
912
Rajeev79dbe4c2013-10-05 11:03:42 +0530913 if (TRUE == lastArg)
914 {
915 goto done;
916 }
917 else if (NULL == inPtr)
918 {
919 return -EINVAL;
920 }
921 }
922 else
923 {
924 return -EINVAL;
925 }
926
927 /*check and parse BESTN*/
928 if ((strncmp(inPtr, "BESTN", 5) == 0))
929 {
930 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800931 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800932
Rajeev Kumarc933d982013-11-18 20:04:20 -0800933 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800934 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800935 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800936 }
937
Rajeev79dbe4c2013-10-05 11:03:42 +0530938 if (TRUE == lastArg)
939 {
940 goto done;
941 }
942 else if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946 }
947
948 /*check and parse CHANNEL*/
949 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
950 {
951 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800952
Rajeev79dbe4c2013-10-05 11:03:42 +0530953 if (('A' == val) || ('a' == val))
954 {
c_hpothuebf89732014-02-25 13:00:24 +0530955 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530956 }
957 else if (('B' == val) || ('b' == val))
958 {
c_hpothuebf89732014-02-25 13:00:24 +0530959 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530960 }
961 else
962 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800963 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
964 }
965
966 if (TRUE == lastArg)
967 {
968 goto done;
969 }
970 else if (NULL == inPtr)
971 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530972 return -EINVAL;
973 }
974 }
975
976 /*check and parse RTT*/
977 if ((strncmp(inPtr, "RTT", 3) == 0))
978 {
979 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800980 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530981 if (TRUE == lastArg)
982 {
983 goto done;
984 }
985 if (NULL == inPtr)
986 {
987 return -EINVAL;
988 }
989 }
990
991
992done:
993
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800994 pHddSetBatchScanReq->scanFrequency = nScanFreq;
995 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
996 pHddSetBatchScanReq->bestNetwork = nBestN;
997 pHddSetBatchScanReq->rfBand = ucRfBand;
998 pHddSetBatchScanReq->rtt = nRtt;
999
Rajeev79dbe4c2013-10-05 11:03:42 +05301000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1001 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1002 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1003 pHddSetBatchScanReq->scanFrequency,
1004 pHddSetBatchScanReq->numberOfScansToBatch,
1005 pHddSetBatchScanReq->bestNetwork,
1006 pHddSetBatchScanReq->rfBand,
1007 pHddSetBatchScanReq->rtt);
1008
1009 return 0;
1010}/*End of hdd_parse_set_batchscan_command*/
1011
1012/**---------------------------------------------------------------------------
1013
1014 \brief hdd_set_batch_scan_req_callback () - This function is called after
1015 receiving set batch scan response from FW and it saves set batch scan
1016 response data FW to HDD context and sets the completion event on
1017 which hdd_ioctl is waiting
1018
1019 \param - callbackContext Pointer to HDD adapter
1020 \param - pRsp Pointer to set batch scan response data received from FW
1021
1022 \return - nothing
1023
1024 --------------------------------------------------------------------------*/
1025static void hdd_set_batch_scan_req_callback
1026(
1027 void *callbackContext,
1028 tSirSetBatchScanRsp *pRsp
1029)
1030{
1031 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1032 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1033
1034 /*sanity check*/
1035 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1036 {
1037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1038 "%s: Invalid pAdapter magic", __func__);
1039 VOS_ASSERT(0);
1040 return;
1041 }
1042 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1043
1044 /*save set batch scan response*/
1045 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1046
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1048 "Received set batch scan rsp from FW with nScansToBatch=%d",
1049 pHddSetBatchScanRsp->nScansToBatch);
1050
1051 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1052 complete(&pAdapter->hdd_set_batch_scan_req_var);
1053
1054 return;
1055}/*End of hdd_set_batch_scan_req_callback*/
1056
1057
1058/**---------------------------------------------------------------------------
1059
1060 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1061 info in hdd batch scan response queue
1062
1063 \param - pAdapter Pointer to hdd adapter
1064 \param - pAPMetaInfo Pointer to access point meta info
1065 \param - scanId scan ID of batch scan response
1066 \param - isLastAp tells whether AP is last AP in batch scan response or not
1067
1068 \return - nothing
1069
1070 --------------------------------------------------------------------------*/
1071static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1072 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1073{
1074 tHddBatchScanRsp *pHead;
1075 tHddBatchScanRsp *pNode;
1076 tHddBatchScanRsp *pPrev;
1077 tHddBatchScanRsp *pTemp;
1078 tANI_U8 ssidLen;
1079
1080 /*head of hdd batch scan response queue*/
1081 pHead = pAdapter->pBatchScanRsp;
1082
1083 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1084 if (NULL == pNode)
1085 {
1086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1087 "%s: Could not allocate memory", __func__);
1088 VOS_ASSERT(0);
1089 return;
1090 }
1091
1092 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1093 sizeof(pNode->ApInfo.bssid));
1094 ssidLen = strlen(pApMetaInfo->ssid);
1095 if (SIR_MAX_SSID_SIZE < ssidLen)
1096 {
1097 /*invalid scan result*/
1098 vos_mem_free(pNode);
1099 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1101 return;
1102 }
1103 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1104 /*null terminate ssid*/
1105 pNode->ApInfo.ssid[ssidLen] = '\0';
1106 pNode->ApInfo.ch = pApMetaInfo->ch;
1107 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1108 pNode->ApInfo.age = pApMetaInfo->timestamp;
1109 pNode->ApInfo.batchId = scanId;
1110 pNode->ApInfo.isLastAp = isLastAp;
1111
1112 pNode->pNext = NULL;
1113 if (NULL == pHead)
1114 {
1115 pAdapter->pBatchScanRsp = pNode;
1116 }
1117 else
1118 {
1119 pTemp = pHead;
1120 while (NULL != pTemp)
1121 {
1122 pPrev = pTemp;
1123 pTemp = pTemp->pNext;
1124 }
1125 pPrev->pNext = pNode;
1126 }
1127
1128 return;
1129}/*End of hdd_populate_batch_scan_rsp_queue*/
1130
1131/**---------------------------------------------------------------------------
1132
1133 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1134 receiving batch scan response indication from FW. It saves get batch scan
1135 response data in HDD batch scan response queue. This callback sets the
1136 completion event on which hdd_ioctl is waiting only after getting complete
1137 batch scan response data from FW
1138
1139 \param - callbackContext Pointer to HDD adapter
1140 \param - pRsp Pointer to get batch scan response data received from FW
1141
1142 \return - nothing
1143
1144 --------------------------------------------------------------------------*/
1145static void hdd_batch_scan_result_ind_callback
1146(
1147 void *callbackContext,
1148 void *pRsp
1149)
1150{
1151 v_BOOL_t isLastAp;
1152 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001153 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301154 tANI_U32 numberScanList;
1155 tANI_U32 nextScanListOffset;
1156 tANI_U32 nextApMetaInfoOffset;
1157 hdd_adapter_t* pAdapter;
1158 tpSirBatchScanList pScanList;
1159 tpSirBatchScanNetworkInfo pApMetaInfo;
1160 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1161 tSirSetBatchScanReq *pReq;
1162
1163 pAdapter = (hdd_adapter_t *)callbackContext;
1164 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001165 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301166 {
1167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: Invalid pAdapter magic", __func__);
1169 VOS_ASSERT(0);
1170 return;
1171 }
1172
1173 /*initialize locals*/
1174 pReq = &pAdapter->hddSetBatchScanReq;
1175 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1176 isLastAp = FALSE;
1177 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001178 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301179 numberScanList = 0;
1180 nextScanListOffset = 0;
1181 nextApMetaInfoOffset = 0;
1182 pScanList = NULL;
1183 pApMetaInfo = NULL;
1184
1185 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1186 {
1187 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1188 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1189 isLastAp = TRUE;
1190 goto done;
1191 }
1192
1193 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "Batch scan rsp: numberScalList %d", numberScanList);
1196
1197 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1198 {
1199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1200 "%s: numberScanList %d", __func__, numberScanList);
1201 isLastAp = TRUE;
1202 goto done;
1203 }
1204
1205 while (numberScanList)
1206 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001207 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301208 nextScanListOffset);
1209 if (NULL == pScanList)
1210 {
1211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1212 "%s: pScanList is %p", __func__, pScanList);
1213 isLastAp = TRUE;
1214 goto done;
1215 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001216 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001218 "Batch scan rsp: numApMetaInfo %d scanId %d",
1219 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301220
1221 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1222 {
1223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1225 isLastAp = TRUE;
1226 goto done;
1227 }
1228
Rajeev Kumarce651e42013-10-21 18:57:15 -07001229 /*Initialize next AP meta info offset for next scan list*/
1230 nextApMetaInfoOffset = 0;
1231
Rajeev79dbe4c2013-10-05 11:03:42 +05301232 while (numApMetaInfo)
1233 {
1234 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1235 nextApMetaInfoOffset);
1236 if (NULL == pApMetaInfo)
1237 {
1238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1240 isLastAp = TRUE;
1241 goto done;
1242 }
1243 /*calculate AP age*/
1244 pApMetaInfo->timestamp =
1245 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1246
1247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001248 "%s: bssId "MAC_ADDRESS_STR
1249 " ch %d rssi %d timestamp %d", __func__,
1250 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1251 pApMetaInfo->ch, pApMetaInfo->rssi,
1252 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301253
1254 /*mark last AP in batch scan response*/
1255 if ((TRUE == pBatchScanRsp->isLastResult) &&
1256 (1 == numberScanList) && (1 == numApMetaInfo))
1257 {
1258 isLastAp = TRUE;
1259 }
1260
1261 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1262 /*store batch scan repsonse in hdd queue*/
1263 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1264 pScanList->scanId, isLastAp);
1265 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1266
1267 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1268 numApMetaInfo--;
1269 }
1270
Rajeev Kumarce651e42013-10-21 18:57:15 -07001271 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1272 + (sizeof(tSirBatchScanNetworkInfo)
1273 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301274 numberScanList--;
1275 }
1276
1277done:
1278
1279 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1280 requested from hdd_ioctl*/
1281 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1282 (TRUE == isLastAp))
1283 {
1284 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1285 complete(&pAdapter->hdd_get_batch_scan_req_var);
1286 }
1287
1288 return;
1289}/*End of hdd_batch_scan_result_ind_callback*/
1290
1291/**---------------------------------------------------------------------------
1292
1293 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1294 response as per batch scan FR request format by putting proper markers
1295
1296 \param - pDest pointer to destination buffer
1297 \param - cur_len current length
1298 \param - tot_len total remaining size which can be written to user space
1299 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1300 \param - pAdapter Pointer to HDD adapter
1301
1302 \return - ret no of characters written
1303
1304 --------------------------------------------------------------------------*/
1305static tANI_U32
1306hdd_format_batch_scan_rsp
1307(
1308 tANI_U8 *pDest,
1309 tANI_U32 cur_len,
1310 tANI_U32 tot_len,
1311 tHddBatchScanRsp *pApMetaInfo,
1312 hdd_adapter_t* pAdapter
1313)
1314{
1315 tANI_U32 ret = 0;
1316 tANI_U32 rem_len = 0;
1317 tANI_U8 temp_len = 0;
1318 tANI_U8 temp_total_len = 0;
1319 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1320 tANI_U8 *pTemp = temp;
1321
1322 /*Batch scan reponse needs to be returned to user space in
1323 following format:
1324 "scancount=X\n" where X is the number of scans in current batch
1325 batch
1326 "trunc\n" optional present if current scan truncated
1327 "bssid=XX:XX:XX:XX:XX:XX\n"
1328 "ssid=XXXX\n"
1329 "freq=X\n" frequency in Mhz
1330 "level=XX\n"
1331 "age=X\n" ms
1332 "dist=X\n" cm (-1 if not available)
1333 "errror=X\n" (-1if not available)
1334 "====\n" (end of ap marker)
1335 "####\n" (end of scan marker)
1336 "----\n" (end of results)*/
1337 /*send scan result in above format to user space based on
1338 available length*/
1339 /*The GET response may have more data than the driver can return in its
1340 buffer. In that case the buffer should be filled to the nearest complete
1341 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1342 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1343 The final buffer should end with "----\n"*/
1344
1345 /*sanity*/
1346 if (cur_len > tot_len)
1347 {
1348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1350 return 0;
1351 }
1352 else
1353 {
1354 rem_len = (tot_len - cur_len);
1355 }
1356
1357 /*end scan marker*/
1358 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1359 {
1360 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1361 pTemp += temp_len;
1362 temp_total_len += temp_len;
1363 }
1364
1365 /*bssid*/
1366 temp_len = snprintf(pTemp, sizeof(temp),
1367 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1368 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1369 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1370 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1371 pTemp += temp_len;
1372 temp_total_len += temp_len;
1373
1374 /*ssid*/
1375 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1376 pApMetaInfo->ApInfo.ssid);
1377 pTemp += temp_len;
1378 temp_total_len += temp_len;
1379
1380 /*freq*/
1381 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001382 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301383 pTemp += temp_len;
1384 temp_total_len += temp_len;
1385
1386 /*level*/
1387 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1388 pApMetaInfo->ApInfo.rssi);
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001393 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301394 pApMetaInfo->ApInfo.age);
1395 pTemp += temp_len;
1396 temp_total_len += temp_len;
1397
1398 /*dist*/
1399 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
1402
1403 /*error*/
1404 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1405 pTemp += temp_len;
1406 temp_total_len += temp_len;
1407
1408 /*end AP marker*/
1409 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1410 pTemp += temp_len;
1411 temp_total_len += temp_len;
1412
1413 /*last AP in batch scan response*/
1414 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1415 {
1416 /*end scan marker*/
1417 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1418 pTemp += temp_len;
1419 temp_total_len += temp_len;
1420
1421 /*end batch scan result marker*/
1422 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1423 pTemp += temp_len;
1424 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001425
Rajeev79dbe4c2013-10-05 11:03:42 +05301426 }
1427
1428 if (temp_total_len < rem_len)
1429 {
1430 ret = temp_total_len + 1;
1431 strlcpy(pDest, temp, ret);
1432 pAdapter->isTruncated = FALSE;
1433 }
1434 else
1435 {
1436 pAdapter->isTruncated = TRUE;
1437 if (rem_len >= strlen("%%%%"))
1438 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001439 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301440 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001441 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301442 {
1443 ret = 0;
1444 }
1445 }
1446
1447 return ret;
1448
1449}/*End of hdd_format_batch_scan_rsp*/
1450
1451/**---------------------------------------------------------------------------
1452
1453 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1454 buffer starting with head of hdd batch scan response queue
1455
1456 \param - pAdapter Pointer to HDD adapter
1457 \param - pDest Pointer to user data buffer
1458 \param - cur_len current offset in user buffer
1459 \param - rem_len remaining no of bytes in user buffer
1460
1461 \return - number of bytes written in user buffer
1462
1463 --------------------------------------------------------------------------*/
1464
1465tANI_U32 hdd_populate_user_batch_scan_rsp
1466(
1467 hdd_adapter_t* pAdapter,
1468 tANI_U8 *pDest,
1469 tANI_U32 cur_len,
1470 tANI_U32 rem_len
1471)
1472{
1473 tHddBatchScanRsp *pHead;
1474 tHddBatchScanRsp *pPrev;
1475 tANI_U32 len;
1476
Rajeev79dbe4c2013-10-05 11:03:42 +05301477 pAdapter->isTruncated = FALSE;
1478
1479 /*head of hdd batch scan response queue*/
1480 pHead = pAdapter->pBatchScanRsp;
1481 while (pHead)
1482 {
1483 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1484 pAdapter);
1485 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001486 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301487 cur_len += len;
1488 if(TRUE == pAdapter->isTruncated)
1489 {
1490 /*result is truncated return rest of scan rsp in next req*/
1491 cur_len = rem_len;
1492 break;
1493 }
1494 pPrev = pHead;
1495 pHead = pHead->pNext;
1496 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001497 if (TRUE == pPrev->ApInfo.isLastAp)
1498 {
1499 pAdapter->prev_batch_id = 0;
1500 }
1501 else
1502 {
1503 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1504 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301505 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001506 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301507 }
1508
1509 return cur_len;
1510}/*End of hdd_populate_user_batch_scan_rsp*/
1511
1512/**---------------------------------------------------------------------------
1513
1514 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1515 scan response data from HDD queue to user space
1516 It does following in detail:
1517 a) if HDD has enough data in its queue then it 1st copies data to user
1518 space and then send get batch scan indication message to FW. In this
1519 case it does not wait on any event and batch scan response data will
1520 be populated in HDD response queue in MC thread context after receiving
1521 indication from FW
1522 b) else send get batch scan indication message to FW and wait on an event
1523 which will be set once HDD receives complete batch scan response from
1524 FW and then this function returns batch scan response to user space
1525
1526 \param - pAdapter Pointer to HDD adapter
1527 \param - pPrivData Pointer to priv_data
1528
1529 \return - 0 for success -EFAULT for failure
1530
1531 --------------------------------------------------------------------------*/
1532
1533int hdd_return_batch_scan_rsp_to_user
1534(
1535 hdd_adapter_t* pAdapter,
1536 hdd_priv_data_t *pPrivData,
1537 tANI_U8 *command
1538)
1539{
1540 tANI_U8 *pDest;
1541 tANI_U32 count = 0;
1542 tANI_U32 len = 0;
1543 tANI_U32 cur_len = 0;
1544 tANI_U32 rem_len = 0;
1545 eHalStatus halStatus;
1546 unsigned long rc;
1547 tSirTriggerBatchScanResultInd *pReq;
1548
1549 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1550 pReq->param = 0;/*batch scan client*/
1551 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1552 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1553
1554 cur_len = pPrivData->used_len;
1555 if (pPrivData->total_len > pPrivData->used_len)
1556 {
1557 rem_len = pPrivData->total_len - pPrivData->used_len;
1558 }
1559 else
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "%s: Invalid user data buffer total_len %d used_len %d",
1563 __func__, pPrivData->total_len, pPrivData->used_len);
1564 return -EFAULT;
1565 }
1566
1567 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1568 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1569 cur_len, rem_len);
1570 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1571
1572 /*enough scan result available in cache to return to user space or
1573 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001574 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301575 {
1576 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1577 halStatus = sme_TriggerBatchScanResultInd(
1578 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1579 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1580 pAdapter);
1581 if ( eHAL_STATUS_SUCCESS == halStatus )
1582 {
1583 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1584 {
1585 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1586 rc = wait_for_completion_timeout(
1587 &pAdapter->hdd_get_batch_scan_req_var,
1588 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1589 if (0 == rc)
1590 {
1591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "%s: Timeout waiting to fetch batch scan rsp from fw",
1593 __func__);
1594 return -EFAULT;
1595 }
1596 }
1597
1598 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001599 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 pDest += len;
1601 cur_len += len;
1602
1603 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1604 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1605 cur_len, rem_len);
1606 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1607
1608 count = 0;
1609 len = (len - pPrivData->used_len);
1610 pDest = (command + pPrivData->used_len);
1611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001612 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301613 while(count < len)
1614 {
1615 printk("%c", *(pDest + count));
1616 count++;
1617 }
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "%s: copy %d data to user buffer", __func__, len);
1620 if (copy_to_user(pPrivData->buf, pDest, len))
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1623 "%s: failed to copy data to user buffer", __func__);
1624 return -EFAULT;
1625 }
1626 }
1627 else
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1630 "sme_GetBatchScanScan returned failure halStatus %d",
1631 halStatus);
1632 return -EINVAL;
1633 }
1634 }
1635 else
1636 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301637 count = 0;
1638 len = (len - pPrivData->used_len);
1639 pDest = (command + pPrivData->used_len);
1640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001641 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301642 while(count < len)
1643 {
1644 printk("%c", *(pDest + count));
1645 count++;
1646 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1648 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301649 if (copy_to_user(pPrivData->buf, pDest, len))
1650 {
1651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1652 "%s: failed to copy data to user buffer", __func__);
1653 return -EFAULT;
1654 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301655 }
1656
1657 return 0;
1658} /*End of hdd_return_batch_scan_rsp_to_user*/
1659
Rajeev Kumar8b373292014-01-08 20:36:55 -08001660
1661/**---------------------------------------------------------------------------
1662
1663 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1664 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1665 WLS_BATCHING VERSION
1666 WLS_BATCHING SET
1667 WLS_BATCHING GET
1668 WLS_BATCHING STOP
1669
1670 \param - pAdapter Pointer to HDD adapter
1671 \param - pPrivdata Pointer to priv_data
1672 \param - command Pointer to command
1673
1674 \return - 0 for success -EFAULT for failure
1675
1676 --------------------------------------------------------------------------*/
1677
1678int hdd_handle_batch_scan_ioctl
1679(
1680 hdd_adapter_t *pAdapter,
1681 hdd_priv_data_t *pPrivdata,
1682 tANI_U8 *command
1683)
1684{
1685 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001686 hdd_context_t *pHddCtx;
1687
1688 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1689 ret = wlan_hdd_validate_context(pHddCtx);
1690 if (ret)
1691 {
1692 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1693 "%s: HDD context is not valid!", __func__);
1694 goto exit;
1695 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001696
1697 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1698 {
1699 char extra[32];
1700 tANI_U8 len = 0;
1701 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1702
1703 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1704 {
1705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1706 "%s: Batch scan feature is not supported by FW", __func__);
1707 ret = -EINVAL;
1708 goto exit;
1709 }
1710
1711 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1712 version);
1713 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1714 {
1715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1716 "%s: failed to copy data to user buffer", __func__);
1717 ret = -EFAULT;
1718 goto exit;
1719 }
1720 ret = HDD_BATCH_SCAN_VERSION;
1721 }
1722 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1723 {
1724 int status;
1725 tANI_U8 *value = (command + 16);
1726 eHalStatus halStatus;
1727 unsigned long rc;
1728 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1729 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1730
1731 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "%s: Batch scan feature is not supported by FW", __func__);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1740 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1742 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1743 {
1744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301745 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001746 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301747 hdd_device_modetoString(pAdapter->device_mode),
1748 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001749 ret = -EINVAL;
1750 goto exit;
1751 }
1752
1753 status = hdd_parse_set_batchscan_command(value, pReq);
1754 if (status)
1755 {
1756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "Invalid WLS_BATCHING SET command");
1758 ret = -EINVAL;
1759 goto exit;
1760 }
1761
1762
1763 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1764 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1765 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1766 pAdapter);
1767
1768 if ( eHAL_STATUS_SUCCESS == halStatus )
1769 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301770 char extra[32];
1771 tANI_U8 len = 0;
1772 tANI_U8 mScan = 0;
1773
Rajeev Kumar8b373292014-01-08 20:36:55 -08001774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1775 "sme_SetBatchScanReq returned success halStatus %d",
1776 halStatus);
1777 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1778 {
1779 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1780 rc = wait_for_completion_timeout(
1781 &pAdapter->hdd_set_batch_scan_req_var,
1782 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1783 if (0 == rc)
1784 {
1785 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1786 "%s: Timeout waiting for set batch scan to complete",
1787 __func__);
1788 ret = -EINVAL;
1789 goto exit;
1790 }
1791 }
1792 if ( !pRsp->nScansToBatch )
1793 {
1794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1795 "%s: Received set batch scan failure response from FW",
1796 __func__);
1797 ret = -EINVAL;
1798 goto exit;
1799 }
1800 /*As per the Batch Scan Framework API we should return the MIN of
1801 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301802 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001803
1804 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1805
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301808 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1809 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1810 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "%s: failed to copy MSCAN value to user buffer", __func__);
1814 ret = -EFAULT;
1815 goto exit;
1816 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001817 }
1818 else
1819 {
1820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "sme_SetBatchScanReq returned failure halStatus %d",
1822 halStatus);
1823 ret = -EINVAL;
1824 goto exit;
1825 }
1826 }
1827 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1828 {
1829 eHalStatus halStatus;
1830 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1831 pInd->param = 0;
1832
1833 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1834 {
1835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1836 "%s: Batch scan feature is not supported by FW", __func__);
1837 ret = -EINVAL;
1838 goto exit;
1839 }
1840
1841 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1842 {
1843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1844 "Batch scan is not yet enabled batch scan state %d",
1845 pAdapter->batchScanState);
1846 ret = -EINVAL;
1847 goto exit;
1848 }
1849
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001850 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1851 hdd_deinit_batch_scan(pAdapter);
1852 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1853
Rajeev Kumar8b373292014-01-08 20:36:55 -08001854 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1855
1856 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1857 pAdapter->sessionId);
1858 if ( eHAL_STATUS_SUCCESS == halStatus )
1859 {
1860 ret = 0;
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1862 "sme_StopBatchScanInd returned success halStatus %d",
1863 halStatus);
1864 }
1865 else
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "sme_StopBatchScanInd returned failure halStatus %d",
1869 halStatus);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
1873 }
1874 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1875 {
1876 tANI_U32 remain_len;
1877
1878 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1881 "%s: Batch scan feature is not supported by FW", __func__);
1882 ret = -EINVAL;
1883 goto exit;
1884 }
1885
1886 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1887 {
1888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1889 "Batch scan is not yet enabled could not return results"
1890 "Batch Scan state %d",
1891 pAdapter->batchScanState);
1892 ret = -EINVAL;
1893 goto exit;
1894 }
1895
1896 pPrivdata->used_len = 16;
1897 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1898 if (remain_len < pPrivdata->total_len)
1899 {
1900 /*Clear previous batch scan response data if any*/
1901 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1902 }
1903 else
1904 {
1905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1906 "Invalid total length from user space can't fetch batch"
1907 " scan response total_len %d used_len %d remain len %d",
1908 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1909 ret = -EINVAL;
1910 goto exit;
1911 }
1912 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1913 }
1914
1915exit:
1916
1917 return ret;
1918}
1919
1920
Rajeev79dbe4c2013-10-05 11:03:42 +05301921#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1922
c_hpothu92367912014-05-01 15:18:17 +05301923static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1924{
c_hpothu39eb1e32014-06-26 16:31:50 +05301925 bcnMissRateContext_t *pCBCtx;
1926
1927 if (NULL == data)
1928 {
1929 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1930 return;
1931 }
c_hpothu92367912014-05-01 15:18:17 +05301932
1933 /* there is a race condition that exists between this callback
1934 function and the caller since the caller could time out either
1935 before or while this code is executing. we use a spinlock to
1936 serialize these actions */
1937 spin_lock(&hdd_context_lock);
1938
c_hpothu39eb1e32014-06-26 16:31:50 +05301939 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301940 gbcnMissRate = -1;
1941
c_hpothu39eb1e32014-06-26 16:31:50 +05301942 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301943 {
1944 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301945 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301946 spin_unlock(&hdd_context_lock);
1947 return ;
1948 }
1949
1950 if (VOS_STATUS_SUCCESS == status)
1951 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301952 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301953 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301954 else
1955 {
1956 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1957 }
1958
c_hpothu92367912014-05-01 15:18:17 +05301959 complete(&(pCBCtx->completion));
1960 spin_unlock(&hdd_context_lock);
1961
1962 return;
1963}
1964
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301965static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1966{
1967 int ret = 0;
1968
1969 if (!pCfg || !command || !extra || !len)
1970 {
1971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1972 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1973 ret = -EINVAL;
1974 return ret;
1975 }
1976
1977 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1978 {
1979 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1980 (int)pCfg->nActiveMaxChnTime);
1981 return ret;
1982 }
1983 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1984 {
1985 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1986 (int)pCfg->nActiveMinChnTime);
1987 return ret;
1988 }
1989 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1990 {
1991 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1992 (int)pCfg->nPassiveMaxChnTime);
1993 return ret;
1994 }
1995 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1996 {
1997 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1998 (int)pCfg->nPassiveMinChnTime);
1999 return ret;
2000 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302001 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2002 {
2003 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2004 (int)pCfg->nActiveMaxChnTime);
2005 return ret;
2006 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302007 else
2008 {
2009 ret = -EINVAL;
2010 }
2011
2012 return ret;
2013}
2014
2015static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2016{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302017 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302018 hdd_config_t *pCfg;
2019 tANI_U8 *value = command;
2020 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302021 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302022
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302023 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2024 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302025 {
2026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2027 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2028 ret = -EINVAL;
2029 return ret;
2030 }
2031
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302032 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2033 sme_GetConfigParam(hHal, &smeConfig);
2034
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302035 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2036 {
2037 value = value + 24;
2038 temp = kstrtou32(value, 10, &val);
2039 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2040 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2041 {
2042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2043 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2044 ret = -EFAULT;
2045 return ret;
2046 }
2047 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302048 smeConfig.csrConfig.nActiveMaxChnTime = val;
2049 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302050 }
2051 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2052 {
2053 value = value + 24;
2054 temp = kstrtou32(value, 10, &val);
2055 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2056 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2057 {
2058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2060 ret = -EFAULT;
2061 return ret;
2062 }
2063 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302064 smeConfig.csrConfig.nActiveMinChnTime = val;
2065 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302066 }
2067 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2068 {
2069 value = value + 25;
2070 temp = kstrtou32(value, 10, &val);
2071 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2072 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2075 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2076 ret = -EFAULT;
2077 return ret;
2078 }
2079 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302080 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2081 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302082 }
2083 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2084 {
2085 value = value + 25;
2086 temp = kstrtou32(value, 10, &val);
2087 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2088 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2089 {
2090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2091 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2092 ret = -EFAULT;
2093 return ret;
2094 }
2095 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302096 smeConfig.csrConfig.nPassiveMinChnTime = val;
2097 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302098 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302099 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2100 {
2101 value = value + 13;
2102 temp = kstrtou32(value, 10, &val);
2103 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2104 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2107 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2108 ret = -EFAULT;
2109 return ret;
2110 }
2111 pCfg->nActiveMaxChnTime = val;
2112 smeConfig.csrConfig.nActiveMaxChnTime = val;
2113 sme_UpdateConfig(hHal, &smeConfig);
2114 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302115 else
2116 {
2117 ret = -EINVAL;
2118 }
2119
2120 return ret;
2121}
2122
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002123static int hdd_driver_command(hdd_adapter_t *pAdapter,
2124 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002125{
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 hdd_priv_data_t priv_data;
2127 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002128 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002129
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002130 /*
2131 * Note that valid pointers are provided by caller
2132 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002133
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002134 /* copy to local struct to avoid numerous changes to legacy code */
2135 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002136
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002137 if (priv_data.total_len <= 0 ||
2138 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002139 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002140 hddLog(VOS_TRACE_LEVEL_WARN,
2141 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2142 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002143 ret = -EINVAL;
2144 goto exit;
2145 }
2146
2147 /* Allocate +1 for '\0' */
2148 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002149 if (!command)
2150 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002151 hddLog(VOS_TRACE_LEVEL_ERROR,
2152 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 ret = -ENOMEM;
2154 goto exit;
2155 }
2156
2157 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2158 {
2159 ret = -EFAULT;
2160 goto exit;
2161 }
2162
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002163 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002164 command[priv_data.total_len] = '\0';
2165
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002166 /* at one time the following block of code was conditional. braces
2167 * have been retained to avoid re-indenting the legacy code
2168 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002169 {
2170 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2171
2172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002173 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002174
2175 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2176 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302177 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2178 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2179 pAdapter->sessionId, (unsigned)
2180 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2181 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2182 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2183 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002184 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2185 sizeof(tSirMacAddr)))
2186 {
2187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002188 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 ret = -EFAULT;
2190 }
2191 }
Amar Singhal0974e402013-02-12 14:27:46 -08002192 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 {
Amar Singhal0974e402013-02-12 14:27:46 -08002194 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002195
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002197
2198 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002201 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002202 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002203 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302204 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302205 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002206 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002207 }
Kiet Lamf040f472013-11-20 21:15:23 +05302208 else if(strncmp(command, "SETWMMPS", 8) == 0)
2209 {
2210 tANI_U8 *ptr = command;
2211 ret = hdd_wmmps_helper(pAdapter, ptr);
2212 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002213 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2214 {
2215 char *country_code;
2216
2217 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002218
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002219 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002220 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002221#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302222 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002223#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002224 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2225 (void *)(tSmeChangeCountryCallback)
2226 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302227 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002228 if (eHAL_STATUS_SUCCESS == ret)
2229 {
2230 ret = wait_for_completion_interruptible_timeout(
2231 &pAdapter->change_country_code,
2232 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2233 if (0 >= ret)
2234 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002235 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302236 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002237 }
2238 }
2239 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002240 {
2241 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002242 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002243 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002244 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002245
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002246 }
2247 /*
2248 command should be a string having format
2249 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2250 */
Amar Singhal0974e402013-02-12 14:27:46 -08002251 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002252 {
Amar Singhal0974e402013-02-12 14:27:46 -08002253 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002254
2255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002256 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002257
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002258 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002259 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002260 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2261 {
2262 int suspend = 0;
2263 tANI_U8 *ptr = (tANI_U8*)command + 15;
2264
2265 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302266 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2267 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2268 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002269 hdd_set_wlan_suspend_mode(suspend);
2270 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002271#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2272 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2273 {
2274 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002275 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002276 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2277 eHalStatus status = eHAL_STATUS_SUCCESS;
2278
2279 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2280 value = value + 15;
2281
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002282 /* Convert the value from ascii to integer */
2283 ret = kstrtos8(value, 10, &rssi);
2284 if (ret < 0)
2285 {
2286 /* If the input value is greater than max value of datatype, then also
2287 kstrtou8 fails */
2288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2289 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002290 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002291 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2292 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2293 ret = -EINVAL;
2294 goto exit;
2295 }
2296
Srinivas Girigowdade697412013-02-14 16:31:48 -08002297 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002298
Srinivas Girigowdade697412013-02-14 16:31:48 -08002299 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2300 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2301 {
2302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2303 "Neighbor lookup threshold value %d is out of range"
2304 " (Min: %d Max: %d)", lookUpThreshold,
2305 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2306 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2307 ret = -EINVAL;
2308 goto exit;
2309 }
2310
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302311 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2312 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2313 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2315 "%s: Received Command to Set Roam trigger"
2316 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2317
2318 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2319 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2320 if (eHAL_STATUS_SUCCESS != status)
2321 {
2322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2323 "%s: Failed to set roam trigger, try again", __func__);
2324 ret = -EPERM;
2325 goto exit;
2326 }
2327
2328 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302329 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002330 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2331 }
2332 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2333 {
2334 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2335 int rssi = (-1) * lookUpThreshold;
2336 char extra[32];
2337 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302338 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2339 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2340 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002341 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002342 if (copy_to_user(priv_data.buf, &extra, len + 1))
2343 {
2344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2345 "%s: failed to copy data to user buffer", __func__);
2346 ret = -EFAULT;
2347 goto exit;
2348 }
2349 }
2350 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2351 {
2352 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002353 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002354 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002355
Srinivas Girigowdade697412013-02-14 16:31:48 -08002356 /* input refresh period is in terms of seconds */
2357 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2358 value = value + 18;
2359 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002360 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002361 if (ret < 0)
2362 {
2363 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002364 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002366 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002367 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002368 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2369 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 ret = -EINVAL;
2371 goto exit;
2372 }
2373
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002374 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2375 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376 {
2377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002378 "Roam scan period value %d is out of range"
2379 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002380 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2381 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002382 ret = -EINVAL;
2383 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302384 }
2385 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2386 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2387 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002388 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002389
2390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2391 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002392 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002393
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002394 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2395 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002396 }
2397 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2398 {
2399 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2400 char extra[32];
2401 tANI_U8 len = 0;
2402
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302403 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2404 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2405 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002406 len = scnprintf(extra, sizeof(extra), "%s %d",
2407 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002408 /* Returned value is in units of seconds */
2409 if (copy_to_user(priv_data.buf, &extra, len + 1))
2410 {
2411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2412 "%s: failed to copy data to user buffer", __func__);
2413 ret = -EFAULT;
2414 goto exit;
2415 }
2416 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002417 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2418 {
2419 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002420 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002421 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002422
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002423 /* input refresh period is in terms of seconds */
2424 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2425 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002426
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002427 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002428 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002429 if (ret < 0)
2430 {
2431 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002432 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002434 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002435 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2437 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2438 ret = -EINVAL;
2439 goto exit;
2440 }
2441
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002442 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2443 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2444 {
2445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2446 "Neighbor scan results refresh period value %d is out of range"
2447 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2448 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2449 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2450 ret = -EINVAL;
2451 goto exit;
2452 }
2453 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2454
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2456 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002457 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002458
2459 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2460 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2461 }
2462 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2463 {
2464 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2465 char extra[32];
2466 tANI_U8 len = 0;
2467
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002468 len = scnprintf(extra, sizeof(extra), "%s %d",
2469 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002470 /* Returned value is in units of seconds */
2471 if (copy_to_user(priv_data.buf, &extra, len + 1))
2472 {
2473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2474 "%s: failed to copy data to user buffer", __func__);
2475 ret = -EFAULT;
2476 goto exit;
2477 }
2478 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002479#ifdef FEATURE_WLAN_LFR
2480 /* SETROAMMODE */
2481 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2482 {
2483 tANI_U8 *value = command;
2484 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2485
2486 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2487 value = value + SIZE_OF_SETROAMMODE + 1;
2488
2489 /* Convert the value from ascii to integer */
2490 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2491 if (ret < 0)
2492 {
2493 /* If the input value is greater than max value of datatype, then also
2494 kstrtou8 fails */
2495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2496 "%s: kstrtou8 failed range [%d - %d]", __func__,
2497 CFG_LFR_FEATURE_ENABLED_MIN,
2498 CFG_LFR_FEATURE_ENABLED_MAX);
2499 ret = -EINVAL;
2500 goto exit;
2501 }
2502 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2503 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2504 {
2505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2506 "Roam Mode value %d is out of range"
2507 " (Min: %d Max: %d)", roamMode,
2508 CFG_LFR_FEATURE_ENABLED_MIN,
2509 CFG_LFR_FEATURE_ENABLED_MAX);
2510 ret = -EINVAL;
2511 goto exit;
2512 }
2513
2514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2515 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2516 /*
2517 * Note that
2518 * SETROAMMODE 0 is to enable LFR while
2519 * SETROAMMODE 1 is to disable LFR, but
2520 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2521 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2522 */
2523 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2524 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2525 else
2526 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2527
2528 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2529 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2530 }
2531 /* GETROAMMODE */
2532 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2533 {
2534 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2535 char extra[32];
2536 tANI_U8 len = 0;
2537
2538 /*
2539 * roamMode value shall be inverted because the sementics is different.
2540 */
2541 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2542 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2543 else
2544 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2545
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002546 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002547 if (copy_to_user(priv_data.buf, &extra, len + 1))
2548 {
2549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2550 "%s: failed to copy data to user buffer", __func__);
2551 ret = -EFAULT;
2552 goto exit;
2553 }
2554 }
2555#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002556#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002557#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002558 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2559 {
2560 tANI_U8 *value = command;
2561 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2562
2563 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2564 value = value + 13;
2565 /* Convert the value from ascii to integer */
2566 ret = kstrtou8(value, 10, &roamRssiDiff);
2567 if (ret < 0)
2568 {
2569 /* If the input value is greater than max value of datatype, then also
2570 kstrtou8 fails */
2571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2572 "%s: kstrtou8 failed range [%d - %d]", __func__,
2573 CFG_ROAM_RSSI_DIFF_MIN,
2574 CFG_ROAM_RSSI_DIFF_MAX);
2575 ret = -EINVAL;
2576 goto exit;
2577 }
2578
2579 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2580 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2581 {
2582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2583 "Roam rssi diff value %d is out of range"
2584 " (Min: %d Max: %d)", roamRssiDiff,
2585 CFG_ROAM_RSSI_DIFF_MIN,
2586 CFG_ROAM_RSSI_DIFF_MAX);
2587 ret = -EINVAL;
2588 goto exit;
2589 }
2590
2591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2592 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2593
2594 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2595 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2596 }
2597 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2598 {
2599 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2600 char extra[32];
2601 tANI_U8 len = 0;
2602
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302603 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2604 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2605 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002606 len = scnprintf(extra, sizeof(extra), "%s %d",
2607 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002608 if (copy_to_user(priv_data.buf, &extra, len + 1))
2609 {
2610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2611 "%s: failed to copy data to user buffer", __func__);
2612 ret = -EFAULT;
2613 goto exit;
2614 }
2615 }
2616#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002617#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002618 else if (strncmp(command, "GETBAND", 7) == 0)
2619 {
2620 int band = -1;
2621 char extra[32];
2622 tANI_U8 len = 0;
2623 hdd_getBand_helper(pHddCtx, &band);
2624
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302625 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2626 TRACE_CODE_HDD_GETBAND_IOCTL,
2627 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002628 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002629 if (copy_to_user(priv_data.buf, &extra, len + 1))
2630 {
2631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2632 "%s: failed to copy data to user buffer", __func__);
2633 ret = -EFAULT;
2634 goto exit;
2635 }
2636 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002637 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2638 {
2639 tANI_U8 *value = command;
2640 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2641 tANI_U8 numChannels = 0;
2642 eHalStatus status = eHAL_STATUS_SUCCESS;
2643
2644 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2645 if (eHAL_STATUS_SUCCESS != status)
2646 {
2647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2648 "%s: Failed to parse channel list information", __func__);
2649 ret = -EINVAL;
2650 goto exit;
2651 }
2652
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302653 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2654 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2655 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002656 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2657 {
2658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2659 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2660 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2661 ret = -EINVAL;
2662 goto exit;
2663 }
2664 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2665 numChannels);
2666 if (eHAL_STATUS_SUCCESS != status)
2667 {
2668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2669 "%s: Failed to update channel list information", __func__);
2670 ret = -EINVAL;
2671 goto exit;
2672 }
2673 }
2674 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2675 {
2676 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2677 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002678 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002679 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002680 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002681
2682 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2683 ChannelList, &numChannels ))
2684 {
2685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2686 "%s: failed to get roam scan channel list", __func__);
2687 ret = -EFAULT;
2688 goto exit;
2689 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302690 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2691 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2692 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002693 /* output channel list is of the format
2694 [Number of roam scan channels][Channel1][Channel2]... */
2695 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002696 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002697 for (j = 0; (j < numChannels); j++)
2698 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002699 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2700 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002701 }
2702
2703 if (copy_to_user(priv_data.buf, &extra, len + 1))
2704 {
2705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2706 "%s: failed to copy data to user buffer", __func__);
2707 ret = -EFAULT;
2708 goto exit;
2709 }
2710 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002711 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2712 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002713 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002714 char extra[32];
2715 tANI_U8 len = 0;
2716
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002717 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002718 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002719 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002720 hdd_is_okc_mode_enabled(pHddCtx) &&
2721 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2722 {
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002724 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002725 " hence this operation is not permitted!", __func__);
2726 ret = -EPERM;
2727 goto exit;
2728 }
2729
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002730 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002731 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002732 if (copy_to_user(priv_data.buf, &extra, len + 1))
2733 {
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "%s: failed to copy data to user buffer", __func__);
2736 ret = -EFAULT;
2737 goto exit;
2738 }
2739 }
2740 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2741 {
2742 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2743 char extra[32];
2744 tANI_U8 len = 0;
2745
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002746 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002747 then this operation is not permitted (return FAILURE) */
2748 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002749 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002750 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2751 {
2752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002753 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002754 " hence this operation is not permitted!", __func__);
2755 ret = -EPERM;
2756 goto exit;
2757 }
2758
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002759 len = scnprintf(extra, sizeof(extra), "%s %d",
2760 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002761 if (copy_to_user(priv_data.buf, &extra, len + 1))
2762 {
2763 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2764 "%s: failed to copy data to user buffer", __func__);
2765 ret = -EFAULT;
2766 goto exit;
2767 }
2768 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002769 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002770 {
2771 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2772 char extra[32];
2773 tANI_U8 len = 0;
2774
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002775 len = scnprintf(extra, sizeof(extra), "%s %d",
2776 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002777 if (copy_to_user(priv_data.buf, &extra, len + 1))
2778 {
2779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2780 "%s: failed to copy data to user buffer", __func__);
2781 ret = -EFAULT;
2782 goto exit;
2783 }
2784 }
2785 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2786 {
2787 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2788 char extra[32];
2789 tANI_U8 len = 0;
2790
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002791 len = scnprintf(extra, sizeof(extra), "%s %d",
2792 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002793 if (copy_to_user(priv_data.buf, &extra, len + 1))
2794 {
2795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2796 "%s: failed to copy data to user buffer", __func__);
2797 ret = -EFAULT;
2798 goto exit;
2799 }
2800 }
2801 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2802 {
2803 tANI_U8 *value = command;
2804 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2805
2806 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2807 value = value + 26;
2808 /* Convert the value from ascii to integer */
2809 ret = kstrtou8(value, 10, &minTime);
2810 if (ret < 0)
2811 {
2812 /* If the input value is greater than max value of datatype, then also
2813 kstrtou8 fails */
2814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2815 "%s: kstrtou8 failed range [%d - %d]", __func__,
2816 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2817 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2818 ret = -EINVAL;
2819 goto exit;
2820 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002821 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2822 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2823 {
2824 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2825 "scan min channel time value %d is out of range"
2826 " (Min: %d Max: %d)", minTime,
2827 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2828 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2829 ret = -EINVAL;
2830 goto exit;
2831 }
2832
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302833 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2834 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2835 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2837 "%s: Received Command to change channel min time = %d", __func__, minTime);
2838
2839 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2840 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2841 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002842 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2843 {
2844 tANI_U8 *value = command;
2845 tANI_U8 channel = 0;
2846 tANI_U8 dwellTime = 0;
2847 tANI_U8 bufLen = 0;
2848 tANI_U8 *buf = NULL;
2849 tSirMacAddr targetApBssid;
2850 eHalStatus status = eHAL_STATUS_SUCCESS;
2851 struct ieee80211_channel chan;
2852 tANI_U8 finalLen = 0;
2853 tANI_U8 *finalBuf = NULL;
2854 tANI_U8 temp = 0;
2855 u64 cookie;
2856 hdd_station_ctx_t *pHddStaCtx = NULL;
2857 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2858
2859 /* if not associated, no need to send action frame */
2860 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2861 {
2862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2863 ret = -EINVAL;
2864 goto exit;
2865 }
2866
2867 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2868 &dwellTime, &buf, &bufLen);
2869 if (eHAL_STATUS_SUCCESS != status)
2870 {
2871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2872 "%s: Failed to parse send action frame data", __func__);
2873 ret = -EINVAL;
2874 goto exit;
2875 }
2876
2877 /* if the target bssid is different from currently associated AP,
2878 then no need to send action frame */
2879 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2880 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2881 {
2882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2883 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002884 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002885 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002886 goto exit;
2887 }
2888
2889 /* if the channel number is different from operating channel then
2890 no need to send action frame */
2891 if (channel != pHddStaCtx->conn_info.operationChannel)
2892 {
2893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2894 "%s: channel(%d) is different from operating channel(%d)",
2895 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2896 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002897 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002898 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002899 goto exit;
2900 }
2901 chan.center_freq = sme_ChnToFreq(channel);
2902
2903 finalLen = bufLen + 24;
2904 finalBuf = vos_mem_malloc(finalLen);
2905 if (NULL == finalBuf)
2906 {
2907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2908 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002909 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002910 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002911 goto exit;
2912 }
2913 vos_mem_zero(finalBuf, finalLen);
2914
2915 /* Fill subtype */
2916 temp = SIR_MAC_MGMT_ACTION << 4;
2917 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2918
2919 /* Fill type */
2920 temp = SIR_MAC_MGMT_FRAME;
2921 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2922
2923 /* Fill destination address (bssid of the AP) */
2924 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2925
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002926 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002927 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2928
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002929 /* Fill BSSID (AP mac address) */
2930 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002931
2932 /* Fill received buffer from 24th address */
2933 vos_mem_copy(finalBuf + 24, buf, bufLen);
2934
Jeff Johnson11c33152013-04-16 17:52:40 -07002935 /* done with the parsed buffer */
2936 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002937 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002938
DARAM SUDHA39eede62014-02-12 11:16:40 +05302939 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002940#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2941 &(pAdapter->wdev),
2942#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002943 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002944#endif
2945 &chan, 0,
2946#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2947 NL80211_CHAN_HT20, 1,
2948#endif
2949 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002950 1, &cookie );
2951 vos_mem_free(finalBuf);
2952 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002953 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2954 {
2955 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2956 char extra[32];
2957 tANI_U8 len = 0;
2958
2959 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002960 len = scnprintf(extra, sizeof(extra), "%s %d",
2961 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302962 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2963 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2964 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002965 if (copy_to_user(priv_data.buf, &extra, len + 1))
2966 {
2967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2968 "%s: failed to copy data to user buffer", __func__);
2969 ret = -EFAULT;
2970 goto exit;
2971 }
2972 }
2973 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2974 {
2975 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002976 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002977
2978 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2979 value = value + 19;
2980 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002981 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002982 if (ret < 0)
2983 {
2984 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002985 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002987 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002988 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2989 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2990 ret = -EINVAL;
2991 goto exit;
2992 }
2993
2994 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2995 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2996 {
2997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2998 "lfr mode value %d is out of range"
2999 " (Min: %d Max: %d)", maxTime,
3000 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3001 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3002 ret = -EINVAL;
3003 goto exit;
3004 }
3005
3006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3007 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3008
3009 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3010 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3011 }
3012 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3013 {
3014 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3015 char extra[32];
3016 tANI_U8 len = 0;
3017
3018 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003019 len = scnprintf(extra, sizeof(extra), "%s %d",
3020 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003021 if (copy_to_user(priv_data.buf, &extra, len + 1))
3022 {
3023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3024 "%s: failed to copy data to user buffer", __func__);
3025 ret = -EFAULT;
3026 goto exit;
3027 }
3028 }
3029 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3030 {
3031 tANI_U8 *value = command;
3032 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3033
3034 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3035 value = value + 16;
3036 /* Convert the value from ascii to integer */
3037 ret = kstrtou16(value, 10, &val);
3038 if (ret < 0)
3039 {
3040 /* If the input value is greater than max value of datatype, then also
3041 kstrtou16 fails */
3042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3043 "%s: kstrtou16 failed range [%d - %d]", __func__,
3044 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3045 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3046 ret = -EINVAL;
3047 goto exit;
3048 }
3049
3050 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3051 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3052 {
3053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3054 "scan home time value %d is out of range"
3055 " (Min: %d Max: %d)", val,
3056 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3057 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3058 ret = -EINVAL;
3059 goto exit;
3060 }
3061
3062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3063 "%s: Received Command to change scan home time = %d", __func__, val);
3064
3065 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3066 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3067 }
3068 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3069 {
3070 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3071 char extra[32];
3072 tANI_U8 len = 0;
3073
3074 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003075 len = scnprintf(extra, sizeof(extra), "%s %d",
3076 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003077 if (copy_to_user(priv_data.buf, &extra, len + 1))
3078 {
3079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3080 "%s: failed to copy data to user buffer", __func__);
3081 ret = -EFAULT;
3082 goto exit;
3083 }
3084 }
3085 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3086 {
3087 tANI_U8 *value = command;
3088 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3089
3090 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3091 value = value + 17;
3092 /* Convert the value from ascii to integer */
3093 ret = kstrtou8(value, 10, &val);
3094 if (ret < 0)
3095 {
3096 /* If the input value is greater than max value of datatype, then also
3097 kstrtou8 fails */
3098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3099 "%s: kstrtou8 failed range [%d - %d]", __func__,
3100 CFG_ROAM_INTRA_BAND_MIN,
3101 CFG_ROAM_INTRA_BAND_MAX);
3102 ret = -EINVAL;
3103 goto exit;
3104 }
3105
3106 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3107 (val > CFG_ROAM_INTRA_BAND_MAX))
3108 {
3109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3110 "intra band mode value %d is out of range"
3111 " (Min: %d Max: %d)", val,
3112 CFG_ROAM_INTRA_BAND_MIN,
3113 CFG_ROAM_INTRA_BAND_MAX);
3114 ret = -EINVAL;
3115 goto exit;
3116 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3118 "%s: Received Command to change intra band = %d", __func__, val);
3119
3120 pHddCtx->cfg_ini->nRoamIntraBand = val;
3121 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3122 }
3123 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3124 {
3125 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3126 char extra[32];
3127 tANI_U8 len = 0;
3128
3129 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003130 len = scnprintf(extra, sizeof(extra), "%s %d",
3131 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003132 if (copy_to_user(priv_data.buf, &extra, len + 1))
3133 {
3134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3135 "%s: failed to copy data to user buffer", __func__);
3136 ret = -EFAULT;
3137 goto exit;
3138 }
3139 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003140 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3141 {
3142 tANI_U8 *value = command;
3143 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3144
3145 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3146 value = value + 15;
3147 /* Convert the value from ascii to integer */
3148 ret = kstrtou8(value, 10, &nProbes);
3149 if (ret < 0)
3150 {
3151 /* If the input value is greater than max value of datatype, then also
3152 kstrtou8 fails */
3153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3154 "%s: kstrtou8 failed range [%d - %d]", __func__,
3155 CFG_ROAM_SCAN_N_PROBES_MIN,
3156 CFG_ROAM_SCAN_N_PROBES_MAX);
3157 ret = -EINVAL;
3158 goto exit;
3159 }
3160
3161 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3162 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3163 {
3164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3165 "NProbes value %d is out of range"
3166 " (Min: %d Max: %d)", nProbes,
3167 CFG_ROAM_SCAN_N_PROBES_MIN,
3168 CFG_ROAM_SCAN_N_PROBES_MAX);
3169 ret = -EINVAL;
3170 goto exit;
3171 }
3172
3173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3174 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3175
3176 pHddCtx->cfg_ini->nProbes = nProbes;
3177 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3178 }
3179 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3180 {
3181 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3182 char extra[32];
3183 tANI_U8 len = 0;
3184
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003185 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003186 if (copy_to_user(priv_data.buf, &extra, len + 1))
3187 {
3188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3189 "%s: failed to copy data to user buffer", __func__);
3190 ret = -EFAULT;
3191 goto exit;
3192 }
3193 }
3194 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3195 {
3196 tANI_U8 *value = command;
3197 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3198
3199 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3200 /* input value is in units of msec */
3201 value = value + 20;
3202 /* Convert the value from ascii to integer */
3203 ret = kstrtou16(value, 10, &homeAwayTime);
3204 if (ret < 0)
3205 {
3206 /* If the input value is greater than max value of datatype, then also
3207 kstrtou8 fails */
3208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3209 "%s: kstrtou8 failed range [%d - %d]", __func__,
3210 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3211 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3212 ret = -EINVAL;
3213 goto exit;
3214 }
3215
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003216 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3217 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3218 {
3219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3220 "homeAwayTime value %d is out of range"
3221 " (Min: %d Max: %d)", homeAwayTime,
3222 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3223 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3224 ret = -EINVAL;
3225 goto exit;
3226 }
3227
3228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3229 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003230 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3231 {
3232 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3233 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3234 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003235 }
3236 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3237 {
3238 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3239 char extra[32];
3240 tANI_U8 len = 0;
3241
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003242 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003243 if (copy_to_user(priv_data.buf, &extra, len + 1))
3244 {
3245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3246 "%s: failed to copy data to user buffer", __func__);
3247 ret = -EFAULT;
3248 goto exit;
3249 }
3250 }
3251 else if (strncmp(command, "REASSOC", 7) == 0)
3252 {
3253 tANI_U8 *value = command;
3254 tANI_U8 channel = 0;
3255 tSirMacAddr targetApBssid;
3256 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003257#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3258 tCsrHandoffRequest handoffInfo;
3259#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003260 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003261 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3262
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003263 /* if not associated, no need to proceed with reassoc */
3264 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3265 {
3266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3267 ret = -EINVAL;
3268 goto exit;
3269 }
3270
3271 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3272 if (eHAL_STATUS_SUCCESS != status)
3273 {
3274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3275 "%s: Failed to parse reassoc command data", __func__);
3276 ret = -EINVAL;
3277 goto exit;
3278 }
3279
3280 /* if the target bssid is same as currently associated AP,
3281 then no need to proceed with reassoc */
3282 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3283 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3284 {
3285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3286 ret = -EINVAL;
3287 goto exit;
3288 }
3289
3290 /* Check channel number is a valid channel number */
3291 if(VOS_STATUS_SUCCESS !=
3292 wlan_hdd_validate_operation_channel(pAdapter, channel))
3293 {
3294 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003295 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003296 return -EINVAL;
3297 }
3298
3299 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003300#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3301 handoffInfo.channel = channel;
3302 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3303 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3304#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003305 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003306 else if (strncmp(command, "SETWESMODE", 10) == 0)
3307 {
3308 tANI_U8 *value = command;
3309 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3310
3311 /* Move pointer to ahead of SETWESMODE<delimiter> */
3312 value = value + 11;
3313 /* Convert the value from ascii to integer */
3314 ret = kstrtou8(value, 10, &wesMode);
3315 if (ret < 0)
3316 {
3317 /* If the input value is greater than max value of datatype, then also
3318 kstrtou8 fails */
3319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3320 "%s: kstrtou8 failed range [%d - %d]", __func__,
3321 CFG_ENABLE_WES_MODE_NAME_MIN,
3322 CFG_ENABLE_WES_MODE_NAME_MAX);
3323 ret = -EINVAL;
3324 goto exit;
3325 }
3326
3327 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3328 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3329 {
3330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3331 "WES Mode value %d is out of range"
3332 " (Min: %d Max: %d)", wesMode,
3333 CFG_ENABLE_WES_MODE_NAME_MIN,
3334 CFG_ENABLE_WES_MODE_NAME_MAX);
3335 ret = -EINVAL;
3336 goto exit;
3337 }
3338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3339 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3340
3341 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3342 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3343 }
3344 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3345 {
3346 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3347 char extra[32];
3348 tANI_U8 len = 0;
3349
Arif Hussain826d9412013-11-12 16:44:54 -08003350 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003351 if (copy_to_user(priv_data.buf, &extra, len + 1))
3352 {
3353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3354 "%s: failed to copy data to user buffer", __func__);
3355 ret = -EFAULT;
3356 goto exit;
3357 }
3358 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003359#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003360#ifdef FEATURE_WLAN_LFR
3361 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3362 {
3363 tANI_U8 *value = command;
3364 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3365
3366 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3367 value = value + 12;
3368 /* Convert the value from ascii to integer */
3369 ret = kstrtou8(value, 10, &lfrMode);
3370 if (ret < 0)
3371 {
3372 /* If the input value is greater than max value of datatype, then also
3373 kstrtou8 fails */
3374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3375 "%s: kstrtou8 failed range [%d - %d]", __func__,
3376 CFG_LFR_FEATURE_ENABLED_MIN,
3377 CFG_LFR_FEATURE_ENABLED_MAX);
3378 ret = -EINVAL;
3379 goto exit;
3380 }
3381
3382 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3383 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3384 {
3385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3386 "lfr mode value %d is out of range"
3387 " (Min: %d Max: %d)", lfrMode,
3388 CFG_LFR_FEATURE_ENABLED_MIN,
3389 CFG_LFR_FEATURE_ENABLED_MAX);
3390 ret = -EINVAL;
3391 goto exit;
3392 }
3393
3394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3395 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3396
3397 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3398 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3399 }
3400#endif
3401#ifdef WLAN_FEATURE_VOWIFI_11R
3402 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3403 {
3404 tANI_U8 *value = command;
3405 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3406
3407 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3408 value = value + 18;
3409 /* Convert the value from ascii to integer */
3410 ret = kstrtou8(value, 10, &ft);
3411 if (ret < 0)
3412 {
3413 /* If the input value is greater than max value of datatype, then also
3414 kstrtou8 fails */
3415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3416 "%s: kstrtou8 failed range [%d - %d]", __func__,
3417 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3418 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3419 ret = -EINVAL;
3420 goto exit;
3421 }
3422
3423 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3424 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3425 {
3426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3427 "ft mode value %d is out of range"
3428 " (Min: %d Max: %d)", ft,
3429 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3430 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3431 ret = -EINVAL;
3432 goto exit;
3433 }
3434
3435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3436 "%s: Received Command to change ft mode = %d", __func__, ft);
3437
3438 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3439 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3440 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303441
3442 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3443 {
3444 tANI_U8 *value = command;
3445 tSirMacAddr targetApBssid;
3446 tANI_U8 trigger = 0;
3447 eHalStatus status = eHAL_STATUS_SUCCESS;
3448 hdd_station_ctx_t *pHddStaCtx = NULL;
3449 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3450
3451 /* if not associated, no need to proceed with reassoc */
3452 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3453 {
3454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3455 ret = -EINVAL;
3456 goto exit;
3457 }
3458
3459 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3460 if (eHAL_STATUS_SUCCESS != status)
3461 {
3462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3463 "%s: Failed to parse reassoc command data", __func__);
3464 ret = -EINVAL;
3465 goto exit;
3466 }
3467
3468 /* if the target bssid is same as currently associated AP,
3469 then no need to proceed with reassoc */
3470 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3471 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3472 {
3473 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3474 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3475 __func__);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 /* Proceed with scan/roam */
3481 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3482 &targetApBssid[0],
3483 (tSmeFastRoamTrigger)(trigger));
3484 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003485#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003486#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003487 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3488 {
3489 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003490 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003491
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003492 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003493 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003494 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003495 hdd_is_okc_mode_enabled(pHddCtx) &&
3496 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3497 {
3498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003499 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003500 " hence this operation is not permitted!", __func__);
3501 ret = -EPERM;
3502 goto exit;
3503 }
3504
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003505 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3506 value = value + 11;
3507 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003508 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003509 if (ret < 0)
3510 {
3511 /* If the input value is greater than max value of datatype, then also
3512 kstrtou8 fails */
3513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3514 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003515 CFG_ESE_FEATURE_ENABLED_MIN,
3516 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003517 ret = -EINVAL;
3518 goto exit;
3519 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003520 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3521 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003522 {
3523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003524 "Ese mode value %d is out of range"
3525 " (Min: %d Max: %d)", eseMode,
3526 CFG_ESE_FEATURE_ENABLED_MIN,
3527 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003528 ret = -EINVAL;
3529 goto exit;
3530 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003532 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003533
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003534 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3535 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003536 }
3537#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003538 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3539 {
3540 tANI_U8 *value = command;
3541 tANI_BOOLEAN roamScanControl = 0;
3542
3543 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3544 value = value + 19;
3545 /* Convert the value from ascii to integer */
3546 ret = kstrtou8(value, 10, &roamScanControl);
3547 if (ret < 0)
3548 {
3549 /* If the input value is greater than max value of datatype, then also
3550 kstrtou8 fails */
3551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3552 "%s: kstrtou8 failed ", __func__);
3553 ret = -EINVAL;
3554 goto exit;
3555 }
3556
3557 if (0 != roamScanControl)
3558 {
3559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3560 "roam scan control invalid value = %d",
3561 roamScanControl);
3562 ret = -EINVAL;
3563 goto exit;
3564 }
3565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3566 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3567
3568 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3569 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003570#ifdef FEATURE_WLAN_OKC
3571 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3572 {
3573 tANI_U8 *value = command;
3574 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3575
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003576 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003577 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003578 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003579 hdd_is_okc_mode_enabled(pHddCtx) &&
3580 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3581 {
3582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003583 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003584 " hence this operation is not permitted!", __func__);
3585 ret = -EPERM;
3586 goto exit;
3587 }
3588
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003589 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3590 value = value + 11;
3591 /* Convert the value from ascii to integer */
3592 ret = kstrtou8(value, 10, &okcMode);
3593 if (ret < 0)
3594 {
3595 /* If the input value is greater than max value of datatype, then also
3596 kstrtou8 fails */
3597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3598 "%s: kstrtou8 failed range [%d - %d]", __func__,
3599 CFG_OKC_FEATURE_ENABLED_MIN,
3600 CFG_OKC_FEATURE_ENABLED_MAX);
3601 ret = -EINVAL;
3602 goto exit;
3603 }
3604
3605 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3606 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3607 {
3608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3609 "Okc mode value %d is out of range"
3610 " (Min: %d Max: %d)", okcMode,
3611 CFG_OKC_FEATURE_ENABLED_MIN,
3612 CFG_OKC_FEATURE_ENABLED_MAX);
3613 ret = -EINVAL;
3614 goto exit;
3615 }
3616
3617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3618 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3619
3620 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3621 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003622#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003623 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3624 {
3625 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3626 char extra[32];
3627 tANI_U8 len = 0;
3628
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003629 len = scnprintf(extra, sizeof(extra), "%s %d",
3630 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003631 if (copy_to_user(priv_data.buf, &extra, len + 1))
3632 {
3633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3634 "%s: failed to copy data to user buffer", __func__);
3635 ret = -EFAULT;
3636 goto exit;
3637 }
3638 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303639#ifdef WLAN_FEATURE_PACKET_FILTERING
3640 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3641 {
3642 tANI_U8 filterType = 0;
3643 tANI_U8 *value = command;
3644
3645 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3646 value = value + 22;
3647
3648 /* Convert the value from ascii to integer */
3649 ret = kstrtou8(value, 10, &filterType);
3650 if (ret < 0)
3651 {
3652 /* If the input value is greater than max value of datatype,
3653 * then also kstrtou8 fails
3654 */
3655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3656 "%s: kstrtou8 failed range ", __func__);
3657 ret = -EINVAL;
3658 goto exit;
3659 }
3660
3661 if (filterType != 0 && filterType != 1)
3662 {
3663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3664 "%s: Accepted Values are 0 and 1 ", __func__);
3665 ret = -EINVAL;
3666 goto exit;
3667 }
3668 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3669 pAdapter->sessionId);
3670 }
3671#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303672 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3673 {
Kiet Lamad161252014-07-22 11:23:32 -07003674 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303675 int ret;
3676
Kiet Lamad161252014-07-22 11:23:32 -07003677 dhcpPhase = command + 11;
3678 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303679 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003681 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303682
3683 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003684
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303685 ret = wlan_hdd_scan_abort(pAdapter);
3686 if (ret < 0)
3687 {
3688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3689 FL("failed to abort existing scan %d"), ret);
3690 }
3691
Kiet Lamad161252014-07-22 11:23:32 -07003692 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3693 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303694 }
Kiet Lamad161252014-07-22 11:23:32 -07003695 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303696 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003698 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303699
3700 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003701
3702 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3703 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303704 }
3705 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003706 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3707 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3709 FL("making default scan to ACTIVE"));
3710 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003711 }
3712 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3713 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3715 FL("making default scan to PASSIVE"));
3716 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003717 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303718 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3719 {
3720 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3721 char extra[32];
3722 tANI_U8 len = 0;
3723
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303724 memset(extra, 0, sizeof(extra));
3725 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3726 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303727 {
3728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3729 "%s: failed to copy data to user buffer", __func__);
3730 ret = -EFAULT;
3731 goto exit;
3732 }
3733 ret = len;
3734 }
3735 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3736 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303737 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303738 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003739 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3740 {
3741 tANI_U8 filterType = 0;
3742 tANI_U8 *value;
3743 value = command + 9;
3744
3745 /* Convert the value from ascii to integer */
3746 ret = kstrtou8(value, 10, &filterType);
3747 if (ret < 0)
3748 {
3749 /* If the input value is greater than max value of datatype,
3750 * then also kstrtou8 fails
3751 */
3752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3753 "%s: kstrtou8 failed range ", __func__);
3754 ret = -EINVAL;
3755 goto exit;
3756 }
3757 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3758 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3759 {
3760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3761 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3762 " 2-Sink ", __func__);
3763 ret = -EINVAL;
3764 goto exit;
3765 }
3766 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3767 pHddCtx->drvr_miracast = filterType;
3768 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303769 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003770 }
Leo Chang614d2072013-08-22 14:59:44 -07003771 else if (strncmp(command, "SETMCRATE", 9) == 0)
3772 {
Leo Chang614d2072013-08-22 14:59:44 -07003773 tANI_U8 *value = command;
3774 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003775 tSirRateUpdateInd *rateUpdate;
3776 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003777
3778 /* Only valid for SAP mode */
3779 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3780 {
3781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3782 "%s: SAP mode is not running", __func__);
3783 ret = -EFAULT;
3784 goto exit;
3785 }
3786
3787 /* Move pointer to ahead of SETMCRATE<delimiter> */
3788 /* input value is in units of hundred kbps */
3789 value = value + 10;
3790 /* Convert the value from ascii to integer, decimal base */
3791 ret = kstrtouint(value, 10, &targetRate);
3792
Leo Chang1f98cbd2013-10-17 15:03:52 -07003793 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3794 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003795 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003796 hddLog(VOS_TRACE_LEVEL_ERROR,
3797 "%s: SETMCRATE indication alloc fail", __func__);
3798 ret = -EFAULT;
3799 goto exit;
3800 }
3801 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3802
3803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3804 "MC Target rate %d", targetRate);
3805 /* Ignore unicast */
3806 rateUpdate->ucastDataRate = -1;
3807 rateUpdate->mcastDataRate24GHz = targetRate;
3808 rateUpdate->mcastDataRate5GHz = targetRate;
3809 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3810 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3811 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3812 if (eHAL_STATUS_SUCCESS != status)
3813 {
3814 hddLog(VOS_TRACE_LEVEL_ERROR,
3815 "%s: SET_MC_RATE failed", __func__);
3816 vos_mem_free(rateUpdate);
3817 ret = -EFAULT;
3818 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003819 }
3820 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303821#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003822 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303823 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003824 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303825 }
3826#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003827#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003828 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3829 {
3830 tANI_U8 *value = command;
3831 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3832 tANI_U8 numChannels = 0;
3833 eHalStatus status = eHAL_STATUS_SUCCESS;
3834
3835 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3836 if (eHAL_STATUS_SUCCESS != status)
3837 {
3838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3839 "%s: Failed to parse channel list information", __func__);
3840 ret = -EINVAL;
3841 goto exit;
3842 }
3843
3844 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3845 {
3846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3847 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3848 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3849 ret = -EINVAL;
3850 goto exit;
3851 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003852 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003853 ChannelList,
3854 numChannels);
3855 if (eHAL_STATUS_SUCCESS != status)
3856 {
3857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3858 "%s: Failed to update channel list information", __func__);
3859 ret = -EINVAL;
3860 goto exit;
3861 }
3862 }
3863 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3864 {
3865 tANI_U8 *value = command;
3866 char extra[128] = {0};
3867 int len = 0;
3868 tANI_U8 tid = 0;
3869 hdd_station_ctx_t *pHddStaCtx = NULL;
3870 tAniTrafStrmMetrics tsmMetrics;
3871 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3872
3873 /* if not associated, return error */
3874 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3875 {
3876 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3877 ret = -EINVAL;
3878 goto exit;
3879 }
3880
3881 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3882 value = value + 12;
3883 /* Convert the value from ascii to integer */
3884 ret = kstrtou8(value, 10, &tid);
3885 if (ret < 0)
3886 {
3887 /* If the input value is greater than max value of datatype, then also
3888 kstrtou8 fails */
3889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3890 "%s: kstrtou8 failed range [%d - %d]", __func__,
3891 TID_MIN_VALUE,
3892 TID_MAX_VALUE);
3893 ret = -EINVAL;
3894 goto exit;
3895 }
3896
3897 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3898 {
3899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3900 "tid value %d is out of range"
3901 " (Min: %d Max: %d)", tid,
3902 TID_MIN_VALUE,
3903 TID_MAX_VALUE);
3904 ret = -EINVAL;
3905 goto exit;
3906 }
3907
3908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3909 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3910
3911 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3912 {
3913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3914 "%s: failed to get tsm stats", __func__);
3915 ret = -EFAULT;
3916 goto exit;
3917 }
3918
3919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3920 "UplinkPktQueueDly(%d)\n"
3921 "UplinkPktQueueDlyHist[0](%d)\n"
3922 "UplinkPktQueueDlyHist[1](%d)\n"
3923 "UplinkPktQueueDlyHist[2](%d)\n"
3924 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303925 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003926 "UplinkPktLoss(%d)\n"
3927 "UplinkPktCount(%d)\n"
3928 "RoamingCount(%d)\n"
3929 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3930 tsmMetrics.UplinkPktQueueDlyHist[0],
3931 tsmMetrics.UplinkPktQueueDlyHist[1],
3932 tsmMetrics.UplinkPktQueueDlyHist[2],
3933 tsmMetrics.UplinkPktQueueDlyHist[3],
3934 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3935 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3936
3937 /* Output TSM stats is of the format
3938 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3939 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003940 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003941 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3942 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3943 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3944 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3945 tsmMetrics.RoamingDly);
3946
3947 if (copy_to_user(priv_data.buf, &extra, len + 1))
3948 {
3949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3950 "%s: failed to copy data to user buffer", __func__);
3951 ret = -EFAULT;
3952 goto exit;
3953 }
3954 }
3955 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3956 {
3957 tANI_U8 *value = command;
3958 tANI_U8 *cckmIe = NULL;
3959 tANI_U8 cckmIeLen = 0;
3960 eHalStatus status = eHAL_STATUS_SUCCESS;
3961
3962 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3963 if (eHAL_STATUS_SUCCESS != status)
3964 {
3965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3966 "%s: Failed to parse cckm ie data", __func__);
3967 ret = -EINVAL;
3968 goto exit;
3969 }
3970
3971 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3972 {
3973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3974 "%s: CCKM Ie input length is more than max[%d]", __func__,
3975 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003976 vos_mem_free(cckmIe);
3977 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003978 ret = -EINVAL;
3979 goto exit;
3980 }
3981 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003982 vos_mem_free(cckmIe);
3983 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003984 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003985 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3986 {
3987 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003988 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003989 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003990
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003991 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003992 if (eHAL_STATUS_SUCCESS != status)
3993 {
3994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003995 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003996 ret = -EINVAL;
3997 goto exit;
3998 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003999 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4000 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4001 hdd_indicateEseBcnReportNoResults (pAdapter,
4002 eseBcnReq.bcnReq[0].measurementToken,
4003 0x02, //BIT(1) set for measurement done
4004 0); // no BSS
4005 goto exit;
4006 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004007
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004008 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4009 if (eHAL_STATUS_SUCCESS != status)
4010 {
4011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4012 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4013 ret = -EINVAL;
4014 goto exit;
4015 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004016 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004017#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304018 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4019 {
4020 eHalStatus status;
4021 char buf[32], len;
4022 long waitRet;
4023 bcnMissRateContext_t getBcnMissRateCtx;
4024
4025 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4026
4027 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4028 {
4029 hddLog(VOS_TRACE_LEVEL_WARN,
4030 FL("GETBCNMISSRATE: STA is not in connected state"));
4031 ret = -1;
4032 goto exit;
4033 }
4034
4035 init_completion(&(getBcnMissRateCtx.completion));
4036 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4037
4038 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4039 pAdapter->sessionId,
4040 (void *)getBcnMissRateCB,
4041 (void *)(&getBcnMissRateCtx));
4042 if( eHAL_STATUS_SUCCESS != status)
4043 {
4044 hddLog(VOS_TRACE_LEVEL_INFO,
4045 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4046 ret = -EINVAL;
4047 goto exit;
4048 }
4049
4050 waitRet = wait_for_completion_interruptible_timeout
4051 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4052 if(waitRet <= 0)
4053 {
4054 hddLog(VOS_TRACE_LEVEL_ERROR,
4055 FL("failed to wait on bcnMissRateComp %d"), ret);
4056
4057 //Make magic number to zero so that callback is not called.
4058 spin_lock(&hdd_context_lock);
4059 getBcnMissRateCtx.magic = 0x0;
4060 spin_unlock(&hdd_context_lock);
4061 ret = -EINVAL;
4062 goto exit;
4063 }
4064
4065 hddLog(VOS_TRACE_LEVEL_INFO,
4066 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4067
4068 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4069 if (copy_to_user(priv_data.buf, &buf, len + 1))
4070 {
4071 hddLog(VOS_TRACE_LEVEL_ERROR,
4072 "%s: failed to copy data to user buffer", __func__);
4073 ret = -EFAULT;
4074 goto exit;
4075 }
4076 ret = len;
4077 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304078#ifdef FEATURE_WLAN_TDLS
4079 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4080 tANI_U8 *value = command;
4081 int set_value;
4082 /* Move pointer to ahead of TDLSOFFCH*/
4083 value += 26;
4084 sscanf(value, "%d", &set_value);
4085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4086 "%s: Tdls offchannel offset:%d",
4087 __func__, set_value);
4088 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4089 if (ret < 0)
4090 {
4091 ret = -EINVAL;
4092 goto exit;
4093 }
4094
4095 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4096 tANI_U8 *value = command;
4097 int set_value;
4098 /* Move pointer to ahead of tdlsoffchnmode*/
4099 value += 18;
4100 sscanf(value, "%d", &set_value);
4101 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4102 "%s: Tdls offchannel mode:%d",
4103 __func__, set_value);
4104 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4105 if (ret < 0)
4106 {
4107 ret = -EINVAL;
4108 goto exit;
4109 }
4110 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4111 tANI_U8 *value = command;
4112 int set_value;
4113 /* Move pointer to ahead of TDLSOFFCH*/
4114 value += 14;
4115 sscanf(value, "%d", &set_value);
4116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4117 "%s: Tdls offchannel num: %d",
4118 __func__, set_value);
4119 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4120 if (ret < 0)
4121 {
4122 ret = -EINVAL;
4123 goto exit;
4124 }
4125 }
4126#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004127 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304128 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4129 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4130 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004131 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4132 __func__, command);
4133 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004134 }
4135exit:
4136 if (command)
4137 {
4138 kfree(command);
4139 }
4140 return ret;
4141}
4142
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004143#ifdef CONFIG_COMPAT
4144static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4145{
4146 struct {
4147 compat_uptr_t buf;
4148 int used_len;
4149 int total_len;
4150 } compat_priv_data;
4151 hdd_priv_data_t priv_data;
4152 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004153
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004154 /*
4155 * Note that pAdapter and ifr have already been verified by caller,
4156 * and HDD context has also been validated
4157 */
4158 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4159 sizeof(compat_priv_data))) {
4160 ret = -EFAULT;
4161 goto exit;
4162 }
4163 priv_data.buf = compat_ptr(compat_priv_data.buf);
4164 priv_data.used_len = compat_priv_data.used_len;
4165 priv_data.total_len = compat_priv_data.total_len;
4166 ret = hdd_driver_command(pAdapter, &priv_data);
4167 exit:
4168 return ret;
4169}
4170#else /* CONFIG_COMPAT */
4171static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4172{
4173 /* will never be invoked */
4174 return 0;
4175}
4176#endif /* CONFIG_COMPAT */
4177
4178static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4179{
4180 hdd_priv_data_t priv_data;
4181 int ret = 0;
4182
4183 /*
4184 * Note that pAdapter and ifr have already been verified by caller,
4185 * and HDD context has also been validated
4186 */
4187 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4188 ret = -EFAULT;
4189 } else {
4190 ret = hdd_driver_command(pAdapter, &priv_data);
4191 }
4192 return ret;
4193}
4194
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304195int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004196{
4197 hdd_adapter_t *pAdapter;
4198 hdd_context_t *pHddCtx;
4199 int ret;
4200
4201 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4202 if (NULL == pAdapter) {
4203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4204 "%s: HDD adapter context is Null", __func__);
4205 ret = -ENODEV;
4206 goto exit;
4207 }
4208 if (dev != pAdapter->dev) {
4209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4210 "%s: HDD adapter/dev inconsistency", __func__);
4211 ret = -ENODEV;
4212 goto exit;
4213 }
4214
4215 if ((!ifr) || (!ifr->ifr_data)) {
4216 ret = -EINVAL;
4217 goto exit;
4218 }
4219
4220 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4221 ret = wlan_hdd_validate_context(pHddCtx);
4222 if (ret) {
4223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4224 "%s: invalid context", __func__);
4225 ret = -EBUSY;
4226 goto exit;
4227 }
4228
4229 switch (cmd) {
4230 case (SIOCDEVPRIVATE + 1):
4231 if (is_compat_task())
4232 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4233 else
4234 ret = hdd_driver_ioctl(pAdapter, ifr);
4235 break;
4236 default:
4237 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4238 __func__, cmd);
4239 ret = -EINVAL;
4240 break;
4241 }
4242 exit:
4243 return ret;
4244}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004245
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304246int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4247{
4248 int ret;
4249
4250 vos_ssr_protect(__func__);
4251 ret = __hdd_ioctl(dev, ifr, cmd);
4252 vos_ssr_unprotect(__func__);
4253
4254 return ret;
4255}
4256
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004257#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004258/**---------------------------------------------------------------------------
4259
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004260 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004261
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004262 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004263 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4264 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4265 <space>Scan Mode N<space>Meas Duration N
4266 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4267 then take N.
4268 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4269 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4270 This function does not take care of removing duplicate channels from the list
4271
4272 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004273 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004274
4275 \return - 0 for success non-zero for failure
4276
4277 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004278static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4279 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004280{
4281 tANI_U8 *inPtr = pValue;
4282 int tempInt = 0;
4283 int j = 0, i = 0, v = 0;
4284 char buf[32];
4285
4286 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4287 /*no argument after the command*/
4288 if (NULL == inPtr)
4289 {
4290 return -EINVAL;
4291 }
4292 /*no space after the command*/
4293 else if (SPACE_ASCII_VALUE != *inPtr)
4294 {
4295 return -EINVAL;
4296 }
4297
4298 /*removing empty spaces*/
4299 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4300
4301 /*no argument followed by spaces*/
4302 if ('\0' == *inPtr) return -EINVAL;
4303
4304 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004305 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004306 if (1 != v) return -EINVAL;
4307
4308 v = kstrtos32(buf, 10, &tempInt);
4309 if ( v < 0) return -EINVAL;
4310
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004311 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004312
4313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004314 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004315
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004316 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004317 {
4318 for (i = 0; i < 4; i++)
4319 {
4320 /*inPtr pointing to the beginning of first space after number of ie fields*/
4321 inPtr = strpbrk( inPtr, " " );
4322 /*no ie data after the number of ie fields argument*/
4323 if (NULL == inPtr) return -EINVAL;
4324
4325 /*removing empty space*/
4326 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4327
4328 /*no ie data after the number of ie fields argument and spaces*/
4329 if ( '\0' == *inPtr ) return -EINVAL;
4330
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004331 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004332 if (1 != v) return -EINVAL;
4333
4334 v = kstrtos32(buf, 10, &tempInt);
4335 if (v < 0) return -EINVAL;
4336
4337 switch (i)
4338 {
4339 case 0: /* Measurement token */
4340 if (tempInt <= 0)
4341 {
4342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4343 "Invalid Measurement Token(%d)", tempInt);
4344 return -EINVAL;
4345 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004346 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004347 break;
4348
4349 case 1: /* Channel number */
4350 if ((tempInt <= 0) ||
4351 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4352 {
4353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4354 "Invalid Channel Number(%d)", tempInt);
4355 return -EINVAL;
4356 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004357 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004358 break;
4359
4360 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004361 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004362 {
4363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4364 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4365 return -EINVAL;
4366 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004367 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004368 break;
4369
4370 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004371 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4372 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004373 {
4374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4375 "Invalid Measurement Duration(%d)", tempInt);
4376 return -EINVAL;
4377 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004378 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004379 break;
4380 }
4381 }
4382 }
4383
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004384 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004385 {
4386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304387 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004388 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004389 pEseBcnReq->bcnReq[j].measurementToken,
4390 pEseBcnReq->bcnReq[j].channel,
4391 pEseBcnReq->bcnReq[j].scanMode,
4392 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004393 }
4394
4395 return VOS_STATUS_SUCCESS;
4396}
4397
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004398static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4399{
4400 struct statsContext *pStatsContext = NULL;
4401 hdd_adapter_t *pAdapter = NULL;
4402
4403 if (NULL == pContext)
4404 {
4405 hddLog(VOS_TRACE_LEVEL_ERROR,
4406 "%s: Bad param, pContext [%p]",
4407 __func__, pContext);
4408 return;
4409 }
4410
Jeff Johnson72a40512013-12-19 10:14:15 -08004411 /* there is a race condition that exists between this callback
4412 function and the caller since the caller could time out either
4413 before or while this code is executing. we use a spinlock to
4414 serialize these actions */
4415 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004416
4417 pStatsContext = pContext;
4418 pAdapter = pStatsContext->pAdapter;
4419 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4420 {
4421 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004422 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004423 hddLog(VOS_TRACE_LEVEL_WARN,
4424 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4425 __func__, pAdapter, pStatsContext->magic);
4426 return;
4427 }
4428
Jeff Johnson72a40512013-12-19 10:14:15 -08004429 /* context is valid so caller is still waiting */
4430
4431 /* paranoia: invalidate the magic */
4432 pStatsContext->magic = 0;
4433
4434 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004435 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4436 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4437 tsmMetrics.UplinkPktQueueDlyHist,
4438 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4439 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4440 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4441 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4442 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4443 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4444 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4445
Jeff Johnson72a40512013-12-19 10:14:15 -08004446 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004447 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004448
4449 /* serialization is complete */
4450 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004451}
4452
4453
4454
4455static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4456 tAniTrafStrmMetrics* pTsmMetrics)
4457{
4458 hdd_station_ctx_t *pHddStaCtx = NULL;
4459 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004460 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004461 long lrc;
4462 struct statsContext context;
4463 hdd_context_t *pHddCtx = NULL;
4464
4465 if (NULL == pAdapter)
4466 {
4467 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4468 return VOS_STATUS_E_FAULT;
4469 }
4470
4471 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4472 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4473
4474 /* we are connected prepare our callback context */
4475 init_completion(&context.completion);
4476 context.pAdapter = pAdapter;
4477 context.magic = STATS_CONTEXT_MAGIC;
4478
4479 /* query tsm stats */
4480 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4481 pHddStaCtx->conn_info.staId[ 0 ],
4482 pHddStaCtx->conn_info.bssId,
4483 &context, pHddCtx->pvosContext, tid);
4484
4485 if (eHAL_STATUS_SUCCESS != hstatus)
4486 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004487 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4488 __func__);
4489 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004490 }
4491 else
4492 {
4493 /* request was sent -- wait for the response */
4494 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4495 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004496 if (lrc <= 0)
4497 {
4498 hddLog(VOS_TRACE_LEVEL_ERROR,
4499 "%s: SME %s while retrieving statistics",
4500 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004501 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004502 }
4503 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004504
Jeff Johnson72a40512013-12-19 10:14:15 -08004505 /* either we never sent a request, we sent a request and received a
4506 response or we sent a request and timed out. if we never sent a
4507 request or if we sent a request and got a response, we want to
4508 clear the magic out of paranoia. if we timed out there is a
4509 race condition such that the callback function could be
4510 executing at the same time we are. of primary concern is if the
4511 callback function had already verified the "magic" but had not
4512 yet set the completion variable when a timeout occurred. we
4513 serialize these activities by invalidating the magic while
4514 holding a shared spinlock which will cause us to block if the
4515 callback is currently executing */
4516 spin_lock(&hdd_context_lock);
4517 context.magic = 0;
4518 spin_unlock(&hdd_context_lock);
4519
4520 if (VOS_STATUS_SUCCESS == vstatus)
4521 {
4522 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4523 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4524 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4525 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4526 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4527 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4528 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4529 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4530 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4531 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4532 }
4533 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004534}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004535#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004536
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004537#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004538void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4539{
4540 eCsrBand band = -1;
4541 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4542 switch (band)
4543 {
4544 case eCSR_BAND_ALL:
4545 *pBand = WLAN_HDD_UI_BAND_AUTO;
4546 break;
4547
4548 case eCSR_BAND_24:
4549 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4550 break;
4551
4552 case eCSR_BAND_5G:
4553 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4554 break;
4555
4556 default:
4557 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4558 *pBand = -1;
4559 break;
4560 }
4561}
4562
4563/**---------------------------------------------------------------------------
4564
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004565 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4566
4567 This function parses the send action frame data passed in the format
4568 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4569
Srinivas Girigowda56076852013-08-20 14:00:50 -07004570 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004571 \param - pTargetApBssid Pointer to target Ap bssid
4572 \param - pChannel Pointer to the Target AP channel
4573 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4574 \param - pBuf Pointer to data
4575 \param - pBufLen Pointer to data length
4576
4577 \return - 0 for success non-zero for failure
4578
4579 --------------------------------------------------------------------------*/
4580VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4581 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4582{
4583 tANI_U8 *inPtr = pValue;
4584 tANI_U8 *dataEnd;
4585 int tempInt;
4586 int j = 0;
4587 int i = 0;
4588 int v = 0;
4589 tANI_U8 tempBuf[32];
4590 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004591 /* 12 hexa decimal digits, 5 ':' and '\0' */
4592 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004593
4594 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4595 /*no argument after the command*/
4596 if (NULL == inPtr)
4597 {
4598 return -EINVAL;
4599 }
4600
4601 /*no space after the command*/
4602 else if (SPACE_ASCII_VALUE != *inPtr)
4603 {
4604 return -EINVAL;
4605 }
4606
4607 /*removing empty spaces*/
4608 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4609
4610 /*no argument followed by spaces*/
4611 if ('\0' == *inPtr)
4612 {
4613 return -EINVAL;
4614 }
4615
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004616 v = sscanf(inPtr, "%17s", macAddress);
4617 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004618 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4620 "Invalid MAC address or All hex inputs are not read (%d)", v);
4621 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004622 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004623
4624 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4625 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4626 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4627 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4628 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4629 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004630
4631 /* point to the next argument */
4632 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4633 /*no argument after the command*/
4634 if (NULL == inPtr) return -EINVAL;
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 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004646 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004647 if (1 != v) return -EINVAL;
4648
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004649 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304650 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304651 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004652
4653 *pChannel = tempInt;
4654
4655 /* point to the next argument */
4656 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4657 /*no argument after the command*/
4658 if (NULL == inPtr) return -EINVAL;
4659 /*removing empty spaces*/
4660 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4661
4662 /*no argument followed by spaces*/
4663 if ('\0' == *inPtr)
4664 {
4665 return -EINVAL;
4666 }
4667
4668 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004669 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004670 if (1 != v) return -EINVAL;
4671
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004672 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004673 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004674
4675 *pDwellTime = tempInt;
4676
4677 /* point to the next argument */
4678 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4679 /*no argument after the command*/
4680 if (NULL == inPtr) return -EINVAL;
4681 /*removing empty spaces*/
4682 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4683
4684 /*no argument followed by spaces*/
4685 if ('\0' == *inPtr)
4686 {
4687 return -EINVAL;
4688 }
4689
4690 /* find the length of data */
4691 dataEnd = inPtr;
4692 while(('\0' != *dataEnd) )
4693 {
4694 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004695 }
Kiet Lambe150c22013-11-21 16:30:32 +05304696 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004697 if ( *pBufLen <= 0) return -EINVAL;
4698
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004699 /* Allocate the number of bytes based on the number of input characters
4700 whether it is even or odd.
4701 if the number of input characters are even, then we need N/2 byte.
4702 if the number of input characters are odd, then we need do (N+1)/2 to
4703 compensate rounding off.
4704 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4705 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4706 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004707 if (NULL == *pBuf)
4708 {
4709 hddLog(VOS_TRACE_LEVEL_FATAL,
4710 "%s: vos_mem_alloc failed ", __func__);
4711 return -EINVAL;
4712 }
4713
4714 /* the buffer received from the upper layer is character buffer,
4715 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4716 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4717 and f0 in 3rd location */
4718 for (i = 0, j = 0; j < *pBufLen; j += 2)
4719 {
Kiet Lambe150c22013-11-21 16:30:32 +05304720 if( j+1 == *pBufLen)
4721 {
4722 tempByte = hdd_parse_hex(inPtr[j]);
4723 }
4724 else
4725 {
4726 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4727 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004728 (*pBuf)[i++] = tempByte;
4729 }
4730 *pBufLen = i;
4731 return VOS_STATUS_SUCCESS;
4732}
4733
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004734/**---------------------------------------------------------------------------
4735
Srinivas Girigowdade697412013-02-14 16:31:48 -08004736 \brief hdd_parse_channellist() - HDD Parse channel list
4737
4738 This function parses the channel list passed in the format
4739 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004740 if the Number of channels (N) does not match with the actual number of channels passed
4741 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4742 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4743 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4744 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004745
4746 \param - pValue Pointer to input channel list
4747 \param - ChannelList Pointer to local output array to record channel list
4748 \param - pNumChannels Pointer to number of roam scan channels
4749
4750 \return - 0 for success non-zero for failure
4751
4752 --------------------------------------------------------------------------*/
4753VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4754{
4755 tANI_U8 *inPtr = pValue;
4756 int tempInt;
4757 int j = 0;
4758 int v = 0;
4759 char buf[32];
4760
4761 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4762 /*no argument after the command*/
4763 if (NULL == inPtr)
4764 {
4765 return -EINVAL;
4766 }
4767
4768 /*no space after the command*/
4769 else if (SPACE_ASCII_VALUE != *inPtr)
4770 {
4771 return -EINVAL;
4772 }
4773
4774 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004775 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004776
4777 /*no argument followed by spaces*/
4778 if ('\0' == *inPtr)
4779 {
4780 return -EINVAL;
4781 }
4782
4783 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004784 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004785 if (1 != v) return -EINVAL;
4786
Srinivas Girigowdade697412013-02-14 16:31:48 -08004787 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004788 if ((v < 0) ||
4789 (tempInt <= 0) ||
4790 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4791 {
4792 return -EINVAL;
4793 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004794
4795 *pNumChannels = tempInt;
4796
4797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4798 "Number of channels are: %d", *pNumChannels);
4799
4800 for (j = 0; j < (*pNumChannels); j++)
4801 {
4802 /*inPtr pointing to the beginning of first space after number of channels*/
4803 inPtr = strpbrk( inPtr, " " );
4804 /*no channel list after the number of channels argument*/
4805 if (NULL == inPtr)
4806 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004807 if (0 != j)
4808 {
4809 *pNumChannels = j;
4810 return VOS_STATUS_SUCCESS;
4811 }
4812 else
4813 {
4814 return -EINVAL;
4815 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004816 }
4817
4818 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004819 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004820
4821 /*no channel list after the number of channels argument and spaces*/
4822 if ( '\0' == *inPtr )
4823 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004824 if (0 != j)
4825 {
4826 *pNumChannels = j;
4827 return VOS_STATUS_SUCCESS;
4828 }
4829 else
4830 {
4831 return -EINVAL;
4832 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004833 }
4834
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004835 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004836 if (1 != v) return -EINVAL;
4837
Srinivas Girigowdade697412013-02-14 16:31:48 -08004838 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004839 if ((v < 0) ||
4840 (tempInt <= 0) ||
4841 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4842 {
4843 return -EINVAL;
4844 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004845 pChannelList[j] = tempInt;
4846
4847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4848 "Channel %d added to preferred channel list",
4849 pChannelList[j] );
4850 }
4851
Srinivas Girigowdade697412013-02-14 16:31:48 -08004852 return VOS_STATUS_SUCCESS;
4853}
4854
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004855
4856/**---------------------------------------------------------------------------
4857
4858 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4859
4860 This function parses the reasoc command data passed in the format
4861 REASSOC<space><bssid><space><channel>
4862
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004863 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004864 \param - pTargetApBssid Pointer to target Ap bssid
4865 \param - pChannel Pointer to the Target AP channel
4866
4867 \return - 0 for success non-zero for failure
4868
4869 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004870VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4871 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004872{
4873 tANI_U8 *inPtr = pValue;
4874 int tempInt;
4875 int v = 0;
4876 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004877 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004878 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004879
4880 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4881 /*no argument after the command*/
4882 if (NULL == inPtr)
4883 {
4884 return -EINVAL;
4885 }
4886
4887 /*no space after the command*/
4888 else if (SPACE_ASCII_VALUE != *inPtr)
4889 {
4890 return -EINVAL;
4891 }
4892
4893 /*removing empty spaces*/
4894 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4895
4896 /*no argument followed by spaces*/
4897 if ('\0' == *inPtr)
4898 {
4899 return -EINVAL;
4900 }
4901
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004902 v = sscanf(inPtr, "%17s", macAddress);
4903 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004904 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4906 "Invalid MAC address or All hex inputs are not read (%d)", v);
4907 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004908 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004909
4910 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4911 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4912 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4913 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4914 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4915 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004916
4917 /* point to the next argument */
4918 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4919 /*no argument after the command*/
4920 if (NULL == inPtr) return -EINVAL;
4921
4922 /*removing empty spaces*/
4923 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4924
4925 /*no argument followed by spaces*/
4926 if ('\0' == *inPtr)
4927 {
4928 return -EINVAL;
4929 }
4930
4931 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004932 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004933 if (1 != v) return -EINVAL;
4934
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004935 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004936 if ((v < 0) ||
4937 (tempInt <= 0) ||
4938 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4939 {
4940 return -EINVAL;
4941 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004942
4943 *pChannel = tempInt;
4944 return VOS_STATUS_SUCCESS;
4945}
4946
4947#endif
4948
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004949#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004950/**---------------------------------------------------------------------------
4951
4952 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4953
4954 This function parses the SETCCKM IE command
4955 SETCCKMIE<space><ie data>
4956
4957 \param - pValue Pointer to input data
4958 \param - pCckmIe Pointer to output cckm Ie
4959 \param - pCckmIeLen Pointer to output cckm ie length
4960
4961 \return - 0 for success non-zero for failure
4962
4963 --------------------------------------------------------------------------*/
4964VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4965 tANI_U8 *pCckmIeLen)
4966{
4967 tANI_U8 *inPtr = pValue;
4968 tANI_U8 *dataEnd;
4969 int j = 0;
4970 int i = 0;
4971 tANI_U8 tempByte = 0;
4972
4973 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4974 /*no argument after the command*/
4975 if (NULL == inPtr)
4976 {
4977 return -EINVAL;
4978 }
4979
4980 /*no space after the command*/
4981 else if (SPACE_ASCII_VALUE != *inPtr)
4982 {
4983 return -EINVAL;
4984 }
4985
4986 /*removing empty spaces*/
4987 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4988
4989 /*no argument followed by spaces*/
4990 if ('\0' == *inPtr)
4991 {
4992 return -EINVAL;
4993 }
4994
4995 /* find the length of data */
4996 dataEnd = inPtr;
4997 while(('\0' != *dataEnd) )
4998 {
4999 dataEnd++;
5000 ++(*pCckmIeLen);
5001 }
5002 if ( *pCckmIeLen <= 0) return -EINVAL;
5003
5004 /* Allocate the number of bytes based on the number of input characters
5005 whether it is even or odd.
5006 if the number of input characters are even, then we need N/2 byte.
5007 if the number of input characters are odd, then we need do (N+1)/2 to
5008 compensate rounding off.
5009 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5010 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5011 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5012 if (NULL == *pCckmIe)
5013 {
5014 hddLog(VOS_TRACE_LEVEL_FATAL,
5015 "%s: vos_mem_alloc failed ", __func__);
5016 return -EINVAL;
5017 }
5018 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5019 /* the buffer received from the upper layer is character buffer,
5020 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5021 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5022 and f0 in 3rd location */
5023 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5024 {
5025 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5026 (*pCckmIe)[i++] = tempByte;
5027 }
5028 *pCckmIeLen = i;
5029
5030 return VOS_STATUS_SUCCESS;
5031}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005032#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034/**---------------------------------------------------------------------------
5035
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005036 \brief hdd_is_valid_mac_address() - Validate MAC address
5037
5038 This function validates whether the given MAC address is valid or not
5039 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5040 where X is the hexa decimal digit character and separated by ':'
5041 This algorithm works even if MAC address is not separated by ':'
5042
5043 This code checks given input string mac contains exactly 12 hexadecimal digits.
5044 and a separator colon : appears in the input string only after
5045 an even number of hex digits.
5046
5047 \param - pMacAddr pointer to the input MAC address
5048 \return - 1 for valid and 0 for invalid
5049
5050 --------------------------------------------------------------------------*/
5051
5052v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5053{
5054 int xdigit = 0;
5055 int separator = 0;
5056 while (*pMacAddr)
5057 {
5058 if (isxdigit(*pMacAddr))
5059 {
5060 xdigit++;
5061 }
5062 else if (':' == *pMacAddr)
5063 {
5064 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5065 break;
5066
5067 ++separator;
5068 }
5069 else
5070 {
5071 separator = -1;
5072 /* Invalid MAC found */
5073 return 0;
5074 }
5075 ++pMacAddr;
5076 }
5077 return (xdigit == 12 && (separator == 5 || separator == 0));
5078}
5079
5080/**---------------------------------------------------------------------------
5081
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305082 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005083
5084 \param - dev Pointer to net_device structure
5085
5086 \return - 0 for success non-zero for failure
5087
5088 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305089int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005090{
5091 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5092 hdd_context_t *pHddCtx;
5093 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5094 VOS_STATUS status;
5095 v_BOOL_t in_standby = TRUE;
5096
5097 if (NULL == pAdapter)
5098 {
5099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305100 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005101 return -ENODEV;
5102 }
5103
5104 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305105 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5106 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 if (NULL == pHddCtx)
5108 {
5109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005110 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 return -ENODEV;
5112 }
5113
5114 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5115 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5116 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005117 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5118 {
5119 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305120 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005121 in_standby = FALSE;
5122 break;
5123 }
5124 else
5125 {
5126 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5127 pAdapterNode = pNext;
5128 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 }
5130
5131 if (TRUE == in_standby)
5132 {
5133 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5134 {
5135 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5136 "wlan out of power save", __func__);
5137 return -EINVAL;
5138 }
5139 }
5140
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005141 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005142 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5143 {
5144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005145 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 /* Enable TX queues only when we are connected */
5147 netif_tx_start_all_queues(dev);
5148 }
5149
5150 return 0;
5151}
5152
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305153/**---------------------------------------------------------------------------
5154
5155 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5156
5157 This is called in response to ifconfig up
5158
5159 \param - dev Pointer to net_device structure
5160
5161 \return - 0 for success non-zero for failure
5162
5163 --------------------------------------------------------------------------*/
5164int hdd_open(struct net_device *dev)
5165{
5166 int ret;
5167
5168 vos_ssr_protect(__func__);
5169 ret = __hdd_open(dev);
5170 vos_ssr_unprotect(__func__);
5171
5172 return ret;
5173}
5174
Jeff Johnson295189b2012-06-20 16:38:30 -07005175int hdd_mon_open (struct net_device *dev)
5176{
5177 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5178
5179 if(pAdapter == NULL) {
5180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005181 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005182 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 }
5184
5185 netif_start_queue(dev);
5186
5187 return 0;
5188}
5189/**---------------------------------------------------------------------------
5190
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305191 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005192
5193 \param - dev Pointer to net_device structure
5194
5195 \return - 0 for success non-zero for failure
5196
5197 --------------------------------------------------------------------------*/
5198
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305199int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005200{
5201 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5202 hdd_context_t *pHddCtx;
5203 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5204 VOS_STATUS status;
5205 v_BOOL_t enter_standby = TRUE;
5206
5207 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 if (NULL == pAdapter)
5209 {
5210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305211 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 return -ENODEV;
5213 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305214 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5215 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005216 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5217 if (NULL == pHddCtx)
5218 {
5219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005220 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 return -ENODEV;
5222 }
5223
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305224 /* Nothing to be done if the interface is not opened */
5225 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5226 {
5227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5228 "%s: NETDEV Interface is not OPENED", __func__);
5229 return -ENODEV;
5230 }
5231
5232 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005233 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305235
5236 /* Disable TX on the interface, after this hard_start_xmit() will not
5237 * be called on that interface
5238 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305240
5241 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 netif_carrier_off(pAdapter->dev);
5243
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305244 /* The interface is marked as down for outside world (aka kernel)
5245 * But the driver is pretty much alive inside. The driver needs to
5246 * tear down the existing connection on the netdev (session)
5247 * cleanup the data pipes and wait until the control plane is stabilized
5248 * for this interface. The call also needs to wait until the above
5249 * mentioned actions are completed before returning to the caller.
5250 * Notice that the hdd_stop_adapter is requested not to close the session
5251 * That is intentional to be able to scan if it is a STA/P2P interface
5252 */
5253 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005254
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305255 /* DeInit the adapter. This ensures datapath cleanup as well */
5256 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005257 /* SoftAP ifaces should never go in power save mode
5258 making sure same here. */
5259 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5260 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 )
5263 {
5264 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5266 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005267 EXIT();
5268 return 0;
5269 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305270 /* Find if any iface is up. If any iface is up then can't put device to
5271 * sleep/power save mode
5272 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5274 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5275 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005276 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5277 {
5278 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305279 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005280 enter_standby = FALSE;
5281 break;
5282 }
5283 else
5284 {
5285 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5286 pAdapterNode = pNext;
5287 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 }
5289
5290 if (TRUE == enter_standby)
5291 {
5292 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5293 "entering standby", __func__);
5294 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5295 {
5296 /*log and return success*/
5297 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5298 "wlan in power save", __func__);
5299 }
5300 }
5301
5302 EXIT();
5303 return 0;
5304}
5305
5306/**---------------------------------------------------------------------------
5307
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305308 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005309
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305310 This is called in response to ifconfig down
5311
5312 \param - dev Pointer to net_device structure
5313
5314 \return - 0 for success non-zero for failure
5315-----------------------------------------------------------------------------*/
5316int hdd_stop (struct net_device *dev)
5317{
5318 int ret;
5319
5320 vos_ssr_protect(__func__);
5321 ret = __hdd_stop(dev);
5322 vos_ssr_unprotect(__func__);
5323
5324 return ret;
5325}
5326
5327/**---------------------------------------------------------------------------
5328
5329 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005330
5331 \param - dev Pointer to net_device structure
5332
5333 \return - void
5334
5335 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305336static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005337{
5338 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5339
5340 ENTER();
5341
5342 do
5343 {
5344 if (NULL == pAdapter)
5345 {
5346 hddLog(VOS_TRACE_LEVEL_FATAL,
5347 "%s: NULL pAdapter", __func__);
5348 break;
5349 }
5350
5351 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5352 {
5353 hddLog(VOS_TRACE_LEVEL_FATAL,
5354 "%s: Invalid magic", __func__);
5355 break;
5356 }
5357
5358 if (NULL == pAdapter->pHddCtx)
5359 {
5360 hddLog(VOS_TRACE_LEVEL_FATAL,
5361 "%s: NULL pHddCtx", __func__);
5362 break;
5363 }
5364
5365 if (dev != pAdapter->dev)
5366 {
5367 hddLog(VOS_TRACE_LEVEL_FATAL,
5368 "%s: Invalid device reference", __func__);
5369 /* we haven't validated all cases so let this go for now */
5370 }
5371
5372 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5373
5374 /* after uninit our adapter structure will no longer be valid */
5375 pAdapter->dev = NULL;
5376 pAdapter->magic = 0;
5377 } while (0);
5378
5379 EXIT();
5380}
5381
5382/**---------------------------------------------------------------------------
5383
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305384 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5385
5386 This is called during the netdev unregister to uninitialize all data
5387associated with the device
5388
5389 \param - dev Pointer to net_device structure
5390
5391 \return - void
5392
5393 --------------------------------------------------------------------------*/
5394static void hdd_uninit (struct net_device *dev)
5395{
5396 vos_ssr_protect(__func__);
5397 __hdd_uninit(dev);
5398 vos_ssr_unprotect(__func__);
5399}
5400
5401/**---------------------------------------------------------------------------
5402
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 \brief hdd_release_firmware() -
5404
5405 This function calls the release firmware API to free the firmware buffer.
5406
5407 \param - pFileName Pointer to the File Name.
5408 pCtx - Pointer to the adapter .
5409
5410
5411 \return - 0 for success, non zero for failure
5412
5413 --------------------------------------------------------------------------*/
5414
5415VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5416{
5417 VOS_STATUS status = VOS_STATUS_SUCCESS;
5418 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5419 ENTER();
5420
5421
5422 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5423
5424 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5425
5426 if(pHddCtx->fw) {
5427 release_firmware(pHddCtx->fw);
5428 pHddCtx->fw = NULL;
5429 }
5430 else
5431 status = VOS_STATUS_E_FAILURE;
5432 }
5433 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5434 if(pHddCtx->nv) {
5435 release_firmware(pHddCtx->nv);
5436 pHddCtx->nv = NULL;
5437 }
5438 else
5439 status = VOS_STATUS_E_FAILURE;
5440
5441 }
5442
5443 EXIT();
5444 return status;
5445}
5446
5447/**---------------------------------------------------------------------------
5448
5449 \brief hdd_request_firmware() -
5450
5451 This function reads the firmware file using the request firmware
5452 API and returns the the firmware data and the firmware file size.
5453
5454 \param - pfileName - Pointer to the file name.
5455 - pCtx - Pointer to the adapter .
5456 - ppfw_data - Pointer to the pointer of the firmware data.
5457 - pSize - Pointer to the file size.
5458
5459 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5460
5461 --------------------------------------------------------------------------*/
5462
5463
5464VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5465{
5466 int status;
5467 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5468 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5469 ENTER();
5470
5471 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5472
5473 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5474
5475 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5476 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5477 __func__, pfileName);
5478 retval = VOS_STATUS_E_FAILURE;
5479 }
5480
5481 else {
5482 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5483 *pSize = pHddCtx->fw->size;
5484 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5485 __func__, *pSize);
5486 }
5487 }
5488 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5489
5490 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5491
5492 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5493 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5494 __func__, pfileName);
5495 retval = VOS_STATUS_E_FAILURE;
5496 }
5497
5498 else {
5499 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5500 *pSize = pHddCtx->nv->size;
5501 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5502 __func__, *pSize);
5503 }
5504 }
5505
5506 EXIT();
5507 return retval;
5508}
5509/**---------------------------------------------------------------------------
5510 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5511
5512 This is the function invoked by SME to inform the result of a full power
5513 request issued by HDD
5514
5515 \param - callbackcontext - Pointer to cookie
5516 status - result of request
5517
5518 \return - None
5519
5520--------------------------------------------------------------------------*/
5521void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5522{
5523 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5524
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005525 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005526 if(&pHddCtx->full_pwr_comp_var)
5527 {
5528 complete(&pHddCtx->full_pwr_comp_var);
5529 }
5530}
5531
5532/**---------------------------------------------------------------------------
5533
5534 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5535
5536 This is the function invoked by SME to inform the result of BMPS
5537 request issued by HDD
5538
5539 \param - callbackcontext - Pointer to cookie
5540 status - result of request
5541
5542 \return - None
5543
5544--------------------------------------------------------------------------*/
5545void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5546{
5547
5548 struct completion *completion_var = (struct completion*) callbackContext;
5549
Arif Hussain6d2a3322013-11-17 19:50:10 -08005550 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 if(completion_var != NULL)
5552 {
5553 complete(completion_var);
5554 }
5555}
5556
5557/**---------------------------------------------------------------------------
5558
5559 \brief hdd_get_cfg_file_size() -
5560
5561 This function reads the configuration file using the request firmware
5562 API and returns the configuration file size.
5563
5564 \param - pCtx - Pointer to the adapter .
5565 - pFileName - Pointer to the file name.
5566 - pBufSize - Pointer to the buffer size.
5567
5568 \return - 0 for success, non zero for failure
5569
5570 --------------------------------------------------------------------------*/
5571
5572VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5573{
5574 int status;
5575 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5576
5577 ENTER();
5578
5579 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5580
5581 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5582 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5583 status = VOS_STATUS_E_FAILURE;
5584 }
5585 else {
5586 *pBufSize = pHddCtx->fw->size;
5587 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5588 release_firmware(pHddCtx->fw);
5589 pHddCtx->fw = NULL;
5590 }
5591
5592 EXIT();
5593 return VOS_STATUS_SUCCESS;
5594}
5595
5596/**---------------------------------------------------------------------------
5597
5598 \brief hdd_read_cfg_file() -
5599
5600 This function reads the configuration file using the request firmware
5601 API and returns the cfg data and the buffer size of the configuration file.
5602
5603 \param - pCtx - Pointer to the adapter .
5604 - pFileName - Pointer to the file name.
5605 - pBuffer - Pointer to the data buffer.
5606 - pBufSize - Pointer to the buffer size.
5607
5608 \return - 0 for success, non zero for failure
5609
5610 --------------------------------------------------------------------------*/
5611
5612VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5613 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5614{
5615 int status;
5616 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5617
5618 ENTER();
5619
5620 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5621
5622 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5623 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5624 return VOS_STATUS_E_FAILURE;
5625 }
5626 else {
5627 if(*pBufSize != pHddCtx->fw->size) {
5628 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5629 "file size", __func__);
5630 release_firmware(pHddCtx->fw);
5631 pHddCtx->fw = NULL;
5632 return VOS_STATUS_E_FAILURE;
5633 }
5634 else {
5635 if(pBuffer) {
5636 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5637 }
5638 release_firmware(pHddCtx->fw);
5639 pHddCtx->fw = NULL;
5640 }
5641 }
5642
5643 EXIT();
5644
5645 return VOS_STATUS_SUCCESS;
5646}
5647
5648/**---------------------------------------------------------------------------
5649
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305650 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005651
5652 This function sets the user specified mac address using
5653 the command ifconfig wlanX hw ether <mac adress>.
5654
5655 \param - dev - Pointer to the net device.
5656 - addr - Pointer to the sockaddr.
5657 \return - 0 for success, non zero for failure
5658
5659 --------------------------------------------------------------------------*/
5660
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305661static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005662{
5663 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5664 struct sockaddr *psta_mac_addr = addr;
5665 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5666
5667 ENTER();
5668
5669 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005670 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5671
5672 EXIT();
5673 return halStatus;
5674}
5675
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305676/**---------------------------------------------------------------------------
5677
5678 \brief hdd_set_mac_address() -
5679
5680 Wrapper function to protect __hdd_set_mac_address() function from ssr
5681
5682 \param - dev - Pointer to the net device.
5683 - addr - Pointer to the sockaddr.
5684 \return - 0 for success, non zero for failure
5685
5686 --------------------------------------------------------------------------*/
5687static int hdd_set_mac_address(struct net_device *dev, void *addr)
5688{
5689 int ret;
5690
5691 vos_ssr_protect(__func__);
5692 ret = __hdd_set_mac_address(dev, addr);
5693 vos_ssr_unprotect(__func__);
5694
5695 return ret;
5696}
5697
Jeff Johnson295189b2012-06-20 16:38:30 -07005698tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5699{
5700 int i;
5701 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5702 {
Abhishek Singheb183782014-02-06 13:37:21 +05305703 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005704 break;
5705 }
5706
5707 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5708 return NULL;
5709
5710 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5711 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5712}
5713
5714void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5715{
5716 int i;
5717 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5718 {
5719 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5720 {
5721 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5722 break;
5723 }
5724 }
5725 return;
5726}
5727
5728#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5729 static struct net_device_ops wlan_drv_ops = {
5730 .ndo_open = hdd_open,
5731 .ndo_stop = hdd_stop,
5732 .ndo_uninit = hdd_uninit,
5733 .ndo_start_xmit = hdd_hard_start_xmit,
5734 .ndo_tx_timeout = hdd_tx_timeout,
5735 .ndo_get_stats = hdd_stats,
5736 .ndo_do_ioctl = hdd_ioctl,
5737 .ndo_set_mac_address = hdd_set_mac_address,
5738 .ndo_select_queue = hdd_select_queue,
5739#ifdef WLAN_FEATURE_PACKET_FILTERING
5740#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5741 .ndo_set_rx_mode = hdd_set_multicast_list,
5742#else
5743 .ndo_set_multicast_list = hdd_set_multicast_list,
5744#endif //LINUX_VERSION_CODE
5745#endif
5746 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005747 static struct net_device_ops wlan_mon_drv_ops = {
5748 .ndo_open = hdd_mon_open,
5749 .ndo_stop = hdd_stop,
5750 .ndo_uninit = hdd_uninit,
5751 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5752 .ndo_tx_timeout = hdd_tx_timeout,
5753 .ndo_get_stats = hdd_stats,
5754 .ndo_do_ioctl = hdd_ioctl,
5755 .ndo_set_mac_address = hdd_set_mac_address,
5756 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005757
5758#endif
5759
5760void hdd_set_station_ops( struct net_device *pWlanDev )
5761{
5762#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 pWlanDev->netdev_ops = &wlan_drv_ops;
5764#else
5765 pWlanDev->open = hdd_open;
5766 pWlanDev->stop = hdd_stop;
5767 pWlanDev->uninit = hdd_uninit;
5768 pWlanDev->hard_start_xmit = NULL;
5769 pWlanDev->tx_timeout = hdd_tx_timeout;
5770 pWlanDev->get_stats = hdd_stats;
5771 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005772 pWlanDev->set_mac_address = hdd_set_mac_address;
5773#endif
5774}
5775
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005776static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005777{
5778 struct net_device *pWlanDev = NULL;
5779 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 /*
5781 * cfg80211 initialization and registration....
5782 */
5783 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5784
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 if(pWlanDev != NULL)
5786 {
5787
5788 //Save the pointer to the net_device in the HDD adapter
5789 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5790
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5792
5793 pAdapter->dev = pWlanDev;
5794 pAdapter->pHddCtx = pHddCtx;
5795 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305796 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005797
5798 init_completion(&pAdapter->session_open_comp_var);
5799 init_completion(&pAdapter->session_close_comp_var);
5800 init_completion(&pAdapter->disconnect_comp_var);
5801 init_completion(&pAdapter->linkup_event_var);
5802 init_completion(&pAdapter->cancel_rem_on_chan_var);
5803 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305804 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005805#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5806 init_completion(&pAdapter->offchannel_tx_event);
5807#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005809#ifdef FEATURE_WLAN_TDLS
5810 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005811 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005812 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305813 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005814#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005815 init_completion(&pHddCtx->mc_sus_event_var);
5816 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305817 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005818 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005819 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005820
Rajeev79dbe4c2013-10-05 11:03:42 +05305821#ifdef FEATURE_WLAN_BATCH_SCAN
5822 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5823 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5824 pAdapter->pBatchScanRsp = NULL;
5825 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005826 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005827 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305828 mutex_init(&pAdapter->hdd_batch_scan_lock);
5829#endif
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 pAdapter->isLinkUpSvcNeeded = FALSE;
5832 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5833 //Init the net_device structure
5834 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5835
5836 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5837 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5838 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5839 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5840
5841 hdd_set_station_ops( pAdapter->dev );
5842
5843 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5845 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5846 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 /* set pWlanDev's parent to underlying device */
5848 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005849
5850 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 }
5852
5853 return pAdapter;
5854}
5855
5856VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5857{
5858 struct net_device *pWlanDev = pAdapter->dev;
5859 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5860 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5861 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5862
5863 if( rtnl_lock_held )
5864 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005865 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5867 {
5868 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5869 return VOS_STATUS_E_FAILURE;
5870 }
5871 }
5872 if (register_netdevice(pWlanDev))
5873 {
5874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5875 return VOS_STATUS_E_FAILURE;
5876 }
5877 }
5878 else
5879 {
5880 if(register_netdev(pWlanDev))
5881 {
5882 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5883 return VOS_STATUS_E_FAILURE;
5884 }
5885 }
5886 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5887
5888 return VOS_STATUS_SUCCESS;
5889}
5890
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005891static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005892{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005893 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005894
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005895 if (NULL == pAdapter)
5896 {
5897 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5898 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005900
5901 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5902 {
5903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5904 return eHAL_STATUS_NOT_INITIALIZED;
5905 }
5906
5907 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5908
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005909#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005910 /* need to make sure all of our scheduled work has completed.
5911 * This callback is called from MC thread context, so it is safe to
5912 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005913 *
5914 * Even though this is called from MC thread context, if there is a faulty
5915 * work item in the system, that can hang this call forever. So flushing
5916 * this global work queue is not safe; and now we make sure that
5917 * individual work queues are stopped correctly. But the cancel work queue
5918 * is a GPL only API, so the proprietary version of the driver would still
5919 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005920 */
5921 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005922#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005923
5924 /* We can be blocked while waiting for scheduled work to be
5925 * flushed, and the adapter structure can potentially be freed, in
5926 * which case the magic will have been reset. So make sure the
5927 * magic is still good, and hence the adapter structure is still
5928 * valid, before signaling completion */
5929 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5930 {
5931 complete(&pAdapter->session_close_comp_var);
5932 }
5933
Jeff Johnson295189b2012-06-20 16:38:30 -07005934 return eHAL_STATUS_SUCCESS;
5935}
5936
5937VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5938{
5939 struct net_device *pWlanDev = pAdapter->dev;
5940 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5941 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5942 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5943 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305944 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005945
5946 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005947 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 //Open a SME session for future operation
5949 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005950 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005951 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5952 {
5953 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005954 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 halStatus, halStatus );
5956 status = VOS_STATUS_E_FAILURE;
5957 goto error_sme_open;
5958 }
5959
5960 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305961 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 &pAdapter->session_open_comp_var,
5963 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305964 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 {
5966 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305967 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005968 status = VOS_STATUS_E_FAILURE;
5969 goto error_sme_open;
5970 }
5971
5972 // Register wireless extensions
5973 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5974 {
5975 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005976 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005977 halStatus, halStatus );
5978 status = VOS_STATUS_E_FAILURE;
5979 goto error_register_wext;
5980 }
5981 //Safe to register the hard_start_xmit function again
5982#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5983 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5984#else
5985 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5986#endif
5987
5988 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305989 hddLog(VOS_TRACE_LEVEL_INFO,
5990 "%s: Set HDD connState to eConnectionState_NotConnected",
5991 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5993
5994 //Set the default operation channel
5995 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5996
5997 /* Make the default Auth Type as OPEN*/
5998 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5999
6000 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6001 {
6002 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006003 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 status, status );
6005 goto error_init_txrx;
6006 }
6007
6008 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6009
6010 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6011 {
6012 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006013 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 status, status );
6015 goto error_wmm_init;
6016 }
6017
6018 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6019
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006020#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306021 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006022 {
6023 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306024 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006025 goto error_tdls_init;
6026 }
6027 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6028#endif
6029
Jeff Johnson295189b2012-06-20 16:38:30 -07006030 return VOS_STATUS_SUCCESS;
6031
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006032#ifdef FEATURE_WLAN_TDLS
6033error_tdls_init:
6034 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6035 hdd_wmm_adapter_close(pAdapter);
6036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006037error_wmm_init:
6038 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6039 hdd_deinit_tx_rx(pAdapter);
6040error_init_txrx:
6041 hdd_UnregisterWext(pWlanDev);
6042error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006043 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 {
6045 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006046 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006048 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006049 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306050 unsigned long rc;
6051
Jeff Johnson295189b2012-06-20 16:38:30 -07006052 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306053 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006055 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306056 if (rc <= 0)
6057 hddLog(VOS_TRACE_LEVEL_ERROR,
6058 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 }
6060}
6061error_sme_open:
6062 return status;
6063}
6064
Jeff Johnson295189b2012-06-20 16:38:30 -07006065void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6066{
6067 hdd_cfg80211_state_t *cfgState;
6068
6069 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6070
6071 if( NULL != cfgState->buf )
6072 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306073 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006074 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6075 rc = wait_for_completion_interruptible_timeout(
6076 &pAdapter->tx_action_cnf_event,
6077 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306078 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006080 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306081 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6082 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006083 }
6084 }
6085 return;
6086}
Jeff Johnson295189b2012-06-20 16:38:30 -07006087
6088void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6089{
6090 ENTER();
6091 switch ( pAdapter->device_mode )
6092 {
6093 case WLAN_HDD_INFRA_STATION:
6094 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006095 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006096 {
6097 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6098 {
6099 hdd_deinit_tx_rx( pAdapter );
6100 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6101 }
6102
6103 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6104 {
6105 hdd_wmm_adapter_close( pAdapter );
6106 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6107 }
6108
Jeff Johnson295189b2012-06-20 16:38:30 -07006109 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006110#ifdef FEATURE_WLAN_TDLS
6111 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6112 {
6113 wlan_hdd_tdls_exit(pAdapter);
6114 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6115 }
6116#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006117
6118 break;
6119 }
6120
6121 case WLAN_HDD_SOFTAP:
6122 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306124
6125 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6126 {
6127 hdd_wmm_adapter_close( pAdapter );
6128 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6129 }
6130
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006132
6133 hdd_unregister_hostapd(pAdapter);
6134 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 break;
6137 }
6138
6139 case WLAN_HDD_MONITOR:
6140 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6143 {
6144 hdd_deinit_tx_rx( pAdapter );
6145 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6146 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006147 if(NULL != pAdapterforTx)
6148 {
6149 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 break;
6152 }
6153
6154
6155 default:
6156 break;
6157 }
6158
6159 EXIT();
6160}
6161
6162void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6163{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006164 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306165
6166 ENTER();
6167 if (NULL == pAdapter)
6168 {
6169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6170 "%s: HDD adapter is Null", __func__);
6171 return;
6172 }
6173
6174 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006175
Rajeev79dbe4c2013-10-05 11:03:42 +05306176#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306177 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6178 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006179 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306180 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6181 )
6182 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006183 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306184 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006185 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6186 {
6187 hdd_deinit_batch_scan(pAdapter);
6188 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306189 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006190 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306191#endif
6192
Jeff Johnson295189b2012-06-20 16:38:30 -07006193 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6194 if( rtnl_held )
6195 {
6196 unregister_netdevice(pWlanDev);
6197 }
6198 else
6199 {
6200 unregister_netdev(pWlanDev);
6201 }
6202 // note that the pAdapter is no longer valid at this point
6203 // since the memory has been reclaimed
6204 }
6205
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306206 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006207}
6208
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006209void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6210{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306211 VOS_STATUS status;
6212 hdd_adapter_t *pAdapter = NULL;
6213 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006214
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306215 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006216
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306217 /*loop through all adapters.*/
6218 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006219 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306220 pAdapter = pAdapterNode->pAdapter;
6221 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6222 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006223
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306224 { // we skip this registration for modes other than STA and P2P client modes.
6225 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6226 pAdapterNode = pNext;
6227 continue;
6228 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006229
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306230 //Apply Dynamic DTIM For P2P
6231 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6232 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6233 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6234 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6235 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6236 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6237 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6238 (eConnectionState_Associated ==
6239 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6240 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6241 {
6242 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006243
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306244 powerRequest.uIgnoreDTIM = 1;
6245 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6246
6247 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6248 {
6249 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6250 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6251 }
6252 else
6253 {
6254 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6255 }
6256
6257 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6258 * specified during Enter/Exit BMPS when LCD off*/
6259 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6260 NULL, eANI_BOOLEAN_FALSE);
6261 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6262 NULL, eANI_BOOLEAN_FALSE);
6263
6264 /* switch to the DTIM specified in cfg.ini */
6265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6266 "Switch to DTIM %d", powerRequest.uListenInterval);
6267 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6268 break;
6269
6270 }
6271
6272 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6273 pAdapterNode = pNext;
6274 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006275}
6276
6277void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6278{
6279 /*Switch back to DTIM 1*/
6280 tSirSetPowerParamsReq powerRequest = { 0 };
6281
6282 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6283 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006284 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006285
6286 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6287 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6288 NULL, eANI_BOOLEAN_FALSE);
6289 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6290 NULL, eANI_BOOLEAN_FALSE);
6291
6292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6293 "Switch to DTIM%d",powerRequest.uListenInterval);
6294 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6295
6296}
6297
Jeff Johnson295189b2012-06-20 16:38:30 -07006298VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6299{
6300 VOS_STATUS status = VOS_STATUS_SUCCESS;
6301
6302 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6303 {
6304 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6305 }
6306
6307 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6308 {
6309 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6310 }
6311
6312 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6313 {
6314 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6315 }
6316
6317 return status;
6318}
6319
6320VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6321{
6322 hdd_adapter_t *pAdapter = NULL;
6323 eHalStatus halStatus;
6324 VOS_STATUS status = VOS_STATUS_E_INVAL;
6325 v_BOOL_t disableBmps = FALSE;
6326 v_BOOL_t disableImps = FALSE;
6327
6328 switch(session_type)
6329 {
6330 case WLAN_HDD_INFRA_STATION:
6331 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 case WLAN_HDD_P2P_CLIENT:
6333 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006334 //Exit BMPS -> Is Sta/P2P Client is already connected
6335 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6336 if((NULL != pAdapter)&&
6337 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6338 {
6339 disableBmps = TRUE;
6340 }
6341
6342 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6343 if((NULL != pAdapter)&&
6344 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6345 {
6346 disableBmps = TRUE;
6347 }
6348
6349 //Exit both Bmps and Imps incase of Go/SAP Mode
6350 if((WLAN_HDD_SOFTAP == session_type) ||
6351 (WLAN_HDD_P2P_GO == session_type))
6352 {
6353 disableBmps = TRUE;
6354 disableImps = TRUE;
6355 }
6356
6357 if(TRUE == disableImps)
6358 {
6359 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6360 {
6361 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6362 }
6363 }
6364
6365 if(TRUE == disableBmps)
6366 {
6367 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6368 {
6369 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6370
6371 if(eHAL_STATUS_SUCCESS != halStatus)
6372 {
6373 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006374 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006375 VOS_ASSERT(0);
6376 return status;
6377 }
6378 }
6379
6380 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6381 {
6382 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6383
6384 if(eHAL_STATUS_SUCCESS != halStatus)
6385 {
6386 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006387 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 VOS_ASSERT(0);
6389 return status;
6390 }
6391 }
6392 }
6393
6394 if((TRUE == disableBmps) ||
6395 (TRUE == disableImps))
6396 {
6397 /* Now, get the chip into Full Power now */
6398 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6399 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6400 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6401
6402 if(halStatus != eHAL_STATUS_SUCCESS)
6403 {
6404 if(halStatus == eHAL_STATUS_PMC_PENDING)
6405 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306406 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006407 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306408 ret = wait_for_completion_interruptible_timeout(
6409 &pHddCtx->full_pwr_comp_var,
6410 msecs_to_jiffies(1000));
6411 if (ret <= 0)
6412 {
6413 hddLog(VOS_TRACE_LEVEL_ERROR,
6414 "%s: wait on full_pwr_comp_var failed %ld",
6415 __func__, ret);
6416 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 }
6418 else
6419 {
6420 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006421 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006422 VOS_ASSERT(0);
6423 return status;
6424 }
6425 }
6426
6427 status = VOS_STATUS_SUCCESS;
6428 }
6429
6430 break;
6431 }
6432 return status;
6433}
6434
6435hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006436 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006437 tANI_U8 rtnl_held )
6438{
6439 hdd_adapter_t *pAdapter = NULL;
6440 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6441 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6442 VOS_STATUS exitbmpsStatus;
6443
Arif Hussain6d2a3322013-11-17 19:50:10 -08006444 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006445
Nirav Shah436658f2014-02-28 17:05:45 +05306446 if(macAddr == NULL)
6447 {
6448 /* Not received valid macAddr */
6449 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6450 "%s:Unable to add virtual intf: Not able to get"
6451 "valid mac address",__func__);
6452 return NULL;
6453 }
6454
Jeff Johnson295189b2012-06-20 16:38:30 -07006455 //Disable BMPS incase of Concurrency
6456 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6457
6458 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6459 {
6460 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306461 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006462 VOS_ASSERT(0);
6463 return NULL;
6464 }
6465
6466 switch(session_type)
6467 {
6468 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006469 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006470 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006471 {
6472 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6473
6474 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306475 {
6476 hddLog(VOS_TRACE_LEVEL_FATAL,
6477 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006480
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306481#ifdef FEATURE_WLAN_TDLS
6482 /* A Mutex Lock is introduced while changing/initializing the mode to
6483 * protect the concurrent access for the Adapters by TDLS module.
6484 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306485 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306486#endif
6487
Jeff Johnsone7245742012-09-05 17:12:55 -07006488 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6489 NL80211_IFTYPE_P2P_CLIENT:
6490 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006491
Jeff Johnson295189b2012-06-20 16:38:30 -07006492 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306493#ifdef FEATURE_WLAN_TDLS
6494 mutex_unlock(&pHddCtx->tdls_lock);
6495#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306496
6497 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 if( VOS_STATUS_SUCCESS != status )
6499 goto err_free_netdev;
6500
6501 status = hdd_register_interface( pAdapter, rtnl_held );
6502 if( VOS_STATUS_SUCCESS != status )
6503 {
6504 hdd_deinit_adapter(pHddCtx, pAdapter);
6505 goto err_free_netdev;
6506 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306507
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306508 // Workqueue which gets scheduled in IPv4 notification callback.
6509 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6510
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306511#ifdef WLAN_NS_OFFLOAD
6512 // Workqueue which gets scheduled in IPv6 notification callback.
6513 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6514#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006515 //Stop the Interface TX queue.
6516 netif_tx_disable(pAdapter->dev);
6517 //netif_tx_disable(pWlanDev);
6518 netif_carrier_off(pAdapter->dev);
6519
6520 break;
6521 }
6522
Jeff Johnson295189b2012-06-20 16:38:30 -07006523 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006524 case WLAN_HDD_SOFTAP:
6525 {
6526 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6527 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306528 {
6529 hddLog(VOS_TRACE_LEVEL_FATAL,
6530 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006531 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306532 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006533
Jeff Johnson295189b2012-06-20 16:38:30 -07006534 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6535 NL80211_IFTYPE_AP:
6536 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006537 pAdapter->device_mode = session_type;
6538
6539 status = hdd_init_ap_mode(pAdapter);
6540 if( VOS_STATUS_SUCCESS != status )
6541 goto err_free_netdev;
6542
6543 status = hdd_register_hostapd( pAdapter, rtnl_held );
6544 if( VOS_STATUS_SUCCESS != status )
6545 {
6546 hdd_deinit_adapter(pHddCtx, pAdapter);
6547 goto err_free_netdev;
6548 }
6549
6550 netif_tx_disable(pAdapter->dev);
6551 netif_carrier_off(pAdapter->dev);
6552
6553 hdd_set_conparam( 1 );
6554 break;
6555 }
6556 case WLAN_HDD_MONITOR:
6557 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006558 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6559 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306560 {
6561 hddLog(VOS_TRACE_LEVEL_FATAL,
6562 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006563 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306564 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006565
6566 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6567 pAdapter->device_mode = session_type;
6568 status = hdd_register_interface( pAdapter, rtnl_held );
6569#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6570 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6571#else
6572 pAdapter->dev->open = hdd_mon_open;
6573 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6574#endif
6575 hdd_init_tx_rx( pAdapter );
6576 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6577 //Set adapter to be used for data tx. It will use either GO or softap.
6578 pAdapter->sessionCtx.monitor.pAdapterForTx =
6579 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006580 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6581 {
6582 pAdapter->sessionCtx.monitor.pAdapterForTx =
6583 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6584 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006585 /* This workqueue will be used to transmit management packet over
6586 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006587 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6588 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6589 return NULL;
6590 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006591
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6593 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006594 }
6595 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006596 case WLAN_HDD_FTM:
6597 {
6598 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6599
6600 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306601 {
6602 hddLog(VOS_TRACE_LEVEL_FATAL,
6603 FL("failed to allocate adapter for session %d"), session_type);
6604 return NULL;
6605 }
6606
Jeff Johnson295189b2012-06-20 16:38:30 -07006607 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6608 * message while loading driver in FTM mode. */
6609 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6610 pAdapter->device_mode = session_type;
6611 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306612
6613 hdd_init_tx_rx( pAdapter );
6614
6615 //Stop the Interface TX queue.
6616 netif_tx_disable(pAdapter->dev);
6617 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 }
6619 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006620 default:
6621 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306622 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6623 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006624 VOS_ASSERT(0);
6625 return NULL;
6626 }
6627 }
6628
Jeff Johnson295189b2012-06-20 16:38:30 -07006629 if( VOS_STATUS_SUCCESS == status )
6630 {
6631 //Add it to the hdd's session list.
6632 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6633 if( NULL == pHddAdapterNode )
6634 {
6635 status = VOS_STATUS_E_NOMEM;
6636 }
6637 else
6638 {
6639 pHddAdapterNode->pAdapter = pAdapter;
6640 status = hdd_add_adapter_back ( pHddCtx,
6641 pHddAdapterNode );
6642 }
6643 }
6644
6645 if( VOS_STATUS_SUCCESS != status )
6646 {
6647 if( NULL != pAdapter )
6648 {
6649 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6650 pAdapter = NULL;
6651 }
6652 if( NULL != pHddAdapterNode )
6653 {
6654 vos_mem_free( pHddAdapterNode );
6655 }
6656
6657 goto resume_bmps;
6658 }
6659
6660 if(VOS_STATUS_SUCCESS == status)
6661 {
6662 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6663
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006664 //Initialize the WoWL service
6665 if(!hdd_init_wowl(pAdapter))
6666 {
6667 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6668 goto err_free_netdev;
6669 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006670 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006671 return pAdapter;
6672
6673err_free_netdev:
6674 free_netdev(pAdapter->dev);
6675 wlan_hdd_release_intf_addr( pHddCtx,
6676 pAdapter->macAddressCurrent.bytes );
6677
6678resume_bmps:
6679 //If bmps disabled enable it
6680 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6681 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306682 if (pHddCtx->hdd_wlan_suspended)
6683 {
6684 hdd_set_pwrparams(pHddCtx);
6685 }
6686 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006687 }
6688 return NULL;
6689}
6690
6691VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6692 tANI_U8 rtnl_held )
6693{
6694 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6695 VOS_STATUS status;
6696
6697 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6698 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306699 {
6700 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6701 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006702 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306703 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006704
6705 while ( pCurrent->pAdapter != pAdapter )
6706 {
6707 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6708 if( VOS_STATUS_SUCCESS != status )
6709 break;
6710
6711 pCurrent = pNext;
6712 }
6713 pAdapterNode = pCurrent;
6714 if( VOS_STATUS_SUCCESS == status )
6715 {
6716 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6717 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306718
6719#ifdef FEATURE_WLAN_TDLS
6720
6721 /* A Mutex Lock is introduced while changing/initializing the mode to
6722 * protect the concurrent access for the Adapters by TDLS module.
6723 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306724 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306725#endif
6726
Jeff Johnson295189b2012-06-20 16:38:30 -07006727 hdd_remove_adapter( pHddCtx, pAdapterNode );
6728 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006729 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006730
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306731#ifdef FEATURE_WLAN_TDLS
6732 mutex_unlock(&pHddCtx->tdls_lock);
6733#endif
6734
Jeff Johnson295189b2012-06-20 16:38:30 -07006735
6736 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306737 if ((!vos_concurrent_open_sessions_running()) &&
6738 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6739 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006740 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306741 if (pHddCtx->hdd_wlan_suspended)
6742 {
6743 hdd_set_pwrparams(pHddCtx);
6744 }
6745 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006746 }
6747
6748 return VOS_STATUS_SUCCESS;
6749 }
6750
6751 return VOS_STATUS_E_FAILURE;
6752}
6753
6754VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6755{
6756 hdd_adapter_list_node_t *pHddAdapterNode;
6757 VOS_STATUS status;
6758
6759 ENTER();
6760
6761 do
6762 {
6763 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6764 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6765 {
6766 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6767 vos_mem_free( pHddAdapterNode );
6768 }
6769 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6770
6771 EXIT();
6772
6773 return VOS_STATUS_SUCCESS;
6774}
6775
6776void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6777{
6778 v_U8_t addIE[1] = {0};
6779
6780 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6781 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6782 eANI_BOOLEAN_FALSE) )
6783 {
6784 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006785 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006786 }
6787
6788 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6789 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6790 eANI_BOOLEAN_FALSE) )
6791 {
6792 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006793 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006794 }
6795
6796 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6797 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6798 eANI_BOOLEAN_FALSE) )
6799 {
6800 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006801 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 }
6803}
6804
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306805VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6806 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006807{
6808 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6809 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6810 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306811 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306812 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006813
6814 ENTER();
6815
6816 switch(pAdapter->device_mode)
6817 {
6818 case WLAN_HDD_INFRA_STATION:
6819 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006820 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306821 {
6822 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6823 if( hdd_connIsConnected(pstation) ||
6824 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006825 {
6826 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6827 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6828 pAdapter->sessionId,
6829 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6830 else
6831 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6832 pAdapter->sessionId,
6833 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6834 //success implies disconnect command got queued up successfully
6835 if(halStatus == eHAL_STATUS_SUCCESS)
6836 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306837 ret = wait_for_completion_interruptible_timeout(
6838 &pAdapter->disconnect_comp_var,
6839 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6840 if (ret <= 0)
6841 {
6842 hddLog(VOS_TRACE_LEVEL_ERROR,
6843 "%s: wait on disconnect_comp_var failed %ld",
6844 __func__, ret);
6845 }
6846 }
6847 else
6848 {
6849 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6850 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006851 }
6852 memset(&wrqu, '\0', sizeof(wrqu));
6853 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6854 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6855 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6856 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306857 else if(pstation->conn_info.connState ==
6858 eConnectionState_Disconnecting)
6859 {
6860 ret = wait_for_completion_interruptible_timeout(
6861 &pAdapter->disconnect_comp_var,
6862 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6863 if (ret <= 0)
6864 {
6865 hddLog(VOS_TRACE_LEVEL_ERROR,
6866 FL("wait on disconnect_comp_var failed %ld"), ret);
6867 }
6868 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006869 else
6870 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306871 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6872 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006873 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306874 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6875 {
6876 while (pAdapter->is_roc_inprogress)
6877 {
6878 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6879 "%s: ROC in progress for session %d!!!",
6880 __func__, pAdapter->sessionId);
6881 // waiting for ROC to expire
6882 msleep(500);
6883 /* In GO present case , if retry exceeds 3,
6884 it means something went wrong. */
6885 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6886 {
6887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6888 "%s: ROC completion is not received.!!!", __func__);
6889 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6890 pAdapter->sessionId);
6891 wait_for_completion_interruptible_timeout(
6892 &pAdapter->cancel_rem_on_chan_var,
6893 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6894 break;
6895 }
6896 }
6897 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306898#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306899#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306900 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6901#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306902 if (pAdapter->ipv6_notifier_registered)
6903 {
6904 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6905 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6906 pAdapter->ipv6_notifier_registered = false;
6907 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306908#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306909 if (pAdapter->ipv4_notifier_registered)
6910 {
6911 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6912 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6913 pAdapter->ipv4_notifier_registered = false;
6914 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306915#ifdef WLAN_OPEN_SOURCE
6916 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6917#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306918 /* It is possible that the caller of this function does not
6919 * wish to close the session
6920 */
6921 if (VOS_TRUE == bCloseSession &&
6922 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006923 {
6924 INIT_COMPLETION(pAdapter->session_close_comp_var);
6925 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306926 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6927 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006928 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306929 unsigned long ret;
6930
Jeff Johnson295189b2012-06-20 16:38:30 -07006931 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306932 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306933 &pAdapter->session_close_comp_var,
6934 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306935 if ( 0 >= ret)
6936 {
6937 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306938 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006940 }
6941 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006943 break;
6944
6945 case WLAN_HDD_SOFTAP:
6946 case WLAN_HDD_P2P_GO:
6947 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306948 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6949 while (pAdapter->is_roc_inprogress) {
6950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6951 "%s: ROC in progress for session %d!!!",
6952 __func__, pAdapter->sessionId);
6953 msleep(500);
6954 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6956 "%s: ROC completion is not received.!!!", __func__);
6957 WLANSAP_CancelRemainOnChannel(
6958 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6959 wait_for_completion_interruptible_timeout(
6960 &pAdapter->cancel_rem_on_chan_var,
6961 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6962 break;
6963 }
6964 }
6965 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 mutex_lock(&pHddCtx->sap_lock);
6967 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6968 {
6969 VOS_STATUS status;
6970 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6971
6972 //Stop Bss.
6973 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6974 if (VOS_IS_STATUS_SUCCESS(status))
6975 {
6976 hdd_hostapd_state_t *pHostapdState =
6977 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6978
6979 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6980
6981 if (!VOS_IS_STATUS_SUCCESS(status))
6982 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306983 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6984 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006985 }
6986 }
6987 else
6988 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006989 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 }
6991 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306992 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006993
6994 if (eHAL_STATUS_FAILURE ==
6995 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6996 0, NULL, eANI_BOOLEAN_FALSE))
6997 {
6998 hddLog(LOGE,
6999 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007000 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007001 }
7002
7003 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7004 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7005 eANI_BOOLEAN_FALSE) )
7006 {
7007 hddLog(LOGE,
7008 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7009 }
7010
7011 // Reset WNI_CFG_PROBE_RSP Flags
7012 wlan_hdd_reset_prob_rspies(pAdapter);
7013 kfree(pAdapter->sessionCtx.ap.beacon);
7014 pAdapter->sessionCtx.ap.beacon = NULL;
7015 }
7016 mutex_unlock(&pHddCtx->sap_lock);
7017 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007018
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007020#ifdef WLAN_OPEN_SOURCE
7021 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7022#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007023 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007024
Jeff Johnson295189b2012-06-20 16:38:30 -07007025 default:
7026 break;
7027 }
7028
7029 EXIT();
7030 return VOS_STATUS_SUCCESS;
7031}
7032
7033VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7034{
7035 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7036 VOS_STATUS status;
7037 hdd_adapter_t *pAdapter;
7038
7039 ENTER();
7040
7041 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7042
7043 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7044 {
7045 pAdapter = pAdapterNode->pAdapter;
7046 netif_tx_disable(pAdapter->dev);
7047 netif_carrier_off(pAdapter->dev);
7048
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307049 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007050
7051 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7052 pAdapterNode = pNext;
7053 }
7054
7055 EXIT();
7056
7057 return VOS_STATUS_SUCCESS;
7058}
7059
Rajeev Kumarf999e582014-01-09 17:33:29 -08007060
7061#ifdef FEATURE_WLAN_BATCH_SCAN
7062/**---------------------------------------------------------------------------
7063
7064 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7065 structures
7066
7067 \param - pAdapter Pointer to HDD adapter
7068
7069 \return - None
7070
7071 --------------------------------------------------------------------------*/
7072void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7073{
7074 tHddBatchScanRsp *pNode;
7075 tHddBatchScanRsp *pPrev;
7076
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307077 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007078 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307079 hddLog(VOS_TRACE_LEVEL_ERROR,
7080 "%s: Adapter context is Null", __func__);
7081 return;
7082 }
7083
7084 pNode = pAdapter->pBatchScanRsp;
7085 while (pNode)
7086 {
7087 pPrev = pNode;
7088 pNode = pNode->pNext;
7089 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007090 }
7091
7092 pAdapter->pBatchScanRsp = NULL;
7093 pAdapter->numScanList = 0;
7094 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7095 pAdapter->prev_batch_id = 0;
7096
7097 return;
7098}
7099#endif
7100
7101
Jeff Johnson295189b2012-06-20 16:38:30 -07007102VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7103{
7104 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7105 VOS_STATUS status;
7106 hdd_adapter_t *pAdapter;
7107
7108 ENTER();
7109
7110 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7111
7112 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7113 {
7114 pAdapter = pAdapterNode->pAdapter;
7115 netif_tx_disable(pAdapter->dev);
7116 netif_carrier_off(pAdapter->dev);
7117
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007118 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7119
Jeff Johnson295189b2012-06-20 16:38:30 -07007120 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307121
7122 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7123
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307124 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7125 {
7126 hdd_wmm_adapter_close( pAdapter );
7127 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7128 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007129
Rajeev Kumarf999e582014-01-09 17:33:29 -08007130#ifdef FEATURE_WLAN_BATCH_SCAN
7131 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7132 {
7133 hdd_deinit_batch_scan(pAdapter);
7134 }
7135#endif
7136
Jeff Johnson295189b2012-06-20 16:38:30 -07007137 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7138 pAdapterNode = pNext;
7139 }
7140
7141 EXIT();
7142
7143 return VOS_STATUS_SUCCESS;
7144}
7145
7146VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7147{
7148 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7149 VOS_STATUS status;
7150 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307151 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007152
7153 ENTER();
7154
7155 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7156
7157 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7158 {
7159 pAdapter = pAdapterNode->pAdapter;
7160
Kumar Anand82c009f2014-05-29 00:29:42 -07007161 hdd_wmm_init( pAdapter );
7162
Jeff Johnson295189b2012-06-20 16:38:30 -07007163 switch(pAdapter->device_mode)
7164 {
7165 case WLAN_HDD_INFRA_STATION:
7166 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007167 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307168
7169 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7170
Jeff Johnson295189b2012-06-20 16:38:30 -07007171 hdd_init_station_mode(pAdapter);
7172 /* Open the gates for HDD to receive Wext commands */
7173 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007174 pHddCtx->scan_info.mScanPending = FALSE;
7175 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007176
7177 //Trigger the initial scan
7178 hdd_wlan_initial_scan(pAdapter);
7179
7180 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307181 if (eConnectionState_Associated == connState ||
7182 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007183 {
7184 union iwreq_data wrqu;
7185 memset(&wrqu, '\0', sizeof(wrqu));
7186 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7187 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7188 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007189 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007190
Jeff Johnson295189b2012-06-20 16:38:30 -07007191 /* indicate disconnected event to nl80211 */
7192 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7193 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307195 else if (eConnectionState_Connecting == connState)
7196 {
7197 /*
7198 * Indicate connect failure to supplicant if we were in the
7199 * process of connecting
7200 */
7201 cfg80211_connect_result(pAdapter->dev, NULL,
7202 NULL, 0, NULL, 0,
7203 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7204 GFP_KERNEL);
7205 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 break;
7207
7208 case WLAN_HDD_SOFTAP:
7209 /* softAP can handle SSR */
7210 break;
7211
7212 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007213 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007214 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007215 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007216 break;
7217
7218 case WLAN_HDD_MONITOR:
7219 /* monitor interface start */
7220 break;
7221 default:
7222 break;
7223 }
7224
7225 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7226 pAdapterNode = pNext;
7227 }
7228
7229 EXIT();
7230
7231 return VOS_STATUS_SUCCESS;
7232}
7233
7234VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7235{
7236 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7237 hdd_adapter_t *pAdapter;
7238 VOS_STATUS status;
7239 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307240 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007241
7242 ENTER();
7243
7244 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7245
7246 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7247 {
7248 pAdapter = pAdapterNode->pAdapter;
7249
7250 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7251 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7252 {
7253 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7254 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7255
Abhishek Singhf4669da2014-05-26 15:07:49 +05307256 hddLog(VOS_TRACE_LEVEL_INFO,
7257 "%s: Set HDD connState to eConnectionState_NotConnected",
7258 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007259 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7260 init_completion(&pAdapter->disconnect_comp_var);
7261 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7262 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7263
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307264 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007265 &pAdapter->disconnect_comp_var,
7266 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307267 if (0 >= ret)
7268 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7269 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007270
7271 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7272 pHddCtx->isAmpAllowed = VOS_FALSE;
7273 sme_RoamConnect(pHddCtx->hHal,
7274 pAdapter->sessionId, &(pWextState->roamProfile),
7275 &roamId);
7276 }
7277
7278 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7279 pAdapterNode = pNext;
7280 }
7281
7282 EXIT();
7283
7284 return VOS_STATUS_SUCCESS;
7285}
7286
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007287void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7288{
7289 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7290 VOS_STATUS status;
7291 hdd_adapter_t *pAdapter;
7292 hdd_station_ctx_t *pHddStaCtx;
7293 hdd_ap_ctx_t *pHddApCtx;
7294 hdd_hostapd_state_t * pHostapdState;
7295 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7296 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7297 const char *p2pMode = "DEV";
7298 const char *ccMode = "Standalone";
7299 int n;
7300
7301 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7302 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7303 {
7304 pAdapter = pAdapterNode->pAdapter;
7305 switch (pAdapter->device_mode) {
7306 case WLAN_HDD_INFRA_STATION:
7307 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7308 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7309 staChannel = pHddStaCtx->conn_info.operationChannel;
7310 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7311 }
7312 break;
7313 case WLAN_HDD_P2P_CLIENT:
7314 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7315 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7316 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7317 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7318 p2pMode = "CLI";
7319 }
7320 break;
7321 case WLAN_HDD_P2P_GO:
7322 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7323 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7324 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7325 p2pChannel = pHddApCtx->operatingChannel;
7326 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7327 }
7328 p2pMode = "GO";
7329 break;
7330 case WLAN_HDD_SOFTAP:
7331 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7332 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7333 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7334 apChannel = pHddApCtx->operatingChannel;
7335 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7336 }
7337 break;
7338 default:
7339 break;
7340 }
7341 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7342 pAdapterNode = pNext;
7343 }
7344 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7345 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7346 }
7347 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7348 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7349 if (p2pChannel > 0) {
7350 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7351 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7352 }
7353 if (apChannel > 0) {
7354 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7355 apChannel, MAC_ADDR_ARRAY(apBssid));
7356 }
7357
7358 if (p2pChannel > 0 && apChannel > 0) {
7359 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7360 }
7361}
7362
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007363bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007364{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007365 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007366}
7367
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007368/* Once SSR is disabled then it cannot be set. */
7369void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007370{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007371 if (HDD_SSR_DISABLED == isSsrRequired)
7372 return;
7373
Jeff Johnson295189b2012-06-20 16:38:30 -07007374 isSsrRequired = value;
7375}
7376
7377VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7378 hdd_adapter_list_node_t** ppAdapterNode)
7379{
7380 VOS_STATUS status;
7381 spin_lock(&pHddCtx->hddAdapters.lock);
7382 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7383 (hdd_list_node_t**) ppAdapterNode );
7384 spin_unlock(&pHddCtx->hddAdapters.lock);
7385 return status;
7386}
7387
7388VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7389 hdd_adapter_list_node_t* pAdapterNode,
7390 hdd_adapter_list_node_t** pNextAdapterNode)
7391{
7392 VOS_STATUS status;
7393 spin_lock(&pHddCtx->hddAdapters.lock);
7394 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7395 (hdd_list_node_t*) pAdapterNode,
7396 (hdd_list_node_t**)pNextAdapterNode );
7397
7398 spin_unlock(&pHddCtx->hddAdapters.lock);
7399 return status;
7400}
7401
7402VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7403 hdd_adapter_list_node_t* pAdapterNode)
7404{
7405 VOS_STATUS status;
7406 spin_lock(&pHddCtx->hddAdapters.lock);
7407 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7408 &pAdapterNode->node );
7409 spin_unlock(&pHddCtx->hddAdapters.lock);
7410 return status;
7411}
7412
7413VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7414 hdd_adapter_list_node_t** ppAdapterNode)
7415{
7416 VOS_STATUS status;
7417 spin_lock(&pHddCtx->hddAdapters.lock);
7418 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7419 (hdd_list_node_t**) ppAdapterNode );
7420 spin_unlock(&pHddCtx->hddAdapters.lock);
7421 return status;
7422}
7423
7424VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7425 hdd_adapter_list_node_t* pAdapterNode)
7426{
7427 VOS_STATUS status;
7428 spin_lock(&pHddCtx->hddAdapters.lock);
7429 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7430 (hdd_list_node_t*) pAdapterNode );
7431 spin_unlock(&pHddCtx->hddAdapters.lock);
7432 return status;
7433}
7434
7435VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7436 hdd_adapter_list_node_t* pAdapterNode)
7437{
7438 VOS_STATUS status;
7439 spin_lock(&pHddCtx->hddAdapters.lock);
7440 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7441 (hdd_list_node_t*) pAdapterNode );
7442 spin_unlock(&pHddCtx->hddAdapters.lock);
7443 return status;
7444}
7445
7446hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7447 tSirMacAddr macAddr )
7448{
7449 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7450 hdd_adapter_t *pAdapter;
7451 VOS_STATUS status;
7452
7453 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7454
7455 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7456 {
7457 pAdapter = pAdapterNode->pAdapter;
7458
7459 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7460 macAddr, sizeof(tSirMacAddr) ) )
7461 {
7462 return pAdapter;
7463 }
7464 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7465 pAdapterNode = pNext;
7466 }
7467
7468 return NULL;
7469
7470}
7471
7472hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7473{
7474 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7475 hdd_adapter_t *pAdapter;
7476 VOS_STATUS status;
7477
7478 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7479
7480 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7481 {
7482 pAdapter = pAdapterNode->pAdapter;
7483
7484 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7485 IFNAMSIZ ) )
7486 {
7487 return pAdapter;
7488 }
7489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7490 pAdapterNode = pNext;
7491 }
7492
7493 return NULL;
7494
7495}
7496
7497hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7498{
7499 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7500 hdd_adapter_t *pAdapter;
7501 VOS_STATUS status;
7502
7503 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7504
7505 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7506 {
7507 pAdapter = pAdapterNode->pAdapter;
7508
7509 if( pAdapter && (mode == pAdapter->device_mode) )
7510 {
7511 return pAdapter;
7512 }
7513 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7514 pAdapterNode = pNext;
7515 }
7516
7517 return NULL;
7518
7519}
7520
7521//Remove this function later
7522hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7523{
7524 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7525 hdd_adapter_t *pAdapter;
7526 VOS_STATUS status;
7527
7528 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7529
7530 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7531 {
7532 pAdapter = pAdapterNode->pAdapter;
7533
7534 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7535 {
7536 return pAdapter;
7537 }
7538
7539 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7540 pAdapterNode = pNext;
7541 }
7542
7543 return NULL;
7544
7545}
7546
Jeff Johnson295189b2012-06-20 16:38:30 -07007547/**---------------------------------------------------------------------------
7548
7549 \brief hdd_set_monitor_tx_adapter() -
7550
7551 This API initializes the adapter to be used while transmitting on monitor
7552 adapter.
7553
7554 \param - pHddCtx - Pointer to the HDD context.
7555 pAdapter - Adapter that will used for TX. This can be NULL.
7556 \return - None.
7557 --------------------------------------------------------------------------*/
7558void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7559{
7560 hdd_adapter_t *pMonAdapter;
7561
7562 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7563
7564 if( NULL != pMonAdapter )
7565 {
7566 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7567 }
7568}
Jeff Johnson295189b2012-06-20 16:38:30 -07007569/**---------------------------------------------------------------------------
7570
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307571 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007572
7573 This API returns the operating channel of the requested device mode
7574
7575 \param - pHddCtx - Pointer to the HDD context.
7576 - mode - Device mode for which operating channel is required
7577 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7578 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7579 \return - channel number. "0" id the requested device is not found OR it is not connected.
7580 --------------------------------------------------------------------------*/
7581v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7582{
7583 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7584 VOS_STATUS status;
7585 hdd_adapter_t *pAdapter;
7586 v_U8_t operatingChannel = 0;
7587
7588 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7589
7590 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7591 {
7592 pAdapter = pAdapterNode->pAdapter;
7593
7594 if( mode == pAdapter->device_mode )
7595 {
7596 switch(pAdapter->device_mode)
7597 {
7598 case WLAN_HDD_INFRA_STATION:
7599 case WLAN_HDD_P2P_CLIENT:
7600 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7601 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7602 break;
7603 case WLAN_HDD_SOFTAP:
7604 case WLAN_HDD_P2P_GO:
7605 /*softap connection info */
7606 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7607 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7608 break;
7609 default:
7610 break;
7611 }
7612
7613 break; //Found the device of interest. break the loop
7614 }
7615
7616 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7617 pAdapterNode = pNext;
7618 }
7619 return operatingChannel;
7620}
7621
7622#ifdef WLAN_FEATURE_PACKET_FILTERING
7623/**---------------------------------------------------------------------------
7624
7625 \brief hdd_set_multicast_list() -
7626
7627 This used to set the multicast address list.
7628
7629 \param - dev - Pointer to the WLAN device.
7630 - skb - Pointer to OS packet (sk_buff).
7631 \return - success/fail
7632
7633 --------------------------------------------------------------------------*/
7634static void hdd_set_multicast_list(struct net_device *dev)
7635{
7636 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007637 int mc_count;
7638 int i = 0;
7639 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307640
7641 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007642 {
7643 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307644 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007645 return;
7646 }
7647
7648 if (dev->flags & IFF_ALLMULTI)
7649 {
7650 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007651 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307652 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007653 }
7654 else
7655 {
7656 mc_count = netdev_mc_count(dev);
7657 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007658 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007659 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7660 {
7661 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007662 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307663 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007664 return;
7665 }
7666
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307667 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007668
7669 netdev_for_each_mc_addr(ha, dev) {
7670 if (i == mc_count)
7671 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307672 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7673 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007674 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007675 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307676 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007677 i++;
7678 }
7679 }
7680 return;
7681}
7682#endif
7683
7684/**---------------------------------------------------------------------------
7685
7686 \brief hdd_select_queue() -
7687
7688 This function is registered with the Linux OS for network
7689 core to decide which queue to use first.
7690
7691 \param - dev - Pointer to the WLAN device.
7692 - skb - Pointer to OS packet (sk_buff).
7693 \return - ac, Queue Index/access category corresponding to UP in IP header
7694
7695 --------------------------------------------------------------------------*/
7696v_U16_t hdd_select_queue(struct net_device *dev,
7697 struct sk_buff *skb)
7698{
7699 return hdd_wmm_select_queue(dev, skb);
7700}
7701
7702
7703/**---------------------------------------------------------------------------
7704
7705 \brief hdd_wlan_initial_scan() -
7706
7707 This function triggers the initial scan
7708
7709 \param - pAdapter - Pointer to the HDD adapter.
7710
7711 --------------------------------------------------------------------------*/
7712void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7713{
7714 tCsrScanRequest scanReq;
7715 tCsrChannelInfo channelInfo;
7716 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007717 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007718 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7719
7720 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7721 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7722 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7723
7724 if(sme_Is11dSupported(pHddCtx->hHal))
7725 {
7726 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7727 if ( HAL_STATUS_SUCCESS( halStatus ) )
7728 {
7729 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7730 if( !scanReq.ChannelInfo.ChannelList )
7731 {
7732 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7733 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007734 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 return;
7736 }
7737 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7738 channelInfo.numOfChannels);
7739 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7740 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007741 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 }
7743
7744 scanReq.scanType = eSIR_PASSIVE_SCAN;
7745 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7746 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7747 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7748 }
7749 else
7750 {
7751 scanReq.scanType = eSIR_ACTIVE_SCAN;
7752 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7753 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7754 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7755 }
7756
7757 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7758 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7759 {
7760 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7761 __func__, halStatus );
7762 }
7763
7764 if(sme_Is11dSupported(pHddCtx->hHal))
7765 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7766}
7767
Jeff Johnson295189b2012-06-20 16:38:30 -07007768/**---------------------------------------------------------------------------
7769
7770 \brief hdd_full_power_callback() - HDD full power callback function
7771
7772 This is the function invoked by SME to inform the result of a full power
7773 request issued by HDD
7774
7775 \param - callbackcontext - Pointer to cookie
7776 \param - status - result of request
7777
7778 \return - None
7779
7780 --------------------------------------------------------------------------*/
7781static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7782{
Jeff Johnson72a40512013-12-19 10:14:15 -08007783 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007784
7785 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307786 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007787
7788 if (NULL == callbackContext)
7789 {
7790 hddLog(VOS_TRACE_LEVEL_ERROR,
7791 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007792 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007793 return;
7794 }
7795
Jeff Johnson72a40512013-12-19 10:14:15 -08007796 /* there is a race condition that exists between this callback
7797 function and the caller since the caller could time out either
7798 before or while this code is executing. we use a spinlock to
7799 serialize these actions */
7800 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007801
7802 if (POWER_CONTEXT_MAGIC != pContext->magic)
7803 {
7804 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007805 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007806 hddLog(VOS_TRACE_LEVEL_WARN,
7807 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007808 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 return;
7810 }
7811
Jeff Johnson72a40512013-12-19 10:14:15 -08007812 /* context is valid so caller is still waiting */
7813
7814 /* paranoia: invalidate the magic */
7815 pContext->magic = 0;
7816
7817 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007819
7820 /* serialization is complete */
7821 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007822}
7823
7824/**---------------------------------------------------------------------------
7825
7826 \brief hdd_wlan_exit() - HDD WLAN exit function
7827
7828 This is the driver exit point (invoked during rmmod)
7829
7830 \param - pHddCtx - Pointer to the HDD Context
7831
7832 \return - None
7833
7834 --------------------------------------------------------------------------*/
7835void hdd_wlan_exit(hdd_context_t *pHddCtx)
7836{
7837 eHalStatus halStatus;
7838 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7839 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307840 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007841 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007842 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007843 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307844 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007845
7846 ENTER();
7847
Jeff Johnson88ba7742013-02-27 14:36:02 -08007848 if (VOS_FTM_MODE != hdd_get_conparam())
7849 {
7850 // Unloading, restart logic is no more required.
7851 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007852
c_hpothu5ab05e92014-06-13 17:34:05 +05307853 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7854 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007855 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307856 pAdapter = pAdapterNode->pAdapter;
7857 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007858 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307859 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7860 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7861 {
7862 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7863 hdd_UnregisterWext(pAdapter->dev);
7864 }
7865 // Cancel any outstanding scan requests. We are about to close all
7866 // of our adapters, but an adapter structure is what SME passes back
7867 // to our callback function. Hence if there are any outstanding scan
7868 // requests then there is a race condition between when the adapter
7869 // is closed and when the callback is invoked.We try to resolve that
7870 // race condition here by canceling any outstanding scans before we
7871 // close the adapters.
7872 // Note that the scans may be cancelled in an asynchronous manner,
7873 // so ideally there needs to be some kind of synchronization. Rather
7874 // than introduce a new synchronization here, we will utilize the
7875 // fact that we are about to Request Full Power, and since that is
7876 // synchronized, the expectation is that by the time Request Full
7877 // Power has completed all scans will be cancelled.
7878 if (pHddCtx->scan_info.mScanPending)
7879 {
7880 hddLog(VOS_TRACE_LEVEL_INFO,
7881 FL("abort scan mode: %d sessionId: %d"),
7882 pAdapter->device_mode,
7883 pAdapter->sessionId);
7884 hdd_abort_mac_scan(pHddCtx,
7885 pAdapter->sessionId,
7886 eCSR_SCAN_ABORT_DEFAULT);
7887 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007888 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307889 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7890 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007891 }
7892 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307893 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007894 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307895 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007896 wlan_hdd_ftm_close(pHddCtx);
7897 goto free_hdd_ctx;
7898 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307899
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 /* DeRegister with platform driver as client for Suspend/Resume */
7901 vosStatus = hddDeregisterPmOps(pHddCtx);
7902 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7903 {
7904 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7905 VOS_ASSERT(0);
7906 }
7907
7908 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7909 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7910 {
7911 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007913
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007914 //Stop the traffic monitor timer
7915 if ( VOS_TIMER_STATE_RUNNING ==
7916 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7917 {
7918 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7919 }
7920
7921 // Destroy the traffic monitor timer
7922 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7923 &pHddCtx->tx_rx_trafficTmr)))
7924 {
7925 hddLog(VOS_TRACE_LEVEL_ERROR,
7926 "%s: Cannot deallocate Traffic monitor timer", __func__);
7927 }
7928
Jeff Johnson295189b2012-06-20 16:38:30 -07007929 //Disable IMPS/BMPS as we do not want the device to enter any power
7930 //save mode during shutdown
7931 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7932 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7933 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7934
7935 //Ensure that device is in full power as we will touch H/W during vos_Stop
7936 init_completion(&powerContext.completion);
7937 powerContext.magic = POWER_CONTEXT_MAGIC;
7938
7939 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7940 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7941
7942 if (eHAL_STATUS_SUCCESS != halStatus)
7943 {
7944 if (eHAL_STATUS_PMC_PENDING == halStatus)
7945 {
7946 /* request was sent -- wait for the response */
7947 lrc = wait_for_completion_interruptible_timeout(
7948 &powerContext.completion,
7949 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007950 if (lrc <= 0)
7951 {
7952 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007953 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007954 }
7955 }
7956 else
7957 {
7958 hddLog(VOS_TRACE_LEVEL_ERROR,
7959 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007960 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007961 /* continue -- need to clean up as much as possible */
7962 }
7963 }
7964
Jeff Johnson72a40512013-12-19 10:14:15 -08007965 /* either we never sent a request, we sent a request and received a
7966 response or we sent a request and timed out. if we never sent a
7967 request or if we sent a request and got a response, we want to
7968 clear the magic out of paranoia. if we timed out there is a
7969 race condition such that the callback function could be
7970 executing at the same time we are. of primary concern is if the
7971 callback function had already verified the "magic" but had not
7972 yet set the completion variable when a timeout occurred. we
7973 serialize these activities by invalidating the magic while
7974 holding a shared spinlock which will cause us to block if the
7975 callback is currently executing */
7976 spin_lock(&hdd_context_lock);
7977 powerContext.magic = 0;
7978 spin_unlock(&hdd_context_lock);
7979
Yue Ma0d4891e2013-08-06 17:01:45 -07007980 hdd_debugfs_exit(pHddCtx);
7981
Jeff Johnson295189b2012-06-20 16:38:30 -07007982 // Unregister the Net Device Notifier
7983 unregister_netdevice_notifier(&hdd_netdev_notifier);
7984
Jeff Johnson295189b2012-06-20 16:38:30 -07007985 hdd_stop_all_adapters( pHddCtx );
7986
Jeff Johnson295189b2012-06-20 16:38:30 -07007987#ifdef WLAN_BTAMP_FEATURE
7988 vosStatus = WLANBAP_Stop(pVosContext);
7989 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7990 {
7991 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7992 "%s: Failed to stop BAP",__func__);
7993 }
7994#endif //WLAN_BTAMP_FEATURE
7995
7996 //Stop all the modules
7997 vosStatus = vos_stop( pVosContext );
7998 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7999 {
8000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8001 "%s: Failed to stop VOSS",__func__);
8002 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8003 }
8004
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008006 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008007
8008 //Close the scheduler before calling vos_close to make sure no thread is
8009 // scheduled after the each module close is called i.e after all the data
8010 // structures are freed.
8011 vosStatus = vos_sched_close( pVosContext );
8012 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8013 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8014 "%s: Failed to close VOSS Scheduler",__func__);
8015 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8016 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008017#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008018#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8019 /* Destroy the wake lock */
8020 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8021#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008022 /* Destroy the wake lock */
8023 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008024#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008025
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308026#ifdef CONFIG_ENABLE_LINUX_REG
8027 vosStatus = vos_nv_close();
8028 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8029 {
8030 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8031 "%s: Failed to close NV", __func__);
8032 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8033 }
8034#endif
8035
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 //Close VOSS
8037 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8038 vos_close(pVosContext);
8039
Jeff Johnson295189b2012-06-20 16:38:30 -07008040 //Close Watchdog
8041 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8042 vos_watchdog_close(pVosContext);
8043
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308044 //Clean up HDD Nlink Service
8045 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308046
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308047#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308048 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308049 {
8050 wlan_logging_sock_deactivate_svc();
8051 }
8052#endif
8053
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308054#ifdef WLAN_KD_READY_NOTIFIER
8055 nl_srv_exit(pHddCtx->ptt_pid);
8056#else
8057 nl_srv_exit();
8058#endif /* WLAN_KD_READY_NOTIFIER */
8059
8060
Jeff Johnson295189b2012-06-20 16:38:30 -07008061 hdd_close_all_adapters( pHddCtx );
8062
Jeff Johnson295189b2012-06-20 16:38:30 -07008063 /* free the power on lock from platform driver */
8064 if (free_riva_power_on_lock("wlan"))
8065 {
8066 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8067 __func__);
8068 }
8069
Jeff Johnson88ba7742013-02-27 14:36:02 -08008070free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308071
8072 //Free up dynamically allocated members inside HDD Adapter
8073 if (pHddCtx->cfg_ini)
8074 {
8075 kfree(pHddCtx->cfg_ini);
8076 pHddCtx->cfg_ini= NULL;
8077 }
8078
Leo Changf04ddad2013-09-18 13:46:38 -07008079 /* FTM mode, WIPHY did not registered
8080 If un-register here, system crash will happen */
8081 if (VOS_FTM_MODE != hdd_get_conparam())
8082 {
8083 wiphy_unregister(wiphy) ;
8084 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008085 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008086 if (hdd_is_ssr_required())
8087 {
8088 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008089 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008090 msleep(5000);
8091 }
8092 hdd_set_ssr_required (VOS_FALSE);
8093}
8094
8095
8096/**---------------------------------------------------------------------------
8097
8098 \brief hdd_update_config_from_nv() - Function to update the contents of
8099 the running configuration with parameters taken from NV storage
8100
8101 \param - pHddCtx - Pointer to the HDD global context
8102
8103 \return - VOS_STATUS_SUCCESS if successful
8104
8105 --------------------------------------------------------------------------*/
8106static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8107{
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 v_BOOL_t itemIsValid = VOS_FALSE;
8109 VOS_STATUS status;
8110 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8111 v_U8_t macLoop;
8112
8113 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8114 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8115 if(status != VOS_STATUS_SUCCESS)
8116 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008117 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008118 return VOS_STATUS_E_FAILURE;
8119 }
8120
8121 if (itemIsValid == VOS_TRUE)
8122 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008123 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008124 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8125 VOS_MAX_CONCURRENCY_PERSONA);
8126 if(status != VOS_STATUS_SUCCESS)
8127 {
8128 /* Get MAC from NV fail, not update CFG info
8129 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008130 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008131 return VOS_STATUS_E_FAILURE;
8132 }
8133
8134 /* If first MAC is not valid, treat all others are not valid
8135 * Then all MACs will be got from ini file */
8136 if(vos_is_macaddr_zero(&macFromNV[0]))
8137 {
8138 /* MAC address in NV file is not configured yet */
8139 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8140 return VOS_STATUS_E_INVAL;
8141 }
8142
8143 /* Get MAC address from NV, update CFG info */
8144 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8145 {
8146 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8147 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308148 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 /* This MAC is not valid, skip it
8150 * This MAC will be got from ini file */
8151 }
8152 else
8153 {
8154 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8155 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8156 VOS_MAC_ADDR_SIZE);
8157 }
8158 }
8159 }
8160 else
8161 {
8162 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8163 return VOS_STATUS_E_FAILURE;
8164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008165
Jeff Johnson295189b2012-06-20 16:38:30 -07008166
8167 return VOS_STATUS_SUCCESS;
8168}
8169
8170/**---------------------------------------------------------------------------
8171
8172 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8173
8174 \param - pAdapter - Pointer to the HDD
8175
8176 \return - None
8177
8178 --------------------------------------------------------------------------*/
8179VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8180{
8181 eHalStatus halStatus;
8182 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308183 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008184
Jeff Johnson295189b2012-06-20 16:38:30 -07008185
8186 // Send ready indication to the HDD. This will kick off the MAC
8187 // into a 'running' state and should kick off an initial scan.
8188 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8189 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8190 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008192 "code %08d [x%08x]",__func__, halStatus, halStatus );
8193 return VOS_STATUS_E_FAILURE;
8194 }
8195
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308196 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008197 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8198 // And RIVA will crash
8199 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8200 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308201 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8202 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8203
8204
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 return VOS_STATUS_SUCCESS;
8206}
8207
Jeff Johnson295189b2012-06-20 16:38:30 -07008208/* wake lock APIs for HDD */
8209void hdd_prevent_suspend(void)
8210{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008211#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008212 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008213#else
8214 wcnss_prevent_suspend();
8215#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008216}
8217
8218void hdd_allow_suspend(void)
8219{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008220#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008221 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008222#else
8223 wcnss_allow_suspend();
8224#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008225}
8226
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308227void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008228{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008229#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008230 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008231#else
8232 /* Do nothing as there is no API in wcnss for timeout*/
8233#endif
8234}
8235
Jeff Johnson295189b2012-06-20 16:38:30 -07008236/**---------------------------------------------------------------------------
8237
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008238 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8239 information between Host and Riva
8240
8241 This function gets reported version of FW
8242 It also finds the version of Riva headers used to compile the host
8243 It compares the above two and prints a warning if they are different
8244 It gets the SW and HW version string
8245 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8246 indicating the features they support through a bitmap
8247
8248 \param - pHddCtx - Pointer to HDD context
8249
8250 \return - void
8251
8252 --------------------------------------------------------------------------*/
8253
8254void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8255{
8256
8257 tSirVersionType versionCompiled;
8258 tSirVersionType versionReported;
8259 tSirVersionString versionString;
8260 tANI_U8 fwFeatCapsMsgSupported = 0;
8261 VOS_STATUS vstatus;
8262
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008263 memset(&versionCompiled, 0, sizeof(versionCompiled));
8264 memset(&versionReported, 0, sizeof(versionReported));
8265
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008266 /* retrieve and display WCNSS version information */
8267 do {
8268
8269 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8270 &versionCompiled);
8271 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8272 {
8273 hddLog(VOS_TRACE_LEVEL_FATAL,
8274 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008275 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008276 break;
8277 }
8278
8279 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8280 &versionReported);
8281 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8282 {
8283 hddLog(VOS_TRACE_LEVEL_FATAL,
8284 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008285 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008286 break;
8287 }
8288
8289 if ((versionCompiled.major != versionReported.major) ||
8290 (versionCompiled.minor != versionReported.minor) ||
8291 (versionCompiled.version != versionReported.version) ||
8292 (versionCompiled.revision != versionReported.revision))
8293 {
8294 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8295 "Host expected %u.%u.%u.%u\n",
8296 WLAN_MODULE_NAME,
8297 (int)versionReported.major,
8298 (int)versionReported.minor,
8299 (int)versionReported.version,
8300 (int)versionReported.revision,
8301 (int)versionCompiled.major,
8302 (int)versionCompiled.minor,
8303 (int)versionCompiled.version,
8304 (int)versionCompiled.revision);
8305 }
8306 else
8307 {
8308 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8309 WLAN_MODULE_NAME,
8310 (int)versionReported.major,
8311 (int)versionReported.minor,
8312 (int)versionReported.version,
8313 (int)versionReported.revision);
8314 }
8315
8316 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8317 versionString,
8318 sizeof(versionString));
8319 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8320 {
8321 hddLog(VOS_TRACE_LEVEL_FATAL,
8322 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008323 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008324 break;
8325 }
8326
8327 pr_info("%s: WCNSS software version %s\n",
8328 WLAN_MODULE_NAME, versionString);
8329
8330 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8331 versionString,
8332 sizeof(versionString));
8333 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8334 {
8335 hddLog(VOS_TRACE_LEVEL_FATAL,
8336 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008337 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008338 break;
8339 }
8340
8341 pr_info("%s: WCNSS hardware version %s\n",
8342 WLAN_MODULE_NAME, versionString);
8343
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008344 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8345 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008346 send the message only if it the riva is 1.1
8347 minor numbers for different riva branches:
8348 0 -> (1.0)Mainline Build
8349 1 -> (1.1)Mainline Build
8350 2->(1.04) Stability Build
8351 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008352 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008353 ((versionReported.minor>=1) && (versionReported.version>=1)))
8354 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8355 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008356
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008357 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008358 {
8359#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8360 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8361 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8362#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008363 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8364 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8365 {
8366 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8367 }
8368
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008369 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008370 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008371
8372 } while (0);
8373
8374}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308375void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8376{
8377 struct sk_buff *skb;
8378 struct nlmsghdr *nlh;
8379 tAniMsgHdr *ani_hdr;
8380
8381 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8382
8383 if(skb == NULL) {
8384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8385 "%s: alloc_skb failed", __func__);
8386 return;
8387 }
8388
8389 nlh = (struct nlmsghdr *)skb->data;
8390 nlh->nlmsg_pid = 0; /* from kernel */
8391 nlh->nlmsg_flags = 0;
8392 nlh->nlmsg_seq = 0;
8393 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8394
8395 ani_hdr = NLMSG_DATA(nlh);
8396 ani_hdr->type = type;
8397
8398 switch(type) {
8399 case WLAN_SVC_SAP_RESTART_IND:
8400 ani_hdr->length = 0;
8401 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8402 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8403 break;
8404 default:
8405 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8406 "Attempt to send unknown nlink message %d", type);
8407 kfree_skb(skb);
8408 return;
8409 }
8410
8411 nl_srv_bcast(skb);
8412
8413 return;
8414}
8415
8416
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008417
8418/**---------------------------------------------------------------------------
8419
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308420 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8421
8422 \param - pHddCtx - Pointer to the hdd context
8423
8424 \return - true if hardware supports 5GHz
8425
8426 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308427boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308428{
8429 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8430 * then hardware support 5Ghz.
8431 */
8432 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8433 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308434 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308435 return true;
8436 }
8437 else
8438 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308439 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308440 __func__);
8441 return false;
8442 }
8443}
8444
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308445/**---------------------------------------------------------------------------
8446
8447 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8448 generate function
8449
8450 This is generate the random mac address for WLAN interface
8451
8452 \param - pHddCtx - Pointer to HDD context
8453 idx - Start interface index to get auto
8454 generated mac addr.
8455 mac_addr - Mac address
8456
8457 \return - 0 for success, < 0 for failure
8458
8459 --------------------------------------------------------------------------*/
8460
8461static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8462 int idx, v_MACADDR_t mac_addr)
8463{
8464 int i;
8465 unsigned int serialno;
8466 serialno = wcnss_get_serial_number();
8467
8468 if (0 != serialno)
8469 {
8470 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8471 bytes of the serial number that can be used to generate
8472 the other 3 bytes of the MAC address. Mask off all but
8473 the lower 3 bytes (this will also make sure we don't
8474 overflow in the next step) */
8475 serialno &= 0x00FFFFFF;
8476
8477 /* we need a unique address for each session */
8478 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8479
8480 /* autogen other Mac addresses */
8481 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8482 {
8483 /* start with the entire default address */
8484 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8485 /* then replace the lower 3 bytes */
8486 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8487 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8488 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8489
8490 serialno++;
8491 hddLog(VOS_TRACE_LEVEL_ERROR,
8492 "%s: Derived Mac Addr: "
8493 MAC_ADDRESS_STR, __func__,
8494 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8495 }
8496
8497 }
8498 else
8499 {
8500 hddLog(LOGE, FL("Failed to Get Serial NO"));
8501 return -1;
8502 }
8503 return 0;
8504}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308505
8506/**---------------------------------------------------------------------------
8507
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308508 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8509 completed to flush out the scan results
8510
8511 11d scan is done during driver load and is a passive scan on all
8512 channels supported by the device, 11d scans may find some APs on
8513 frequencies which are forbidden to be used in the regulatory domain
8514 the device is operating in. If these APs are notified to the supplicant
8515 it may try to connect to these APs, thus flush out all the scan results
8516 which are present in SME after 11d scan is done.
8517
8518 \return - eHalStatus
8519
8520 --------------------------------------------------------------------------*/
8521static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8522 tANI_U32 scanId, eCsrScanStatus status)
8523{
8524 ENTER();
8525
8526 sme_ScanFlushResult(halHandle, 0);
8527
8528 EXIT();
8529
8530 return eHAL_STATUS_SUCCESS;
8531}
8532
8533/**---------------------------------------------------------------------------
8534
Jeff Johnson295189b2012-06-20 16:38:30 -07008535 \brief hdd_wlan_startup() - HDD init function
8536
8537 This is the driver startup code executed once a WLAN device has been detected
8538
8539 \param - dev - Pointer to the underlying device
8540
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008541 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008542
8543 --------------------------------------------------------------------------*/
8544
8545int hdd_wlan_startup(struct device *dev )
8546{
8547 VOS_STATUS status;
8548 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008549 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008550 hdd_context_t *pHddCtx = NULL;
8551 v_CONTEXT_t pVosContext= NULL;
8552#ifdef WLAN_BTAMP_FEATURE
8553 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8554 WLANBAP_ConfigType btAmpConfig;
8555 hdd_config_t *pConfig;
8556#endif
8557 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008558 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308559 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008560
8561 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 /*
8563 * cfg80211: wiphy allocation
8564 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308565 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008566
8567 if(wiphy == NULL)
8568 {
8569 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008570 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008571 }
8572
8573 pHddCtx = wiphy_priv(wiphy);
8574
Jeff Johnson295189b2012-06-20 16:38:30 -07008575 //Initialize the adapter context to zeros.
8576 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8577
Jeff Johnson295189b2012-06-20 16:38:30 -07008578 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008579 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308580 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008581
8582 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8583
8584 /*Get vos context here bcoz vos_open requires it*/
8585 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8586
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008587 if(pVosContext == NULL)
8588 {
8589 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8590 goto err_free_hdd_context;
8591 }
8592
Jeff Johnson295189b2012-06-20 16:38:30 -07008593 //Save the Global VOSS context in adapter context for future.
8594 pHddCtx->pvosContext = pVosContext;
8595
8596 //Save the adapter context in global context for future.
8597 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8598
Jeff Johnson295189b2012-06-20 16:38:30 -07008599 pHddCtx->parent_dev = dev;
8600
8601 init_completion(&pHddCtx->full_pwr_comp_var);
8602 init_completion(&pHddCtx->standby_comp_var);
8603 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008604 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008605 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308606 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308607 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008608
8609#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008610 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008611#else
8612 init_completion(&pHddCtx->driver_crda_req);
8613#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008614
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308615 spin_lock_init(&pHddCtx->schedScan_lock);
8616
Jeff Johnson295189b2012-06-20 16:38:30 -07008617 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8618
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308619#ifdef FEATURE_WLAN_TDLS
8620 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8621 * invoked by other instances also) to protect the concurrent
8622 * access for the Adapters by TDLS module.
8623 */
8624 mutex_init(&pHddCtx->tdls_lock);
8625#endif
Agarwal Ashish1f422872014-07-22 00:11:55 +05308626 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308627
Agarwal Ashish1f422872014-07-22 00:11:55 +05308628 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008629 // Load all config first as TL config is needed during vos_open
8630 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8631 if(pHddCtx->cfg_ini == NULL)
8632 {
8633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8634 goto err_free_hdd_context;
8635 }
8636
8637 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8638
8639 // Read and parse the qcom_cfg.ini file
8640 status = hdd_parse_config_ini( pHddCtx );
8641 if ( VOS_STATUS_SUCCESS != status )
8642 {
8643 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8644 __func__, WLAN_INI_FILE);
8645 goto err_config;
8646 }
Arif Hussaind5218912013-12-05 01:10:55 -08008647#ifdef MEMORY_DEBUG
8648 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8649 vos_mem_init();
8650
8651 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8652 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8653#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008654
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308655 /* INI has been read, initialise the configuredMcastBcastFilter with
8656 * INI value as this will serve as the default value
8657 */
8658 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8659 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8660 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308661
8662 if (false == hdd_is_5g_supported(pHddCtx))
8663 {
8664 //5Ghz is not supported.
8665 if (1 != pHddCtx->cfg_ini->nBandCapability)
8666 {
8667 hddLog(VOS_TRACE_LEVEL_INFO,
8668 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8669 pHddCtx->cfg_ini->nBandCapability = 1;
8670 }
8671 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308672
8673 /* If SNR Monitoring is enabled, FW has to parse all beacons
8674 * for calcaluting and storing the average SNR, so set Nth beacon
8675 * filter to 1 to enable FW to parse all the beaocons
8676 */
8677 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8678 {
8679 /* The log level is deliberately set to WARN as overriding
8680 * nthBeaconFilter to 1 will increase power cosumption and this
8681 * might just prove helpful to detect the power issue.
8682 */
8683 hddLog(VOS_TRACE_LEVEL_WARN,
8684 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8685 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008687 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308688 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008689 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008690 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008691 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008692 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8693 {
8694 hddLog(VOS_TRACE_LEVEL_FATAL,
8695 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8696 goto err_config;
8697 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008698 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008699
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008700 // Update VOS trace levels based upon the cfg.ini
8701 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8702 pHddCtx->cfg_ini->vosTraceEnableBAP);
8703 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8704 pHddCtx->cfg_ini->vosTraceEnableTL);
8705 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8706 pHddCtx->cfg_ini->vosTraceEnableWDI);
8707 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8708 pHddCtx->cfg_ini->vosTraceEnableHDD);
8709 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8710 pHddCtx->cfg_ini->vosTraceEnableSME);
8711 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8712 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308713 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8714 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008715 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8716 pHddCtx->cfg_ini->vosTraceEnableWDA);
8717 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8718 pHddCtx->cfg_ini->vosTraceEnableSYS);
8719 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8720 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008721 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8722 pHddCtx->cfg_ini->vosTraceEnableSAP);
8723 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8724 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008725
Jeff Johnson295189b2012-06-20 16:38:30 -07008726 // Update WDI trace levels based upon the cfg.ini
8727 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8728 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8729 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8730 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8731 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8732 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8733 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8734 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008735
Jeff Johnson88ba7742013-02-27 14:36:02 -08008736 if (VOS_FTM_MODE == hdd_get_conparam())
8737 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008738 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8739 {
8740 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8741 goto err_free_hdd_context;
8742 }
8743 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308744
8745 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008746 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008747 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008748
Jeff Johnson88ba7742013-02-27 14:36:02 -08008749 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008750 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8751 {
8752 status = vos_watchdog_open(pVosContext,
8753 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8754
8755 if(!VOS_IS_STATUS_SUCCESS( status ))
8756 {
8757 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308758 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008759 }
8760 }
8761
8762 pHddCtx->isLogpInProgress = FALSE;
8763 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8764
Amar Singhala49cbc52013-10-08 18:37:44 -07008765#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008766 /* initialize the NV module. This is required so that
8767 we can initialize the channel information in wiphy
8768 from the NV.bin data. The channel information in
8769 wiphy needs to be initialized before wiphy registration */
8770
8771 status = vos_nv_open();
8772 if (!VOS_IS_STATUS_SUCCESS(status))
8773 {
8774 /* NV module cannot be initialized */
8775 hddLog( VOS_TRACE_LEVEL_FATAL,
8776 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05308777 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07008778 }
8779
8780 status = vos_init_wiphy_from_nv_bin();
8781 if (!VOS_IS_STATUS_SUCCESS(status))
8782 {
8783 /* NV module cannot be initialized */
8784 hddLog( VOS_TRACE_LEVEL_FATAL,
8785 "%s: vos_init_wiphy failed", __func__);
8786 goto err_vos_nv_close;
8787 }
8788
Amar Singhala49cbc52013-10-08 18:37:44 -07008789#endif
8790
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308791 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008792 if ( !VOS_IS_STATUS_SUCCESS( status ))
8793 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008794 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308795 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008796 }
8797
Jeff Johnson295189b2012-06-20 16:38:30 -07008798 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8799
8800 if ( NULL == pHddCtx->hHal )
8801 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008802 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008803 goto err_vosclose;
8804 }
8805
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008806 status = vos_preStart( pHddCtx->pvosContext );
8807 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8808 {
8809 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308810 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008811 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008812
Arif Hussaineaf68602013-12-30 23:10:44 -08008813 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8814 {
8815 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8816 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8817 __func__, enable_dfs_chan_scan);
8818 }
8819 if (0 == enable_11d || 1 == enable_11d)
8820 {
8821 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8822 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8823 __func__, enable_11d);
8824 }
8825
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008826 /* Note that the vos_preStart() sequence triggers the cfg download.
8827 The cfg download must occur before we update the SME config
8828 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008829 status = hdd_set_sme_config( pHddCtx );
8830
8831 if ( VOS_STATUS_SUCCESS != status )
8832 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308834 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008836
Jeff Johnson295189b2012-06-20 16:38:30 -07008837 /* In the integrated architecture we update the configuration from
8838 the INI file and from NV before vOSS has been started so that
8839 the final contents are available to send down to the cCPU */
8840
8841 // Apply the cfg.ini to cfg.dat
8842 if (FALSE == hdd_update_config_dat(pHddCtx))
8843 {
8844 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308845 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008846 }
8847
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308848 // Get mac addr from platform driver
8849 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8850
8851 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008852 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308853 /* Store the mac addr for first interface */
8854 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8855
8856 hddLog(VOS_TRACE_LEVEL_ERROR,
8857 "%s: WLAN Mac Addr: "
8858 MAC_ADDRESS_STR, __func__,
8859 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8860
8861 /* Here, passing Arg2 as 1 because we do not want to change the
8862 last 3 bytes (means non OUI bytes) of first interface mac
8863 addr.
8864 */
8865 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8866 {
8867 hddLog(VOS_TRACE_LEVEL_ERROR,
8868 "%s: Failed to generate wlan interface mac addr "
8869 "using MAC from ini file ", __func__);
8870 }
8871 }
8872 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8873 {
8874 // Apply the NV to cfg.dat
8875 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008876#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8877 /* There was not a valid set of MAC Addresses in NV. See if the
8878 default addresses were modified by the cfg.ini settings. If so,
8879 we'll use them, but if not, we'll autogenerate a set of MAC
8880 addresses based upon the device serial number */
8881
8882 static const v_MACADDR_t default_address =
8883 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008884
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308885 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8886 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008887 {
8888 /* cfg.ini has the default address, invoke autogen logic */
8889
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308890 /* Here, passing Arg2 as 0 because we want to change the
8891 last 3 bytes (means non OUI bytes) of all the interfaces
8892 mac addr.
8893 */
8894 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8895 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008896 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308897 hddLog(VOS_TRACE_LEVEL_ERROR,
8898 "%s: Failed to generate wlan interface mac addr "
8899 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8900 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008901 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008902 }
8903 else
8904#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8905 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008906 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008907 "%s: Invalid MAC address in NV, using MAC from ini file "
8908 MAC_ADDRESS_STR, __func__,
8909 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8910 }
8911 }
8912 {
8913 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308914
8915 /* Set the MAC Address Currently this is used by HAL to
8916 * add self sta. Remove this once self sta is added as
8917 * part of session open.
8918 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8920 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8921 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308922
Jeff Johnson295189b2012-06-20 16:38:30 -07008923 if (!HAL_STATUS_SUCCESS( halStatus ))
8924 {
8925 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8926 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308927 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008928 }
8929 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008930
8931 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8932 Note: Firmware image will be read and downloaded inside vos_start API */
8933 status = vos_start( pHddCtx->pvosContext );
8934 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8935 {
8936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308937 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008938 }
8939
Leo Chang6cec3e22014-01-21 15:33:49 -08008940#ifdef FEATURE_WLAN_CH_AVOID
8941 /* Plug in avoid channel notification callback
8942 * This should happen before ADD_SELF_STA
8943 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308944
8945 /* check the Channel Avoidance is enabled */
8946 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8947 {
8948 sme_AddChAvoidCallback(pHddCtx->hHal,
8949 hdd_hostapd_ch_avoid_cb);
8950 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008951#endif /* FEATURE_WLAN_CH_AVOID */
8952
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008953 /* Exchange capability info between Host and FW and also get versioning info from FW */
8954 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008955
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308956#ifdef CONFIG_ENABLE_LINUX_REG
8957 status = wlan_hdd_init_channels(pHddCtx);
8958 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8959 {
8960 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8961 __func__);
8962 goto err_vosstop;
8963 }
8964#endif
8965
Jeff Johnson295189b2012-06-20 16:38:30 -07008966 status = hdd_post_voss_start_config( pHddCtx );
8967 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8968 {
8969 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8970 __func__);
8971 goto err_vosstop;
8972 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008973
8974#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308975 wlan_hdd_cfg80211_update_reg_info( wiphy );
8976
8977 /* registration of wiphy dev with cfg80211 */
8978 if (0 > wlan_hdd_cfg80211_register(wiphy))
8979 {
8980 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8981 goto err_vosstop;
8982 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008983#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008984
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308985#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308986 /* registration of wiphy dev with cfg80211 */
8987 if (0 > wlan_hdd_cfg80211_register(wiphy))
8988 {
8989 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8990 goto err_vosstop;
8991 }
8992
8993 status = wlan_hdd_init_channels_for_cc(pHddCtx);
8994 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8995 {
8996 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8997 __func__);
8998 goto err_unregister_wiphy;
8999 }
9000#endif
9001
Jeff Johnson295189b2012-06-20 16:38:30 -07009002 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9003 {
9004 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9005 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9006 }
9007 else
9008 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009009 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9010 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9011 if (pAdapter != NULL)
9012 {
kaidde69982014-06-18 13:23:21 +08009013 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009014 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309015 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9016 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9017 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009018
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309019 /* Generate the P2P Device Address. This consists of the device's
9020 * primary MAC address with the locally administered bit set.
9021 */
9022 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009023 }
9024 else
9025 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309026 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9027 if (p2p_dev_addr != NULL)
9028 {
9029 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9030 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9031 }
9032 else
9033 {
9034 hddLog(VOS_TRACE_LEVEL_FATAL,
9035 "%s: Failed to allocate mac_address for p2p_device",
9036 __func__);
9037 goto err_close_adapter;
9038 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009039 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009040
9041 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9042 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9043 if ( NULL == pP2pAdapter )
9044 {
9045 hddLog(VOS_TRACE_LEVEL_FATAL,
9046 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009047 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009048 goto err_close_adapter;
9049 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009050 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009051 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009052
9053 if( pAdapter == NULL )
9054 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009055 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9056 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009057 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009058
Arif Hussain66559122013-11-21 10:11:40 -08009059 if (country_code)
9060 {
9061 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009062 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009063 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9064#ifndef CONFIG_ENABLE_LINUX_REG
9065 hdd_checkandupdate_phymode(pAdapter, country_code);
9066#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009067 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9068 (void *)(tSmeChangeCountryCallback)
9069 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009070 country_code,
9071 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309072 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009073 if (eHAL_STATUS_SUCCESS == ret)
9074 {
Arif Hussaincb607082013-12-20 11:57:42 -08009075 ret = wait_for_completion_interruptible_timeout(
9076 &pAdapter->change_country_code,
9077 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9078
9079 if (0 >= ret)
9080 {
9081 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9082 "%s: SME while setting country code timed out", __func__);
9083 }
Arif Hussain66559122013-11-21 10:11:40 -08009084 }
9085 else
9086 {
Arif Hussaincb607082013-12-20 11:57:42 -08009087 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9088 "%s: SME Change Country code from module param fail ret=%d",
9089 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009090 }
9091 }
9092
Jeff Johnson295189b2012-06-20 16:38:30 -07009093#ifdef WLAN_BTAMP_FEATURE
9094 vStatus = WLANBAP_Open(pVosContext);
9095 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9096 {
9097 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9098 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009099 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009100 }
9101
9102 vStatus = BSL_Init(pVosContext);
9103 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9104 {
9105 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9106 "%s: Failed to Init BSL",__func__);
9107 goto err_bap_close;
9108 }
9109 vStatus = WLANBAP_Start(pVosContext);
9110 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9111 {
9112 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9113 "%s: Failed to start TL",__func__);
9114 goto err_bap_close;
9115 }
9116
9117 pConfig = pHddCtx->cfg_ini;
9118 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9119 status = WLANBAP_SetConfig(&btAmpConfig);
9120
9121#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009122
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009123#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9124 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9125 {
9126 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9127 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9128 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9129 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9130 }
9131#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009132
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309133 wlan_hdd_tdls_init(pHddCtx);
9134
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309135 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9136
Jeff Johnson295189b2012-06-20 16:38:30 -07009137 /* Register with platform driver as client for Suspend/Resume */
9138 status = hddRegisterPmOps(pHddCtx);
9139 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9140 {
9141 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9142#ifdef WLAN_BTAMP_FEATURE
9143 goto err_bap_stop;
9144#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009145 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009146#endif //WLAN_BTAMP_FEATURE
9147 }
9148
Yue Ma0d4891e2013-08-06 17:01:45 -07009149 /* Open debugfs interface */
9150 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9151 {
9152 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9153 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009154 }
9155
Jeff Johnson295189b2012-06-20 16:38:30 -07009156 /* Register TM level change handler function to the platform */
9157 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9158 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9159 {
9160 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9161 goto err_unregister_pmops;
9162 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009163
9164 /* register for riva power on lock to platform driver */
9165 if (req_riva_power_on_lock("wlan"))
9166 {
9167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9168 __func__);
9169 goto err_unregister_pmops;
9170 }
9171
Jeff Johnson295189b2012-06-20 16:38:30 -07009172 // register net device notifier for device change notification
9173 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9174
9175 if(ret < 0)
9176 {
9177 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9178 goto err_free_power_on_lock;
9179 }
9180
9181 //Initialize the nlink service
9182 if(nl_srv_init() != 0)
9183 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309184 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009185 goto err_reg_netdev;
9186 }
9187
Leo Chang4ce1cc52013-10-21 18:27:15 -07009188#ifdef WLAN_KD_READY_NOTIFIER
9189 pHddCtx->kd_nl_init = 1;
9190#endif /* WLAN_KD_READY_NOTIFIER */
9191
Jeff Johnson295189b2012-06-20 16:38:30 -07009192 //Initialize the BTC service
9193 if(btc_activate_service(pHddCtx) != 0)
9194 {
9195 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9196 goto err_nl_srv;
9197 }
9198
9199#ifdef PTT_SOCK_SVC_ENABLE
9200 //Initialize the PTT service
9201 if(ptt_sock_activate_svc(pHddCtx) != 0)
9202 {
9203 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9204 goto err_nl_srv;
9205 }
9206#endif
9207
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309208#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9209 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9210 {
9211 if(wlan_logging_sock_activate_svc(
9212 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9213 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9214 {
9215 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9216 " failed", __func__);
9217 goto err_nl_srv;
9218 }
9219 }
9220#endif
9221
Jeff Johnson295189b2012-06-20 16:38:30 -07009222 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009223 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009224 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009225 /* Action frame registered in one adapter which will
9226 * applicable to all interfaces
9227 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309228 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009229 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009230
9231 mutex_init(&pHddCtx->sap_lock);
9232
Jeff Johnson295189b2012-06-20 16:38:30 -07009233
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009234#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009235#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9236 /* Initialize the wake lcok */
9237 wake_lock_init(&pHddCtx->rx_wake_lock,
9238 WAKE_LOCK_SUSPEND,
9239 "qcom_rx_wakelock");
9240#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009241 /* Initialize the wake lcok */
9242 wake_lock_init(&pHddCtx->sap_wake_lock,
9243 WAKE_LOCK_SUSPEND,
9244 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009245#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009246
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009247 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9248 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009249
Katya Nigam5c306ea2014-06-19 15:39:54 +05309250 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009251 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9252 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309253
9254#ifdef FEATURE_WLAN_SCAN_PNO
9255 /*SME must send channel update configuration to RIVA*/
9256 sme_UpdateChannelConfig(pHddCtx->hHal);
9257#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309258 /* Send the update default channel list to the FW*/
9259 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309260#ifndef CONFIG_ENABLE_LINUX_REG
9261 /*updating wiphy so that regulatory user hints can be processed*/
9262 if (wiphy)
9263 {
9264 regulatory_hint(wiphy, "00");
9265 }
9266#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009267 // Initialize the restart logic
9268 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309269
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009270 //Register the traffic monitor timer now
9271 if ( pHddCtx->cfg_ini->dynSplitscan)
9272 {
9273 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9274 VOS_TIMER_TYPE_SW,
9275 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9276 (void *)pHddCtx);
9277 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309278#ifdef WLAN_FEATURE_EXTSCAN
9279 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9280 wlan_hdd_cfg80211_extscan_callback,
9281 pHddCtx);
9282#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009283 goto success;
9284
9285err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009286#ifdef WLAN_KD_READY_NOTIFIER
9287 nl_srv_exit(pHddCtx->ptt_pid);
9288#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009289 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009290#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009291err_reg_netdev:
9292 unregister_netdevice_notifier(&hdd_netdev_notifier);
9293
9294err_free_power_on_lock:
9295 free_riva_power_on_lock("wlan");
9296
9297err_unregister_pmops:
9298 hddDevTmUnregisterNotifyCallback(pHddCtx);
9299 hddDeregisterPmOps(pHddCtx);
9300
Yue Ma0d4891e2013-08-06 17:01:45 -07009301 hdd_debugfs_exit(pHddCtx);
9302
Jeff Johnson295189b2012-06-20 16:38:30 -07009303#ifdef WLAN_BTAMP_FEATURE
9304err_bap_stop:
9305 WLANBAP_Stop(pVosContext);
9306#endif
9307
9308#ifdef WLAN_BTAMP_FEATURE
9309err_bap_close:
9310 WLANBAP_Close(pVosContext);
9311#endif
9312
Jeff Johnson295189b2012-06-20 16:38:30 -07009313err_close_adapter:
9314 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309315#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309316err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309317#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309318 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009319err_vosstop:
9320 vos_stop(pVosContext);
9321
Amar Singhala49cbc52013-10-08 18:37:44 -07009322err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009323 status = vos_sched_close( pVosContext );
9324 if (!VOS_IS_STATUS_SUCCESS(status)) {
9325 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9326 "%s: Failed to close VOSS Scheduler", __func__);
9327 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9328 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009329 vos_close(pVosContext );
9330
Amar Singhal0a402232013-10-11 20:57:16 -07009331err_vos_nv_close:
9332
c_hpothue6a36282014-03-19 12:27:38 +05309333#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009334 vos_nv_close();
9335
c_hpothu70f8d812014-03-22 22:59:23 +05309336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009337
9338err_wdclose:
9339 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9340 vos_watchdog_close(pVosContext);
9341
Jeff Johnson295189b2012-06-20 16:38:30 -07009342err_config:
9343 kfree(pHddCtx->cfg_ini);
9344 pHddCtx->cfg_ini= NULL;
9345
9346err_free_hdd_context:
9347 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009348 wiphy_free(wiphy) ;
9349 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009350 VOS_BUG(1);
9351
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009352 if (hdd_is_ssr_required())
9353 {
9354 /* WDI timeout had happened during load, so SSR is needed here */
9355 subsystem_restart("wcnss");
9356 msleep(5000);
9357 }
9358 hdd_set_ssr_required (VOS_FALSE);
9359
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009360 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009361
9362success:
9363 EXIT();
9364 return 0;
9365}
9366
9367/**---------------------------------------------------------------------------
9368
Jeff Johnson32d95a32012-09-10 13:15:23 -07009369 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009370
Jeff Johnson32d95a32012-09-10 13:15:23 -07009371 This is the driver entry point - called in different timeline depending
9372 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009373
9374 \param - None
9375
9376 \return - 0 for success, non zero for failure
9377
9378 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009379static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009380{
9381 VOS_STATUS status;
9382 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009383 struct device *dev = NULL;
9384 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009385#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9386 int max_retries = 0;
9387#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009388
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309389#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9390 wlan_logging_sock_init_svc();
9391#endif
9392
Jeff Johnson295189b2012-06-20 16:38:30 -07009393 ENTER();
9394
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009395#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009396 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009397#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009398
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309399 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009400 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9401 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9402
Jeff Johnson295189b2012-06-20 16:38:30 -07009403#ifdef ANI_BUS_TYPE_PCI
9404
9405 dev = wcnss_wlan_get_device();
9406
9407#endif // ANI_BUS_TYPE_PCI
9408
9409#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009410
9411#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9412 /* wait until WCNSS driver downloads NV */
9413 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9414 msleep(1000);
9415 }
9416 if (max_retries >= 5) {
9417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309418#ifdef WLAN_OPEN_SOURCE
9419 wake_lock_destroy(&wlan_wake_lock);
9420#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309421
9422#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9423 wlan_logging_sock_deinit_svc();
9424#endif
9425
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009426 return -ENODEV;
9427 }
9428#endif
9429
Jeff Johnson295189b2012-06-20 16:38:30 -07009430 dev = wcnss_wlan_get_device();
9431#endif // ANI_BUS_TYPE_PLATFORM
9432
9433
9434 do {
9435 if (NULL == dev) {
9436 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9437 ret_status = -1;
9438 break;
9439 }
9440
Jeff Johnson295189b2012-06-20 16:38:30 -07009441#ifdef TIMER_MANAGER
9442 vos_timer_manager_init();
9443#endif
9444
9445 /* Preopen VOSS so that it is ready to start at least SAL */
9446 status = vos_preOpen(&pVosContext);
9447
9448 if (!VOS_IS_STATUS_SUCCESS(status))
9449 {
9450 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9451 ret_status = -1;
9452 break;
9453 }
9454
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009455#ifndef MODULE
9456 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9457 */
9458 hdd_set_conparam((v_UINT_t)con_mode);
9459#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009460
9461 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009462 if (hdd_wlan_startup(dev))
9463 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009464 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009465 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009466 vos_preClose( &pVosContext );
9467 ret_status = -1;
9468 break;
9469 }
9470
Jeff Johnson295189b2012-06-20 16:38:30 -07009471 } while (0);
9472
9473 if (0 != ret_status)
9474 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009475#ifdef TIMER_MANAGER
9476 vos_timer_exit();
9477#endif
9478#ifdef MEMORY_DEBUG
9479 vos_mem_exit();
9480#endif
9481
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009482#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009483 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009484#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309485
9486#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9487 wlan_logging_sock_deinit_svc();
9488#endif
9489
Jeff Johnson295189b2012-06-20 16:38:30 -07009490 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9491 }
9492 else
9493 {
9494 //Send WLAN UP indication to Nlink Service
9495 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9496
9497 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009498 }
9499
9500 EXIT();
9501
9502 return ret_status;
9503}
9504
Jeff Johnson32d95a32012-09-10 13:15:23 -07009505/**---------------------------------------------------------------------------
9506
9507 \brief hdd_module_init() - Init Function
9508
9509 This is the driver entry point (invoked when module is loaded using insmod)
9510
9511 \param - None
9512
9513 \return - 0 for success, non zero for failure
9514
9515 --------------------------------------------------------------------------*/
9516#ifdef MODULE
9517static int __init hdd_module_init ( void)
9518{
9519 return hdd_driver_init();
9520}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009521#else /* #ifdef MODULE */
9522static int __init hdd_module_init ( void)
9523{
9524 /* Driver initialization is delayed to fwpath_changed_handler */
9525 return 0;
9526}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009527#endif /* #ifdef MODULE */
9528
Jeff Johnson295189b2012-06-20 16:38:30 -07009529
9530/**---------------------------------------------------------------------------
9531
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009532 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009533
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009534 This is the driver exit point (invoked when module is unloaded using rmmod
9535 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009536
9537 \param - None
9538
9539 \return - None
9540
9541 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009542static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009543{
9544 hdd_context_t *pHddCtx = NULL;
9545 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309546 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309547 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009548
9549 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9550
9551 //Get the global vos context
9552 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9553
9554 if(!pVosContext)
9555 {
9556 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9557 goto done;
9558 }
9559
9560 //Get the HDD context.
9561 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9562
9563 if(!pHddCtx)
9564 {
9565 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9566 }
9567 else
9568 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309569 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9570
9571 if (pHddCtx->isLogpInProgress)
9572 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309574 "%s:SSR in Progress; block rmmod !!!", __func__);
9575 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9576 msecs_to_jiffies(30000));
9577 if(!rc)
9578 {
9579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9580 "%s:SSR timedout, fatal error", __func__);
9581 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009582 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309583 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009584
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309585 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309586 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009587 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309588 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009589
Agarwal Ashish8db39882014-07-30 21:56:07 +05309590 /* Driver Need to send country code 00 in below condition
9591 * 1) If gCountryCodePriority is set to 1; and last country
9592 * code set is through 11d. This needs to be done in case
9593 * when NV country code is 00.
9594 * This Needs to be done as when kernel store last country
9595 * code and if stored country code is not through 11d,
9596 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9597 * in next load/unload as soon as we get any country through
9598 * 11d. In sme_HandleChangeCountryCodeByUser
9599 * pMsg->countryCode will be last countryCode and
9600 * pMac->scan.countryCode11d will be country through 11d so
9601 * due to mismatch driver will disable 11d.
9602 *
9603 * 2) When NV country Code is non-zero ;
9604 * There are chances that kernel last country and default
9605 * country can be same. In this case if Driver doesn't pass 00 to
9606 * kernel, at the time of driver loading next timer, driver will not
9607 * call any hint to kernel as country is same. This can add 3 sec
9608 * delay in driver loading.
9609 */
9610
9611 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309612 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Agarwal Ashish8db39882014-07-30 21:56:07 +05309613 sme_Is11dSupported(pHddCtx->hHal)) || (vos_is_nv_country_non_zero() ))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309614 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309615 hddLog(VOS_TRACE_LEVEL_INFO,
9616 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309617 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9618 }
9619
Jeff Johnson295189b2012-06-20 16:38:30 -07009620 //Do all the cleanup before deregistering the driver
9621 hdd_wlan_exit(pHddCtx);
9622 }
9623
Jeff Johnson295189b2012-06-20 16:38:30 -07009624 vos_preClose( &pVosContext );
9625
9626#ifdef TIMER_MANAGER
9627 vos_timer_exit();
9628#endif
9629#ifdef MEMORY_DEBUG
9630 vos_mem_exit();
9631#endif
9632
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309633#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9634 wlan_logging_sock_deinit_svc();
9635#endif
9636
Jeff Johnson295189b2012-06-20 16:38:30 -07009637done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009638#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009639 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009640#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309641
Jeff Johnson295189b2012-06-20 16:38:30 -07009642 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9643}
9644
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009645/**---------------------------------------------------------------------------
9646
9647 \brief hdd_module_exit() - Exit function
9648
9649 This is the driver exit point (invoked when module is unloaded using rmmod)
9650
9651 \param - None
9652
9653 \return - None
9654
9655 --------------------------------------------------------------------------*/
9656static void __exit hdd_module_exit(void)
9657{
9658 hdd_driver_exit();
9659}
9660
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009661#ifdef MODULE
9662static int fwpath_changed_handler(const char *kmessage,
9663 struct kernel_param *kp)
9664{
Jeff Johnson76052702013-04-16 13:55:05 -07009665 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009666}
9667
9668static int con_mode_handler(const char *kmessage,
9669 struct kernel_param *kp)
9670{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009671 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009672}
9673#else /* #ifdef MODULE */
9674/**---------------------------------------------------------------------------
9675
Jeff Johnson76052702013-04-16 13:55:05 -07009676 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009677
Jeff Johnson76052702013-04-16 13:55:05 -07009678 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009679 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009680 - invoked when module parameter fwpath is modified from userspace to signal
9681 initializing the WLAN driver or when con_mode is modified from userspace
9682 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009683
9684 \return - 0 for success, non zero for failure
9685
9686 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009687static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009688{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009689 int ret_status;
9690
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009691 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009692 ret_status = hdd_driver_init();
9693 wlan_hdd_inited = ret_status ? 0 : 1;
9694 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009695 }
9696
9697 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009698
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009699 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009700
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009701 ret_status = hdd_driver_init();
9702 wlan_hdd_inited = ret_status ? 0 : 1;
9703 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009704}
9705
Jeff Johnson295189b2012-06-20 16:38:30 -07009706/**---------------------------------------------------------------------------
9707
Jeff Johnson76052702013-04-16 13:55:05 -07009708 \brief fwpath_changed_handler() - Handler Function
9709
9710 Handle changes to the fwpath parameter
9711
9712 \return - 0 for success, non zero for failure
9713
9714 --------------------------------------------------------------------------*/
9715static int fwpath_changed_handler(const char *kmessage,
9716 struct kernel_param *kp)
9717{
9718 int ret;
9719
9720 ret = param_set_copystring(kmessage, kp);
9721 if (0 == ret)
9722 ret = kickstart_driver();
9723 return ret;
9724}
9725
9726/**---------------------------------------------------------------------------
9727
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009728 \brief con_mode_handler() -
9729
9730 Handler function for module param con_mode when it is changed by userspace
9731 Dynamically linked - do nothing
9732 Statically linked - exit and init driver, as in rmmod and insmod
9733
Jeff Johnson76052702013-04-16 13:55:05 -07009734 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009735
Jeff Johnson76052702013-04-16 13:55:05 -07009736 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009737
9738 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009739static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009740{
Jeff Johnson76052702013-04-16 13:55:05 -07009741 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009742
Jeff Johnson76052702013-04-16 13:55:05 -07009743 ret = param_set_int(kmessage, kp);
9744 if (0 == ret)
9745 ret = kickstart_driver();
9746 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009747}
9748#endif /* #ifdef MODULE */
9749
9750/**---------------------------------------------------------------------------
9751
Jeff Johnson295189b2012-06-20 16:38:30 -07009752 \brief hdd_get_conparam() -
9753
9754 This is the driver exit point (invoked when module is unloaded using rmmod)
9755
9756 \param - None
9757
9758 \return - tVOS_CON_MODE
9759
9760 --------------------------------------------------------------------------*/
9761tVOS_CON_MODE hdd_get_conparam ( void )
9762{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009763#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009764 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009765#else
9766 return (tVOS_CON_MODE)curr_con_mode;
9767#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009768}
9769void hdd_set_conparam ( v_UINT_t newParam )
9770{
9771 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009772#ifndef MODULE
9773 curr_con_mode = con_mode;
9774#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009775}
9776/**---------------------------------------------------------------------------
9777
9778 \brief hdd_softap_sta_deauth() - function
9779
9780 This to take counter measure to handle deauth req from HDD
9781
9782 \param - pAdapter - Pointer to the HDD
9783
9784 \param - enable - boolean value
9785
9786 \return - None
9787
9788 --------------------------------------------------------------------------*/
9789
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009790VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009791{
Jeff Johnson295189b2012-06-20 16:38:30 -07009792 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009793 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009794
9795 ENTER();
9796
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009797 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9798 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009799
9800 //Ignore request to deauth bcmc station
9801 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009802 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009803
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009804 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009805
9806 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009807 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009808}
9809
9810/**---------------------------------------------------------------------------
9811
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309812 \brief hdd_del_all_sta() - function
9813
9814 This function removes all the stations associated on stopping AP/P2P GO.
9815
9816 \param - pAdapter - Pointer to the HDD
9817
9818 \return - None
9819
9820 --------------------------------------------------------------------------*/
9821
9822int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9823{
9824 v_U16_t i;
9825 VOS_STATUS vos_status;
9826
9827 ENTER();
9828
9829 hddLog(VOS_TRACE_LEVEL_INFO,
9830 "%s: Delete all STAs associated.",__func__);
9831 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9832 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9833 )
9834 {
9835 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9836 {
9837 if ((pAdapter->aStaInfo[i].isUsed) &&
9838 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9839 {
9840 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
9841 hddLog(VOS_TRACE_LEVEL_ERROR,
9842 "%s: Delete STA with staid = %d and MAC::"
9843 MAC_ADDRESS_STR,
9844 __func__, i, MAC_ADDR_ARRAY(macAddr));
9845 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
9846 if (VOS_IS_STATUS_SUCCESS(vos_status))
9847 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9848 }
9849 }
9850 }
9851
9852 EXIT();
9853 return 0;
9854}
9855
9856/**---------------------------------------------------------------------------
9857
Jeff Johnson295189b2012-06-20 16:38:30 -07009858 \brief hdd_softap_sta_disassoc() - function
9859
9860 This to take counter measure to handle deauth req from HDD
9861
9862 \param - pAdapter - Pointer to the HDD
9863
9864 \param - enable - boolean value
9865
9866 \return - None
9867
9868 --------------------------------------------------------------------------*/
9869
9870void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9871{
9872 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9873
9874 ENTER();
9875
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309876 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009877
9878 //Ignore request to disassoc bcmc station
9879 if( pDestMacAddress[0] & 0x1 )
9880 return;
9881
9882 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9883}
9884
9885void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9886{
9887 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9888
9889 ENTER();
9890
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309891 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009892
9893 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9894}
9895
Jeff Johnson295189b2012-06-20 16:38:30 -07009896/**---------------------------------------------------------------------------
9897 *
9898 * \brief hdd_get__concurrency_mode() -
9899 *
9900 *
9901 * \param - None
9902 *
9903 * \return - CONCURRENCY MODE
9904 *
9905 * --------------------------------------------------------------------------*/
9906tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9907{
9908 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9909 hdd_context_t *pHddCtx;
9910
9911 if (NULL != pVosContext)
9912 {
9913 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9914 if (NULL != pHddCtx)
9915 {
9916 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9917 }
9918 }
9919
9920 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009921 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009922 return VOS_STA;
9923}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309924v_BOOL_t
9925wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9926{
9927 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009928
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309929 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9930 if (pAdapter == NULL)
9931 {
9932 hddLog(VOS_TRACE_LEVEL_INFO,
9933 FL("GO doesn't exist"));
9934 return TRUE;
9935 }
9936 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9937 {
9938 hddLog(VOS_TRACE_LEVEL_INFO,
9939 FL("GO started"));
9940 return TRUE;
9941 }
9942 else
9943 /* wait till GO changes its interface to p2p device */
9944 hddLog(VOS_TRACE_LEVEL_INFO,
9945 FL("Del_bss called, avoid apps suspend"));
9946 return FALSE;
9947
9948}
Jeff Johnson295189b2012-06-20 16:38:30 -07009949/* Decide whether to allow/not the apps power collapse.
9950 * Allow apps power collapse if we are in connected state.
9951 * if not, allow only if we are in IMPS */
9952v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9953{
9954 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009955 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009956 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009957 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9958 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9959 hdd_adapter_t *pAdapter = NULL;
9960 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009961 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009962
Jeff Johnson295189b2012-06-20 16:38:30 -07009963 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9964 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009965
Yathish9f22e662012-12-10 14:21:35 -08009966 concurrent_state = hdd_get_concurrency_mode();
9967
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309968 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
9969 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
9970 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -08009971#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309972
Yathish9f22e662012-12-10 14:21:35 -08009973 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309974 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -08009975 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9976 return TRUE;
9977#endif
9978
Jeff Johnson295189b2012-06-20 16:38:30 -07009979 /*loop through all adapters. TBD fix for Concurrency */
9980 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9981 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9982 {
9983 pAdapter = pAdapterNode->pAdapter;
9984 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9985 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9986 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009987 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +05309988 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -08009989 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009990 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9991 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009992 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009993 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009994 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9995 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009996 return FALSE;
9997 }
9998 }
9999 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10000 pAdapterNode = pNext;
10001 }
10002 return TRUE;
10003}
10004
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010005/* Decides whether to send suspend notification to Riva
10006 * if any adapter is in BMPS; then it is required */
10007v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10008{
10009 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10010 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10011
10012 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10013 {
10014 return TRUE;
10015 }
10016 return FALSE;
10017}
10018
Jeff Johnson295189b2012-06-20 16:38:30 -070010019void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10020{
10021 switch(mode)
10022 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010023 case VOS_STA_MODE:
10024 case VOS_P2P_CLIENT_MODE:
10025 case VOS_P2P_GO_MODE:
10026 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010027 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010028 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010029 break;
10030 default:
10031 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010032 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010033 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10034 "Number of open sessions for mode %d = %d"),
10035 pHddCtx->concurrency_mode, mode,
10036 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010037}
10038
10039
10040void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10041{
10042 switch(mode)
10043 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010044 case VOS_STA_MODE:
10045 case VOS_P2P_CLIENT_MODE:
10046 case VOS_P2P_GO_MODE:
10047 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010048 pHddCtx->no_of_open_sessions[mode]--;
10049 if (!(pHddCtx->no_of_open_sessions[mode]))
10050 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010051 break;
10052 default:
10053 break;
10054 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010055 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10056 "Number of open sessions for mode %d = %d"),
10057 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10058
10059}
10060/**---------------------------------------------------------------------------
10061 *
10062 * \brief wlan_hdd_incr_active_session()
10063 *
10064 * This function increments the number of active sessions
10065 * maintained per device mode
10066 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10067 * Incase of SAP/P2P GO upon bss start it is incremented
10068 *
10069 * \param pHddCtx - HDD Context
10070 * \param mode - device mode
10071 *
10072 * \return - None
10073 *
10074 * --------------------------------------------------------------------------*/
10075void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10076{
10077 switch (mode) {
10078 case VOS_STA_MODE:
10079 case VOS_P2P_CLIENT_MODE:
10080 case VOS_P2P_GO_MODE:
10081 case VOS_STA_SAP_MODE:
10082 pHddCtx->no_of_active_sessions[mode]++;
10083 break;
10084 default:
10085 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10086 break;
10087 }
10088 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10089 mode,
10090 pHddCtx->no_of_active_sessions[mode]);
10091}
10092
10093/**---------------------------------------------------------------------------
10094 *
10095 * \brief wlan_hdd_decr_active_session()
10096 *
10097 * This function decrements the number of active sessions
10098 * maintained per device mode
10099 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10100 * Incase of SAP/P2P GO upon bss stop it is decremented
10101 *
10102 * \param pHddCtx - HDD Context
10103 * \param mode - device mode
10104 *
10105 * \return - None
10106 *
10107 * --------------------------------------------------------------------------*/
10108void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10109{
10110 switch (mode) {
10111 case VOS_STA_MODE:
10112 case VOS_P2P_CLIENT_MODE:
10113 case VOS_P2P_GO_MODE:
10114 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010115 if (pHddCtx->no_of_active_sessions[mode] > 0)
10116 pHddCtx->no_of_active_sessions[mode]--;
10117 else
10118 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10119 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010120 break;
10121 default:
10122 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10123 break;
10124 }
10125 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10126 mode,
10127 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010128}
10129
Jeff Johnsone7245742012-09-05 17:12:55 -070010130/**---------------------------------------------------------------------------
10131 *
10132 * \brief wlan_hdd_restart_init
10133 *
10134 * This function initalizes restart timer/flag. An internal function.
10135 *
10136 * \param - pHddCtx
10137 *
10138 * \return - None
10139 *
10140 * --------------------------------------------------------------------------*/
10141
10142static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10143{
10144 /* Initialize */
10145 pHddCtx->hdd_restart_retries = 0;
10146 atomic_set(&pHddCtx->isRestartInProgress, 0);
10147 vos_timer_init(&pHddCtx->hdd_restart_timer,
10148 VOS_TIMER_TYPE_SW,
10149 wlan_hdd_restart_timer_cb,
10150 pHddCtx);
10151}
10152/**---------------------------------------------------------------------------
10153 *
10154 * \brief wlan_hdd_restart_deinit
10155 *
10156 * This function cleans up the resources used. An internal function.
10157 *
10158 * \param - pHddCtx
10159 *
10160 * \return - None
10161 *
10162 * --------------------------------------------------------------------------*/
10163
10164static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10165{
10166
10167 VOS_STATUS vos_status;
10168 /* Block any further calls */
10169 atomic_set(&pHddCtx->isRestartInProgress, 1);
10170 /* Cleanup */
10171 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10172 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010173 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010174 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10175 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010176 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010177
10178}
10179
10180/**---------------------------------------------------------------------------
10181 *
10182 * \brief wlan_hdd_framework_restart
10183 *
10184 * This function uses a cfg80211 API to start a framework initiated WLAN
10185 * driver module unload/load.
10186 *
10187 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10188 *
10189 *
10190 * \param - pHddCtx
10191 *
10192 * \return - VOS_STATUS_SUCCESS: Success
10193 * VOS_STATUS_E_EMPTY: Adapter is Empty
10194 * VOS_STATUS_E_NOMEM: No memory
10195
10196 * --------------------------------------------------------------------------*/
10197
10198static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10199{
10200 VOS_STATUS status = VOS_STATUS_SUCCESS;
10201 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010202 int len = (sizeof (struct ieee80211_mgmt));
10203 struct ieee80211_mgmt *mgmt = NULL;
10204
10205 /* Prepare the DEAUTH managment frame with reason code */
10206 mgmt = kzalloc(len, GFP_KERNEL);
10207 if(mgmt == NULL)
10208 {
10209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10210 "%s: memory allocation failed (%d bytes)", __func__, len);
10211 return VOS_STATUS_E_NOMEM;
10212 }
10213 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010214
10215 /* Iterate over all adapters/devices */
10216 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10217 do
10218 {
10219 if( (status == VOS_STATUS_SUCCESS) &&
10220 pAdapterNode &&
10221 pAdapterNode->pAdapter)
10222 {
10223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10224 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10225 pAdapterNode->pAdapter->dev->name,
10226 pAdapterNode->pAdapter->device_mode,
10227 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010228 /*
10229 * CFG80211 event to restart the driver
10230 *
10231 * 'cfg80211_send_unprot_deauth' sends a
10232 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10233 * of SME(Linux Kernel) state machine.
10234 *
10235 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10236 * the driver.
10237 *
10238 */
10239
10240 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010241 }
10242 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10243 pAdapterNode = pNext;
10244 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10245
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010246
10247 /* Free the allocated management frame */
10248 kfree(mgmt);
10249
Jeff Johnsone7245742012-09-05 17:12:55 -070010250 /* Retry until we unload or reach max count */
10251 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10252 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10253
10254 return status;
10255
10256}
10257/**---------------------------------------------------------------------------
10258 *
10259 * \brief wlan_hdd_restart_timer_cb
10260 *
10261 * Restart timer callback. An internal function.
10262 *
10263 * \param - User data:
10264 *
10265 * \return - None
10266 *
10267 * --------------------------------------------------------------------------*/
10268
10269void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10270{
10271 hdd_context_t *pHddCtx = usrDataForCallback;
10272 wlan_hdd_framework_restart(pHddCtx);
10273 return;
10274
10275}
10276
10277
10278/**---------------------------------------------------------------------------
10279 *
10280 * \brief wlan_hdd_restart_driver
10281 *
10282 * This function sends an event to supplicant to restart the WLAN driver.
10283 *
10284 * This function is called from vos_wlanRestart.
10285 *
10286 * \param - pHddCtx
10287 *
10288 * \return - VOS_STATUS_SUCCESS: Success
10289 * VOS_STATUS_E_EMPTY: Adapter is Empty
10290 * VOS_STATUS_E_ALREADY: Request already in progress
10291
10292 * --------------------------------------------------------------------------*/
10293VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10294{
10295 VOS_STATUS status = VOS_STATUS_SUCCESS;
10296
10297 /* A tight check to make sure reentrancy */
10298 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10299 {
Mihir Shetefd528652014-06-23 19:07:50 +053010300 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010301 "%s: WLAN restart is already in progress", __func__);
10302
10303 return VOS_STATUS_E_ALREADY;
10304 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010305 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010306#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010307 wcnss_reset_intr();
10308#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010309
Jeff Johnsone7245742012-09-05 17:12:55 -070010310 return status;
10311}
10312
Mihir Shetee1093ba2014-01-21 20:13:32 +053010313/**---------------------------------------------------------------------------
10314 *
10315 * \brief wlan_hdd_init_channels
10316 *
10317 * This function is used to initialize the channel list in CSR
10318 *
10319 * This function is called from hdd_wlan_startup
10320 *
10321 * \param - pHddCtx: HDD context
10322 *
10323 * \return - VOS_STATUS_SUCCESS: Success
10324 * VOS_STATUS_E_FAULT: Failure reported by SME
10325
10326 * --------------------------------------------------------------------------*/
10327static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10328{
10329 eHalStatus status;
10330
10331 status = sme_InitChannels(pHddCtx->hHal);
10332 if (HAL_STATUS_SUCCESS(status))
10333 {
10334 return VOS_STATUS_SUCCESS;
10335 }
10336 else
10337 {
10338 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10339 __func__, status);
10340 return VOS_STATUS_E_FAULT;
10341 }
10342}
10343
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010344static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
10345{
10346 eHalStatus status;
10347
10348 status = sme_InitChannelsForCC(pHddCtx->hHal);
10349 if (HAL_STATUS_SUCCESS(status))
10350 {
10351 return VOS_STATUS_SUCCESS;
10352 }
10353 else
10354 {
10355 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10356 __func__, status);
10357 return VOS_STATUS_E_FAULT;
10358 }
10359}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010360/*
10361 * API to find if there is any STA or P2P-Client is connected
10362 */
10363VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10364{
10365 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10366}
Jeff Johnsone7245742012-09-05 17:12:55 -070010367
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010368int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10369{
10370 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10371 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010372 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010373
10374 pScanInfo = &pHddCtx->scan_info;
10375 if (pScanInfo->mScanPending)
10376 {
10377 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10378 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10379 eCSR_SCAN_ABORT_DEFAULT);
10380
10381 status = wait_for_completion_interruptible_timeout(
10382 &pScanInfo->abortscan_event_var,
10383 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010384 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010385 {
10386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010387 "%s: Timeout or Interrupt occurred while waiting for abort"
10388 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010389 return -ETIMEDOUT;
10390 }
10391 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010392 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010393}
10394
Jeff Johnson295189b2012-06-20 16:38:30 -070010395//Register the module init/exit functions
10396module_init(hdd_module_init);
10397module_exit(hdd_module_exit);
10398
10399MODULE_LICENSE("Dual BSD/GPL");
10400MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10401MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10402
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010403module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10404 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010405
Jeff Johnson76052702013-04-16 13:55:05 -070010406module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010407 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010408
10409module_param(enable_dfs_chan_scan, int,
10410 S_IRUSR | S_IRGRP | S_IROTH);
10411
10412module_param(enable_11d, int,
10413 S_IRUSR | S_IRGRP | S_IROTH);
10414
10415module_param(country_code, charp,
10416 S_IRUSR | S_IRGRP | S_IROTH);