blob: da71d0cbf26774b661eb0953816f3d7aec7c7779 [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
Atul Mittal1d722422014-03-19 11:15:07 +0530190/*
191 * Maximum buffer size used for returning the data back to user space
192 */
193#define WLAN_MAX_BUF_SIZE 1024
194#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700195
c_hpothu92367912014-05-01 15:18:17 +0530196//wait time for beacon miss rate.
197#define BCN_MISS_RATE_TIME 500
198
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800199#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700200static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700201#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700202/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700203static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700204
205//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700206static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
207static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
208static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
209void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800210void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700211
Jeff Johnson295189b2012-06-20 16:38:30 -0700212v_U16_t hdd_select_queue(struct net_device *dev,
213 struct sk_buff *skb);
214
215#ifdef WLAN_FEATURE_PACKET_FILTERING
216static void hdd_set_multicast_list(struct net_device *dev);
217#endif
218
219void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
220
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800221#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800222void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
223static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700224static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
225 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
226 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700227static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
228 tANI_U8 *pTargetApBssid,
229 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800230#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800231#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700232VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800233#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700234
Mihir Shetee1093ba2014-01-21 20:13:32 +0530235static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530236const char * hdd_device_modetoString(v_U8_t device_mode)
237{
238 switch(device_mode)
239 {
240 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
241 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
242 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
243 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
244 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
245 CASE_RETURN_STRING( WLAN_HDD_FTM );
246 CASE_RETURN_STRING( WLAN_HDD_IBSS );
247 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
248 default:
249 return "device_mode Unknown";
250 }
251}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530252
Jeff Johnson295189b2012-06-20 16:38:30 -0700253static int hdd_netdev_notifier_call(struct notifier_block * nb,
254 unsigned long state,
255 void *ndev)
256{
257 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700258 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700259 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700260#ifdef WLAN_BTAMP_FEATURE
261 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700262#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530263 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700264
265 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700266 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700267 (strncmp(dev->name, "p2p", 3)))
268 return NOTIFY_DONE;
269
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700271 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700272
Jeff Johnson27cee452013-03-27 11:10:24 -0700273 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800275 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 VOS_ASSERT(0);
277 return NOTIFY_DONE;
278 }
279
Jeff Johnson27cee452013-03-27 11:10:24 -0700280 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
281 if (NULL == pHddCtx)
282 {
283 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
284 VOS_ASSERT(0);
285 return NOTIFY_DONE;
286 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800287 if (pHddCtx->isLogpInProgress)
288 return NOTIFY_DONE;
289
Jeff Johnson27cee452013-03-27 11:10:24 -0700290
291 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
292 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700293
294 switch (state) {
295 case NETDEV_REGISTER:
296 break;
297
298 case NETDEV_UNREGISTER:
299 break;
300
301 case NETDEV_UP:
302 break;
303
304 case NETDEV_DOWN:
305 break;
306
307 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700308 if(TRUE == pAdapter->isLinkUpSvcNeeded)
309 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 break;
311
312 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530313 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530314 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530315 {
316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
317 "%s: Timeout occurred while waiting for abortscan %ld",
318 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 }
320 else
321 {
322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530323 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 }
325#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700326 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700327 status = WLANBAP_StopAmp();
328 if(VOS_STATUS_SUCCESS != status )
329 {
330 pHddCtx->isAmpAllowed = VOS_TRUE;
331 hddLog(VOS_TRACE_LEVEL_FATAL,
332 "%s: Failed to stop AMP", __func__);
333 }
334 else
335 {
336 //a state m/c implementation in PAL is TBD to avoid this delay
337 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700338 if ( pHddCtx->isAmpAllowed )
339 {
340 WLANBAP_DeregisterFromHCI();
341 pHddCtx->isAmpAllowed = VOS_FALSE;
342 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700343 }
344#endif //WLAN_BTAMP_FEATURE
345 break;
346
347 default:
348 break;
349 }
350
351 return NOTIFY_DONE;
352}
353
354struct notifier_block hdd_netdev_notifier = {
355 .notifier_call = hdd_netdev_notifier_call,
356};
357
358/*---------------------------------------------------------------------------
359 * Function definitions
360 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700361void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
362void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700363//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700364static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700365#ifndef MODULE
366/* current con_mode - used only for statically linked driver
367 * con_mode is changed by userspace to indicate a mode change which will
368 * result in calling the module exit and init functions. The module
369 * exit function will clean up based on the value of con_mode prior to it
370 * being changed by userspace. So curr_con_mode records the current con_mode
371 * for exit when con_mode becomes the next mode for init
372 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700373static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700374#endif
375
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800376/**---------------------------------------------------------------------------
377
378 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
379
380 Called immediately after the cfg.ini is read in order to configure
381 the desired trace levels.
382
383 \param - moduleId - module whose trace level is being configured
384 \param - bitmask - bitmask of log levels to be enabled
385
386 \return - void
387
388 --------------------------------------------------------------------------*/
389static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
390{
391 wpt_tracelevel level;
392
393 /* if the bitmask is the default value, then a bitmask was not
394 specified in cfg.ini, so leave the logging level alone (it
395 will remain at the "compiled in" default value) */
396 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
397 {
398 return;
399 }
400
401 /* a mask was specified. start by disabling all logging */
402 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
403
404 /* now cycle through the bitmask until all "set" bits are serviced */
405 level = VOS_TRACE_LEVEL_FATAL;
406 while (0 != bitmask)
407 {
408 if (bitmask & 1)
409 {
410 vos_trace_setValue(moduleId, level, 1);
411 }
412 level++;
413 bitmask >>= 1;
414 }
415}
416
417
Jeff Johnson295189b2012-06-20 16:38:30 -0700418/**---------------------------------------------------------------------------
419
420 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
421
422 Called immediately after the cfg.ini is read in order to configure
423 the desired trace levels in the WDI.
424
425 \param - moduleId - module whose trace level is being configured
426 \param - bitmask - bitmask of log levels to be enabled
427
428 \return - void
429
430 --------------------------------------------------------------------------*/
431static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
432{
433 wpt_tracelevel level;
434
435 /* if the bitmask is the default value, then a bitmask was not
436 specified in cfg.ini, so leave the logging level alone (it
437 will remain at the "compiled in" default value) */
438 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
439 {
440 return;
441 }
442
443 /* a mask was specified. start by disabling all logging */
444 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
445
446 /* now cycle through the bitmask until all "set" bits are serviced */
447 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
448 while (0 != bitmask)
449 {
450 if (bitmask & 1)
451 {
452 wpalTraceSetLevel(moduleId, level, 1);
453 }
454 level++;
455 bitmask >>= 1;
456 }
457}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530459/*
460 * FUNCTION: wlan_hdd_validate_context
461 * This function is used to check the HDD context
462 */
463int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
464{
465 ENTER();
466
467 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
468 {
469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
470 "%s: HDD context is Null", __func__);
471 return -ENODEV;
472 }
473
474 if (pHddCtx->isLogpInProgress)
475 {
476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
477 "%s: LOGP in Progress. Ignore!!!", __func__);
478 return -EAGAIN;
479 }
480
Mihir Shete18156292014-03-11 15:38:30 +0530481 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530482 {
483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
484 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
485 return -EAGAIN;
486 }
487 return 0;
488}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700489#ifdef CONFIG_ENABLE_LINUX_REG
490void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
491{
492 hdd_adapter_t *pAdapter = NULL;
493 hdd_station_ctx_t *pHddStaCtx = NULL;
494 eCsrPhyMode phyMode;
495 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530496
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700497 if (NULL == pHddCtx)
498 {
499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
500 "HDD Context is null !!");
501 return ;
502 }
503
504 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
505 if (NULL == pAdapter)
506 {
507 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
508 "pAdapter is null !!");
509 return ;
510 }
511
512 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
513 if (NULL == pHddStaCtx)
514 {
515 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
516 "pHddStaCtx is null !!");
517 return ;
518 }
519
520 cfg_param = pHddCtx->cfg_ini;
521 if (NULL == cfg_param)
522 {
523 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
524 "cfg_params not available !!");
525 return ;
526 }
527
528 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
529
530 if (!pHddCtx->isVHT80Allowed)
531 {
532 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
533 (eCSR_DOT11_MODE_11ac == phyMode) ||
534 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
537 "Setting phymode to 11n!!");
538 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
539 }
540 }
541 else
542 {
543 /*New country Supports 11ac as well resetting value back from .ini*/
544 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
545 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
546 return ;
547 }
548
549 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
550 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
551 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
552 {
553 VOS_STATUS vosStatus;
554
555 // need to issue a disconnect to CSR.
556 INIT_COMPLETION(pAdapter->disconnect_comp_var);
557 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
558 pAdapter->sessionId,
559 eCSR_DISCONNECT_REASON_UNSPECIFIED );
560
561 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530562 {
563 long ret;
564
565 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700566 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530567 if (0 >= ret)
568 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
569 ret);
570 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700571
572 }
573}
574#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530575void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
576{
577 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
578 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
579 hdd_config_t *cfg_param;
580 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530581 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530582
583 if (NULL == pHddCtx)
584 {
585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
586 "HDD Context is null !!");
587 return ;
588 }
589
590 cfg_param = pHddCtx->cfg_ini;
591
592 if (NULL == cfg_param)
593 {
594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
595 "cfg_params not available !!");
596 return ;
597 }
598
599 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
600
601 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
602 {
603 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
604 (eCSR_DOT11_MODE_11ac == phyMode) ||
605 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
606 {
607 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
608 "Setting phymode to 11n!!");
609 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
610 }
611 }
612 else
613 {
614 /*New country Supports 11ac as well resetting value back from .ini*/
615 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
616 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
617 return ;
618 }
619
620 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
621 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
622 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
623 {
624 VOS_STATUS vosStatus;
625
626 // need to issue a disconnect to CSR.
627 INIT_COMPLETION(pAdapter->disconnect_comp_var);
628 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
629 pAdapter->sessionId,
630 eCSR_DISCONNECT_REASON_UNSPECIFIED );
631
632 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530633 {
634 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530636 if (ret <= 0)
637 {
638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
639 "wait on disconnect_comp_var is failed %ld", ret);
640 }
641 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642
643 }
644}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700645#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530646
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700647void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
648{
649 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
650 hdd_config_t *cfg_param;
651
652 if (NULL == pHddCtx)
653 {
654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
655 "HDD Context is null !!");
656 return ;
657 }
658
659 cfg_param = pHddCtx->cfg_ini;
660
661 if (NULL == cfg_param)
662 {
663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
664 "cfg_params not available !!");
665 return ;
666 }
667
Agarwal Ashish738843c2014-09-25 12:27:56 +0530668 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
669 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700670 {
671 /*New country doesn't support DFS */
672 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
673 }
674 else
675 {
676 /*New country Supports DFS as well resetting value back from .ini*/
677 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
678 }
679
680}
681
Rajeev79dbe4c2013-10-05 11:03:42 +0530682#ifdef FEATURE_WLAN_BATCH_SCAN
683
684/**---------------------------------------------------------------------------
685
686 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
687 input string
688
689 This function extracts assigned integer from string in below format:
690 "STRING=10" : extracts integer 10 from this string
691
692 \param - pInPtr Pointer to input string
693 \param - base Base for string to int conversion(10 for decimal 16 for hex)
694 \param - pOutPtr Pointer to variable in which extracted integer needs to be
695 assigned
696 \param - pLastArg to tell whether it is last arguement in input string or
697 not
698
699 \return - NULL for failure cases
700 pointer to next arguement in input string for success cases
701 --------------------------------------------------------------------------*/
702static tANI_U8 *
703hdd_extract_assigned_int_from_str
704(
705 tANI_U8 *pInPtr,
706 tANI_U8 base,
707 tANI_U32 *pOutPtr,
708 tANI_U8 *pLastArg
709)
710{
711 int tempInt;
712 int v = 0;
713 char buf[32];
714 int val = 0;
715 *pLastArg = FALSE;
716
717 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
718 if (NULL == pInPtr)
719 {
720 return NULL;
721 }
722
723 pInPtr++;
724
725 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
726
727 val = sscanf(pInPtr, "%32s ", buf);
728 if (val < 0 && val > strlen(pInPtr))
729 {
730 return NULL;
731 }
732 pInPtr += val;
733 v = kstrtos32(buf, base, &tempInt);
734 if (v < 0)
735 {
736 return NULL;
737 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800738 if (tempInt < 0)
739 {
740 tempInt = 0;
741 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530742 *pOutPtr = tempInt;
743
744 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
745 if (NULL == pInPtr)
746 {
747 *pLastArg = TRUE;
748 return NULL;
749 }
750 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
751
752 return pInPtr;
753}
754
755/**---------------------------------------------------------------------------
756
757 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
758 input string
759
760 This function extracts assigned character from string in below format:
761 "STRING=A" : extracts char 'A' from this string
762
763 \param - pInPtr Pointer to input string
764 \param - pOutPtr Pointer to variable in which extracted char needs to be
765 assigned
766 \param - pLastArg to tell whether it is last arguement in input string or
767 not
768
769 \return - NULL for failure cases
770 pointer to next arguement in input string for success cases
771 --------------------------------------------------------------------------*/
772static tANI_U8 *
773hdd_extract_assigned_char_from_str
774(
775 tANI_U8 *pInPtr,
776 tANI_U8 *pOutPtr,
777 tANI_U8 *pLastArg
778)
779{
780 *pLastArg = FALSE;
781
782 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
783 if (NULL == pInPtr)
784 {
785 return NULL;
786 }
787
788 pInPtr++;
789
790 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
791
792 *pOutPtr = *pInPtr;
793
794 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
795 if (NULL == pInPtr)
796 {
797 *pLastArg = TRUE;
798 return NULL;
799 }
800 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
801
802 return pInPtr;
803}
804
805
806/**---------------------------------------------------------------------------
807
808 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
809
810 This function parses set batch scan command in below format:
811 WLS_BATCHING_SET <space> followed by below arguements
812 "SCANFREQ=XX" : Optional defaults to 30 sec
813 "MSCAN=XX" : Required number of scans to attempt to batch
814 "BESTN=XX" : Best Network (RSSI) defaults to 16
815 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
816 A. implies only 5 GHz , B. implies only 2.4GHz
817 "RTT=X" : optional defaults to 0
818 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
819 error
820
821 For example input commands:
822 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
823 translated into set batch scan with following parameters:
824 a) Frequence 60 seconds
825 b) Batch 10 scans together
826 c) Best RSSI to be 20
827 d) 5GHz band only
828 e) RTT is equal to 0
829
830 \param - pValue Pointer to input channel list
831 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
832
833 \return - 0 for success non-zero for failure
834
835 --------------------------------------------------------------------------*/
836static int
837hdd_parse_set_batchscan_command
838(
839 tANI_U8 *pValue,
840 tSirSetBatchScanReq *pHddSetBatchScanReq
841)
842{
843 tANI_U8 *inPtr = pValue;
844 tANI_U8 val = 0;
845 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800846 tANI_U32 nScanFreq;
847 tANI_U32 nMscan;
848 tANI_U32 nBestN;
849 tANI_U8 ucRfBand;
850 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800851 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530852
853 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800854 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
855 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
856 nRtt = 0;
857 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530858
859 /*go to space after WLS_BATCHING_SET command*/
860 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
861 /*no argument after the command*/
862 if (NULL == inPtr)
863 {
864 return -EINVAL;
865 }
866
867 /*no space after the command*/
868 else if (SPACE_ASCII_VALUE != *inPtr)
869 {
870 return -EINVAL;
871 }
872
873 /*removing empty spaces*/
874 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
875
876 /*no argument followed by spaces*/
877 if ('\0' == *inPtr)
878 {
879 return -EINVAL;
880 }
881
882 /*check and parse SCANFREQ*/
883 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
884 {
885 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800886 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800887
Rajeev Kumarc933d982013-11-18 20:04:20 -0800888 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800889 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800890 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800891 }
892
Rajeev79dbe4c2013-10-05 11:03:42 +0530893 if ( (NULL == inPtr) || (TRUE == lastArg))
894 {
895 return -EINVAL;
896 }
897 }
898
899 /*check and parse MSCAN*/
900 if ((strncmp(inPtr, "MSCAN", 5) == 0))
901 {
902 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800903 &nMscan, &lastArg);
904
905 if (0 == nMscan)
906 {
907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
908 "invalid MSCAN=%d", nMscan);
909 return -EINVAL;
910 }
911
Rajeev79dbe4c2013-10-05 11:03:42 +0530912 if (TRUE == lastArg)
913 {
914 goto done;
915 }
916 else if (NULL == inPtr)
917 {
918 return -EINVAL;
919 }
920 }
921 else
922 {
923 return -EINVAL;
924 }
925
926 /*check and parse BESTN*/
927 if ((strncmp(inPtr, "BESTN", 5) == 0))
928 {
929 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800930 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800931
Rajeev Kumarc933d982013-11-18 20:04:20 -0800932 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800933 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800934 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800935 }
936
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 if (TRUE == lastArg)
938 {
939 goto done;
940 }
941 else if (NULL == inPtr)
942 {
943 return -EINVAL;
944 }
945 }
946
947 /*check and parse CHANNEL*/
948 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
949 {
950 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800951
Rajeev79dbe4c2013-10-05 11:03:42 +0530952 if (('A' == val) || ('a' == val))
953 {
c_hpothuebf89732014-02-25 13:00:24 +0530954 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530955 }
956 else if (('B' == val) || ('b' == val))
957 {
c_hpothuebf89732014-02-25 13:00:24 +0530958 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530959 }
960 else
961 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800962 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
963 }
964
965 if (TRUE == lastArg)
966 {
967 goto done;
968 }
969 else if (NULL == inPtr)
970 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530971 return -EINVAL;
972 }
973 }
974
975 /*check and parse RTT*/
976 if ((strncmp(inPtr, "RTT", 3) == 0))
977 {
978 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800979 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530980 if (TRUE == lastArg)
981 {
982 goto done;
983 }
984 if (NULL == inPtr)
985 {
986 return -EINVAL;
987 }
988 }
989
990
991done:
992
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800993 pHddSetBatchScanReq->scanFrequency = nScanFreq;
994 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
995 pHddSetBatchScanReq->bestNetwork = nBestN;
996 pHddSetBatchScanReq->rfBand = ucRfBand;
997 pHddSetBatchScanReq->rtt = nRtt;
998
Rajeev79dbe4c2013-10-05 11:03:42 +0530999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1001 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1002 pHddSetBatchScanReq->scanFrequency,
1003 pHddSetBatchScanReq->numberOfScansToBatch,
1004 pHddSetBatchScanReq->bestNetwork,
1005 pHddSetBatchScanReq->rfBand,
1006 pHddSetBatchScanReq->rtt);
1007
1008 return 0;
1009}/*End of hdd_parse_set_batchscan_command*/
1010
1011/**---------------------------------------------------------------------------
1012
1013 \brief hdd_set_batch_scan_req_callback () - This function is called after
1014 receiving set batch scan response from FW and it saves set batch scan
1015 response data FW to HDD context and sets the completion event on
1016 which hdd_ioctl is waiting
1017
1018 \param - callbackContext Pointer to HDD adapter
1019 \param - pRsp Pointer to set batch scan response data received from FW
1020
1021 \return - nothing
1022
1023 --------------------------------------------------------------------------*/
1024static void hdd_set_batch_scan_req_callback
1025(
1026 void *callbackContext,
1027 tSirSetBatchScanRsp *pRsp
1028)
1029{
1030 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1031 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1032
1033 /*sanity check*/
1034 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1035 {
1036 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1037 "%s: Invalid pAdapter magic", __func__);
1038 VOS_ASSERT(0);
1039 return;
1040 }
1041 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1042
1043 /*save set batch scan response*/
1044 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1045
1046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1047 "Received set batch scan rsp from FW with nScansToBatch=%d",
1048 pHddSetBatchScanRsp->nScansToBatch);
1049
1050 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1051 complete(&pAdapter->hdd_set_batch_scan_req_var);
1052
1053 return;
1054}/*End of hdd_set_batch_scan_req_callback*/
1055
1056
1057/**---------------------------------------------------------------------------
1058
1059 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1060 info in hdd batch scan response queue
1061
1062 \param - pAdapter Pointer to hdd adapter
1063 \param - pAPMetaInfo Pointer to access point meta info
1064 \param - scanId scan ID of batch scan response
1065 \param - isLastAp tells whether AP is last AP in batch scan response or not
1066
1067 \return - nothing
1068
1069 --------------------------------------------------------------------------*/
1070static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1071 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1072{
1073 tHddBatchScanRsp *pHead;
1074 tHddBatchScanRsp *pNode;
1075 tHddBatchScanRsp *pPrev;
1076 tHddBatchScanRsp *pTemp;
1077 tANI_U8 ssidLen;
1078
1079 /*head of hdd batch scan response queue*/
1080 pHead = pAdapter->pBatchScanRsp;
1081
1082 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1083 if (NULL == pNode)
1084 {
1085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1086 "%s: Could not allocate memory", __func__);
1087 VOS_ASSERT(0);
1088 return;
1089 }
1090
1091 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1092 sizeof(pNode->ApInfo.bssid));
1093 ssidLen = strlen(pApMetaInfo->ssid);
1094 if (SIR_MAX_SSID_SIZE < ssidLen)
1095 {
1096 /*invalid scan result*/
1097 vos_mem_free(pNode);
1098 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1099 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1100 return;
1101 }
1102 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1103 /*null terminate ssid*/
1104 pNode->ApInfo.ssid[ssidLen] = '\0';
1105 pNode->ApInfo.ch = pApMetaInfo->ch;
1106 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1107 pNode->ApInfo.age = pApMetaInfo->timestamp;
1108 pNode->ApInfo.batchId = scanId;
1109 pNode->ApInfo.isLastAp = isLastAp;
1110
1111 pNode->pNext = NULL;
1112 if (NULL == pHead)
1113 {
1114 pAdapter->pBatchScanRsp = pNode;
1115 }
1116 else
1117 {
1118 pTemp = pHead;
1119 while (NULL != pTemp)
1120 {
1121 pPrev = pTemp;
1122 pTemp = pTemp->pNext;
1123 }
1124 pPrev->pNext = pNode;
1125 }
1126
1127 return;
1128}/*End of hdd_populate_batch_scan_rsp_queue*/
1129
1130/**---------------------------------------------------------------------------
1131
1132 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1133 receiving batch scan response indication from FW. It saves get batch scan
1134 response data in HDD batch scan response queue. This callback sets the
1135 completion event on which hdd_ioctl is waiting only after getting complete
1136 batch scan response data from FW
1137
1138 \param - callbackContext Pointer to HDD adapter
1139 \param - pRsp Pointer to get batch scan response data received from FW
1140
1141 \return - nothing
1142
1143 --------------------------------------------------------------------------*/
1144static void hdd_batch_scan_result_ind_callback
1145(
1146 void *callbackContext,
1147 void *pRsp
1148)
1149{
1150 v_BOOL_t isLastAp;
1151 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001152 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301153 tANI_U32 numberScanList;
1154 tANI_U32 nextScanListOffset;
1155 tANI_U32 nextApMetaInfoOffset;
1156 hdd_adapter_t* pAdapter;
1157 tpSirBatchScanList pScanList;
1158 tpSirBatchScanNetworkInfo pApMetaInfo;
1159 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1160 tSirSetBatchScanReq *pReq;
1161
1162 pAdapter = (hdd_adapter_t *)callbackContext;
1163 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001164 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301165 {
1166 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1167 "%s: Invalid pAdapter magic", __func__);
1168 VOS_ASSERT(0);
1169 return;
1170 }
1171
1172 /*initialize locals*/
1173 pReq = &pAdapter->hddSetBatchScanReq;
1174 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1175 isLastAp = FALSE;
1176 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001177 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301178 numberScanList = 0;
1179 nextScanListOffset = 0;
1180 nextApMetaInfoOffset = 0;
1181 pScanList = NULL;
1182 pApMetaInfo = NULL;
1183
1184 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1185 {
1186 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1187 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1188 isLastAp = TRUE;
1189 goto done;
1190 }
1191
1192 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "Batch scan rsp: numberScalList %d", numberScanList);
1195
1196 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1197 {
1198 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1199 "%s: numberScanList %d", __func__, numberScanList);
1200 isLastAp = TRUE;
1201 goto done;
1202 }
1203
1204 while (numberScanList)
1205 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001206 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301207 nextScanListOffset);
1208 if (NULL == pScanList)
1209 {
1210 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1211 "%s: pScanList is %p", __func__, pScanList);
1212 isLastAp = TRUE;
1213 goto done;
1214 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001215 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001217 "Batch scan rsp: numApMetaInfo %d scanId %d",
1218 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301219
1220 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1221 {
1222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1223 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1224 isLastAp = TRUE;
1225 goto done;
1226 }
1227
Rajeev Kumarce651e42013-10-21 18:57:15 -07001228 /*Initialize next AP meta info offset for next scan list*/
1229 nextApMetaInfoOffset = 0;
1230
Rajeev79dbe4c2013-10-05 11:03:42 +05301231 while (numApMetaInfo)
1232 {
1233 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1234 nextApMetaInfoOffset);
1235 if (NULL == pApMetaInfo)
1236 {
1237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1239 isLastAp = TRUE;
1240 goto done;
1241 }
1242 /*calculate AP age*/
1243 pApMetaInfo->timestamp =
1244 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1245
1246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001247 "%s: bssId "MAC_ADDRESS_STR
1248 " ch %d rssi %d timestamp %d", __func__,
1249 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1250 pApMetaInfo->ch, pApMetaInfo->rssi,
1251 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301252
1253 /*mark last AP in batch scan response*/
1254 if ((TRUE == pBatchScanRsp->isLastResult) &&
1255 (1 == numberScanList) && (1 == numApMetaInfo))
1256 {
1257 isLastAp = TRUE;
1258 }
1259
1260 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1261 /*store batch scan repsonse in hdd queue*/
1262 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1263 pScanList->scanId, isLastAp);
1264 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1265
1266 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1267 numApMetaInfo--;
1268 }
1269
Rajeev Kumarce651e42013-10-21 18:57:15 -07001270 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1271 + (sizeof(tSirBatchScanNetworkInfo)
1272 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301273 numberScanList--;
1274 }
1275
1276done:
1277
1278 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1279 requested from hdd_ioctl*/
1280 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1281 (TRUE == isLastAp))
1282 {
1283 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1284 complete(&pAdapter->hdd_get_batch_scan_req_var);
1285 }
1286
1287 return;
1288}/*End of hdd_batch_scan_result_ind_callback*/
1289
1290/**---------------------------------------------------------------------------
1291
1292 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1293 response as per batch scan FR request format by putting proper markers
1294
1295 \param - pDest pointer to destination buffer
1296 \param - cur_len current length
1297 \param - tot_len total remaining size which can be written to user space
1298 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1299 \param - pAdapter Pointer to HDD adapter
1300
1301 \return - ret no of characters written
1302
1303 --------------------------------------------------------------------------*/
1304static tANI_U32
1305hdd_format_batch_scan_rsp
1306(
1307 tANI_U8 *pDest,
1308 tANI_U32 cur_len,
1309 tANI_U32 tot_len,
1310 tHddBatchScanRsp *pApMetaInfo,
1311 hdd_adapter_t* pAdapter
1312)
1313{
1314 tANI_U32 ret = 0;
1315 tANI_U32 rem_len = 0;
1316 tANI_U8 temp_len = 0;
1317 tANI_U8 temp_total_len = 0;
1318 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1319 tANI_U8 *pTemp = temp;
1320
1321 /*Batch scan reponse needs to be returned to user space in
1322 following format:
1323 "scancount=X\n" where X is the number of scans in current batch
1324 batch
1325 "trunc\n" optional present if current scan truncated
1326 "bssid=XX:XX:XX:XX:XX:XX\n"
1327 "ssid=XXXX\n"
1328 "freq=X\n" frequency in Mhz
1329 "level=XX\n"
1330 "age=X\n" ms
1331 "dist=X\n" cm (-1 if not available)
1332 "errror=X\n" (-1if not available)
1333 "====\n" (end of ap marker)
1334 "####\n" (end of scan marker)
1335 "----\n" (end of results)*/
1336 /*send scan result in above format to user space based on
1337 available length*/
1338 /*The GET response may have more data than the driver can return in its
1339 buffer. In that case the buffer should be filled to the nearest complete
1340 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1341 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1342 The final buffer should end with "----\n"*/
1343
1344 /*sanity*/
1345 if (cur_len > tot_len)
1346 {
1347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1348 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1349 return 0;
1350 }
1351 else
1352 {
1353 rem_len = (tot_len - cur_len);
1354 }
1355
1356 /*end scan marker*/
1357 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1358 {
1359 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362 }
1363
1364 /*bssid*/
1365 temp_len = snprintf(pTemp, sizeof(temp),
1366 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1367 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1368 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1369 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1370 pTemp += temp_len;
1371 temp_total_len += temp_len;
1372
1373 /*ssid*/
1374 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1375 pApMetaInfo->ApInfo.ssid);
1376 pTemp += temp_len;
1377 temp_total_len += temp_len;
1378
1379 /*freq*/
1380 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001381 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301382 pTemp += temp_len;
1383 temp_total_len += temp_len;
1384
1385 /*level*/
1386 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1387 pApMetaInfo->ApInfo.rssi);
1388 pTemp += temp_len;
1389 temp_total_len += temp_len;
1390
1391 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001392 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301393 pApMetaInfo->ApInfo.age);
1394 pTemp += temp_len;
1395 temp_total_len += temp_len;
1396
1397 /*dist*/
1398 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1399 pTemp += temp_len;
1400 temp_total_len += temp_len;
1401
1402 /*error*/
1403 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1404 pTemp += temp_len;
1405 temp_total_len += temp_len;
1406
1407 /*end AP marker*/
1408 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1409 pTemp += temp_len;
1410 temp_total_len += temp_len;
1411
1412 /*last AP in batch scan response*/
1413 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1414 {
1415 /*end scan marker*/
1416 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1417 pTemp += temp_len;
1418 temp_total_len += temp_len;
1419
1420 /*end batch scan result marker*/
1421 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1422 pTemp += temp_len;
1423 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001424
Rajeev79dbe4c2013-10-05 11:03:42 +05301425 }
1426
1427 if (temp_total_len < rem_len)
1428 {
1429 ret = temp_total_len + 1;
1430 strlcpy(pDest, temp, ret);
1431 pAdapter->isTruncated = FALSE;
1432 }
1433 else
1434 {
1435 pAdapter->isTruncated = TRUE;
1436 if (rem_len >= strlen("%%%%"))
1437 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001438 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301439 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001440 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301441 {
1442 ret = 0;
1443 }
1444 }
1445
1446 return ret;
1447
1448}/*End of hdd_format_batch_scan_rsp*/
1449
1450/**---------------------------------------------------------------------------
1451
1452 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1453 buffer starting with head of hdd batch scan response queue
1454
1455 \param - pAdapter Pointer to HDD adapter
1456 \param - pDest Pointer to user data buffer
1457 \param - cur_len current offset in user buffer
1458 \param - rem_len remaining no of bytes in user buffer
1459
1460 \return - number of bytes written in user buffer
1461
1462 --------------------------------------------------------------------------*/
1463
1464tANI_U32 hdd_populate_user_batch_scan_rsp
1465(
1466 hdd_adapter_t* pAdapter,
1467 tANI_U8 *pDest,
1468 tANI_U32 cur_len,
1469 tANI_U32 rem_len
1470)
1471{
1472 tHddBatchScanRsp *pHead;
1473 tHddBatchScanRsp *pPrev;
1474 tANI_U32 len;
1475
Rajeev79dbe4c2013-10-05 11:03:42 +05301476 pAdapter->isTruncated = FALSE;
1477
1478 /*head of hdd batch scan response queue*/
1479 pHead = pAdapter->pBatchScanRsp;
1480 while (pHead)
1481 {
1482 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1483 pAdapter);
1484 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001485 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301486 cur_len += len;
1487 if(TRUE == pAdapter->isTruncated)
1488 {
1489 /*result is truncated return rest of scan rsp in next req*/
1490 cur_len = rem_len;
1491 break;
1492 }
1493 pPrev = pHead;
1494 pHead = pHead->pNext;
1495 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001496 if (TRUE == pPrev->ApInfo.isLastAp)
1497 {
1498 pAdapter->prev_batch_id = 0;
1499 }
1500 else
1501 {
1502 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1503 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301504 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001505 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301506 }
1507
1508 return cur_len;
1509}/*End of hdd_populate_user_batch_scan_rsp*/
1510
1511/**---------------------------------------------------------------------------
1512
1513 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1514 scan response data from HDD queue to user space
1515 It does following in detail:
1516 a) if HDD has enough data in its queue then it 1st copies data to user
1517 space and then send get batch scan indication message to FW. In this
1518 case it does not wait on any event and batch scan response data will
1519 be populated in HDD response queue in MC thread context after receiving
1520 indication from FW
1521 b) else send get batch scan indication message to FW and wait on an event
1522 which will be set once HDD receives complete batch scan response from
1523 FW and then this function returns batch scan response to user space
1524
1525 \param - pAdapter Pointer to HDD adapter
1526 \param - pPrivData Pointer to priv_data
1527
1528 \return - 0 for success -EFAULT for failure
1529
1530 --------------------------------------------------------------------------*/
1531
1532int hdd_return_batch_scan_rsp_to_user
1533(
1534 hdd_adapter_t* pAdapter,
1535 hdd_priv_data_t *pPrivData,
1536 tANI_U8 *command
1537)
1538{
1539 tANI_U8 *pDest;
1540 tANI_U32 count = 0;
1541 tANI_U32 len = 0;
1542 tANI_U32 cur_len = 0;
1543 tANI_U32 rem_len = 0;
1544 eHalStatus halStatus;
1545 unsigned long rc;
1546 tSirTriggerBatchScanResultInd *pReq;
1547
1548 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1549 pReq->param = 0;/*batch scan client*/
1550 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1551 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1552
1553 cur_len = pPrivData->used_len;
1554 if (pPrivData->total_len > pPrivData->used_len)
1555 {
1556 rem_len = pPrivData->total_len - pPrivData->used_len;
1557 }
1558 else
1559 {
1560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1561 "%s: Invalid user data buffer total_len %d used_len %d",
1562 __func__, pPrivData->total_len, pPrivData->used_len);
1563 return -EFAULT;
1564 }
1565
1566 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1567 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1568 cur_len, rem_len);
1569 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1570
1571 /*enough scan result available in cache to return to user space or
1572 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001573 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301574 {
1575 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1576 halStatus = sme_TriggerBatchScanResultInd(
1577 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1578 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1579 pAdapter);
1580 if ( eHAL_STATUS_SUCCESS == halStatus )
1581 {
1582 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1583 {
1584 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1585 rc = wait_for_completion_timeout(
1586 &pAdapter->hdd_get_batch_scan_req_var,
1587 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1588 if (0 == rc)
1589 {
1590 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1591 "%s: Timeout waiting to fetch batch scan rsp from fw",
1592 __func__);
1593 return -EFAULT;
1594 }
1595 }
1596
1597 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001598 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301599 pDest += len;
1600 cur_len += len;
1601
1602 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1603 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1604 cur_len, rem_len);
1605 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1606
1607 count = 0;
1608 len = (len - pPrivData->used_len);
1609 pDest = (command + pPrivData->used_len);
1610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001611 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301612 while(count < len)
1613 {
1614 printk("%c", *(pDest + count));
1615 count++;
1616 }
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1618 "%s: copy %d data to user buffer", __func__, len);
1619 if (copy_to_user(pPrivData->buf, pDest, len))
1620 {
1621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1622 "%s: failed to copy data to user buffer", __func__);
1623 return -EFAULT;
1624 }
1625 }
1626 else
1627 {
1628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1629 "sme_GetBatchScanScan returned failure halStatus %d",
1630 halStatus);
1631 return -EINVAL;
1632 }
1633 }
1634 else
1635 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301636 count = 0;
1637 len = (len - pPrivData->used_len);
1638 pDest = (command + pPrivData->used_len);
1639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001640 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301641 while(count < len)
1642 {
1643 printk("%c", *(pDest + count));
1644 count++;
1645 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301648 if (copy_to_user(pPrivData->buf, pDest, len))
1649 {
1650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1651 "%s: failed to copy data to user buffer", __func__);
1652 return -EFAULT;
1653 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301654 }
1655
1656 return 0;
1657} /*End of hdd_return_batch_scan_rsp_to_user*/
1658
Rajeev Kumar8b373292014-01-08 20:36:55 -08001659
1660/**---------------------------------------------------------------------------
1661
1662 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1663 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1664 WLS_BATCHING VERSION
1665 WLS_BATCHING SET
1666 WLS_BATCHING GET
1667 WLS_BATCHING STOP
1668
1669 \param - pAdapter Pointer to HDD adapter
1670 \param - pPrivdata Pointer to priv_data
1671 \param - command Pointer to command
1672
1673 \return - 0 for success -EFAULT for failure
1674
1675 --------------------------------------------------------------------------*/
1676
1677int hdd_handle_batch_scan_ioctl
1678(
1679 hdd_adapter_t *pAdapter,
1680 hdd_priv_data_t *pPrivdata,
1681 tANI_U8 *command
1682)
1683{
1684 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001685 hdd_context_t *pHddCtx;
1686
1687 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1688 ret = wlan_hdd_validate_context(pHddCtx);
1689 if (ret)
1690 {
1691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1692 "%s: HDD context is not valid!", __func__);
1693 goto exit;
1694 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001695
1696 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1697 {
1698 char extra[32];
1699 tANI_U8 len = 0;
1700 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1701
1702 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1703 {
1704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1705 "%s: Batch scan feature is not supported by FW", __func__);
1706 ret = -EINVAL;
1707 goto exit;
1708 }
1709
1710 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1711 version);
1712 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1713 {
1714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1715 "%s: failed to copy data to user buffer", __func__);
1716 ret = -EFAULT;
1717 goto exit;
1718 }
1719 ret = HDD_BATCH_SCAN_VERSION;
1720 }
1721 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1722 {
1723 int status;
1724 tANI_U8 *value = (command + 16);
1725 eHalStatus halStatus;
1726 unsigned long rc;
1727 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1728 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1729
1730 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1731 {
1732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1733 "%s: Batch scan feature is not supported by FW", __func__);
1734 ret = -EINVAL;
1735 goto exit;
1736 }
1737
1738 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1739 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1740 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1742 {
1743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301744 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001745 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301746 hdd_device_modetoString(pAdapter->device_mode),
1747 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001748 ret = -EINVAL;
1749 goto exit;
1750 }
1751
1752 status = hdd_parse_set_batchscan_command(value, pReq);
1753 if (status)
1754 {
1755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1756 "Invalid WLS_BATCHING SET command");
1757 ret = -EINVAL;
1758 goto exit;
1759 }
1760
1761
1762 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1763 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1764 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1765 pAdapter);
1766
1767 if ( eHAL_STATUS_SUCCESS == halStatus )
1768 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301769 char extra[32];
1770 tANI_U8 len = 0;
1771 tANI_U8 mScan = 0;
1772
Rajeev Kumar8b373292014-01-08 20:36:55 -08001773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1774 "sme_SetBatchScanReq returned success halStatus %d",
1775 halStatus);
1776 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1777 {
1778 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1779 rc = wait_for_completion_timeout(
1780 &pAdapter->hdd_set_batch_scan_req_var,
1781 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1782 if (0 == rc)
1783 {
1784 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1785 "%s: Timeout waiting for set batch scan to complete",
1786 __func__);
1787 ret = -EINVAL;
1788 goto exit;
1789 }
1790 }
1791 if ( !pRsp->nScansToBatch )
1792 {
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1794 "%s: Received set batch scan failure response from FW",
1795 __func__);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799 /*As per the Batch Scan Framework API we should return the MIN of
1800 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301801 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001802
1803 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1804
1805 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1806 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301807 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1808 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1809 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1810 {
1811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s: failed to copy MSCAN value to user buffer", __func__);
1813 ret = -EFAULT;
1814 goto exit;
1815 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001816 }
1817 else
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "sme_SetBatchScanReq returned failure halStatus %d",
1821 halStatus);
1822 ret = -EINVAL;
1823 goto exit;
1824 }
1825 }
1826 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1827 {
1828 eHalStatus halStatus;
1829 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1830 pInd->param = 0;
1831
1832 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1833 {
1834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1835 "%s: Batch scan feature is not supported by FW", __func__);
1836 ret = -EINVAL;
1837 goto exit;
1838 }
1839
1840 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1841 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001843 "Batch scan is not yet enabled batch scan state %d",
1844 pAdapter->batchScanState);
1845 ret = -EINVAL;
1846 goto exit;
1847 }
1848
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001849 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1850 hdd_deinit_batch_scan(pAdapter);
1851 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1852
Rajeev Kumar8b373292014-01-08 20:36:55 -08001853 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1854
1855 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1856 pAdapter->sessionId);
1857 if ( eHAL_STATUS_SUCCESS == halStatus )
1858 {
1859 ret = 0;
1860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1861 "sme_StopBatchScanInd returned success halStatus %d",
1862 halStatus);
1863 }
1864 else
1865 {
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1867 "sme_StopBatchScanInd returned failure halStatus %d",
1868 halStatus);
1869 ret = -EINVAL;
1870 goto exit;
1871 }
1872 }
1873 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1874 {
1875 tANI_U32 remain_len;
1876
1877 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1878 {
1879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1880 "%s: Batch scan feature is not supported by FW", __func__);
1881 ret = -EINVAL;
1882 goto exit;
1883 }
1884
1885 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1886 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001888 "Batch scan is not yet enabled could not return results"
1889 "Batch Scan state %d",
1890 pAdapter->batchScanState);
1891 ret = -EINVAL;
1892 goto exit;
1893 }
1894
1895 pPrivdata->used_len = 16;
1896 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1897 if (remain_len < pPrivdata->total_len)
1898 {
1899 /*Clear previous batch scan response data if any*/
1900 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1901 }
1902 else
1903 {
1904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1905 "Invalid total length from user space can't fetch batch"
1906 " scan response total_len %d used_len %d remain len %d",
1907 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1908 ret = -EINVAL;
1909 goto exit;
1910 }
1911 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1912 }
1913
1914exit:
1915
1916 return ret;
1917}
1918
1919
Rajeev79dbe4c2013-10-05 11:03:42 +05301920#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1921
c_hpothu92367912014-05-01 15:18:17 +05301922static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1923{
c_hpothu39eb1e32014-06-26 16:31:50 +05301924 bcnMissRateContext_t *pCBCtx;
1925
1926 if (NULL == data)
1927 {
1928 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1929 return;
1930 }
c_hpothu92367912014-05-01 15:18:17 +05301931
1932 /* there is a race condition that exists between this callback
1933 function and the caller since the caller could time out either
1934 before or while this code is executing. we use a spinlock to
1935 serialize these actions */
1936 spin_lock(&hdd_context_lock);
1937
c_hpothu39eb1e32014-06-26 16:31:50 +05301938 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301939 gbcnMissRate = -1;
1940
c_hpothu39eb1e32014-06-26 16:31:50 +05301941 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301942 {
1943 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301944 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301945 spin_unlock(&hdd_context_lock);
1946 return ;
1947 }
1948
1949 if (VOS_STATUS_SUCCESS == status)
1950 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301951 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301952 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301953 else
1954 {
1955 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1956 }
1957
c_hpothu92367912014-05-01 15:18:17 +05301958 complete(&(pCBCtx->completion));
1959 spin_unlock(&hdd_context_lock);
1960
1961 return;
1962}
1963
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301964static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1965{
1966 int ret = 0;
1967
1968 if (!pCfg || !command || !extra || !len)
1969 {
1970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1971 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1972 ret = -EINVAL;
1973 return ret;
1974 }
1975
1976 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1977 {
1978 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1979 (int)pCfg->nActiveMaxChnTime);
1980 return ret;
1981 }
1982 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1983 {
1984 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1985 (int)pCfg->nActiveMinChnTime);
1986 return ret;
1987 }
1988 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1989 {
1990 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1991 (int)pCfg->nPassiveMaxChnTime);
1992 return ret;
1993 }
1994 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1995 {
1996 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1997 (int)pCfg->nPassiveMinChnTime);
1998 return ret;
1999 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302000 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2001 {
2002 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2003 (int)pCfg->nActiveMaxChnTime);
2004 return ret;
2005 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302006 else
2007 {
2008 ret = -EINVAL;
2009 }
2010
2011 return ret;
2012}
2013
2014static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2015{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302016 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302017 hdd_config_t *pCfg;
2018 tANI_U8 *value = command;
2019 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302020 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302021
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302022 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2023 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302024 {
2025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2026 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2027 ret = -EINVAL;
2028 return ret;
2029 }
2030
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302031 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2032 sme_GetConfigParam(hHal, &smeConfig);
2033
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302034 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2035 {
2036 value = value + 24;
2037 temp = kstrtou32(value, 10, &val);
2038 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2039 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2040 {
2041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2042 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2043 ret = -EFAULT;
2044 return ret;
2045 }
2046 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302047 smeConfig.csrConfig.nActiveMaxChnTime = val;
2048 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302049 }
2050 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2051 {
2052 value = value + 24;
2053 temp = kstrtou32(value, 10, &val);
2054 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2055 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2056 {
2057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2058 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2059 ret = -EFAULT;
2060 return ret;
2061 }
2062 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302063 smeConfig.csrConfig.nActiveMinChnTime = val;
2064 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302065 }
2066 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2067 {
2068 value = value + 25;
2069 temp = kstrtou32(value, 10, &val);
2070 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2071 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2072 {
2073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2075 ret = -EFAULT;
2076 return ret;
2077 }
2078 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302079 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2080 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302081 }
2082 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2083 {
2084 value = value + 25;
2085 temp = kstrtou32(value, 10, &val);
2086 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2087 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2088 {
2089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2090 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2091 ret = -EFAULT;
2092 return ret;
2093 }
2094 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302095 smeConfig.csrConfig.nPassiveMinChnTime = val;
2096 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302097 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302098 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2099 {
2100 value = value + 13;
2101 temp = kstrtou32(value, 10, &val);
2102 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2103 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2104 {
2105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2106 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2107 ret = -EFAULT;
2108 return ret;
2109 }
2110 pCfg->nActiveMaxChnTime = val;
2111 smeConfig.csrConfig.nActiveMaxChnTime = val;
2112 sme_UpdateConfig(hHal, &smeConfig);
2113 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302114 else
2115 {
2116 ret = -EINVAL;
2117 }
2118
2119 return ret;
2120}
2121
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002122static int hdd_driver_command(hdd_adapter_t *pAdapter,
2123 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002124{
Jeff Johnson295189b2012-06-20 16:38:30 -07002125 hdd_priv_data_t priv_data;
2126 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302127 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2128 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002129 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302130 int status;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002131 /*
2132 * Note that valid pointers are provided by caller
2133 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002134
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002135 /* copy to local struct to avoid numerous changes to legacy code */
2136 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002137
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002138 if (priv_data.total_len <= 0 ||
2139 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002140 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002141 hddLog(VOS_TRACE_LEVEL_WARN,
2142 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2143 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002144 ret = -EINVAL;
2145 goto exit;
2146 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05302147 status = wlan_hdd_validate_context(pHddCtx);
2148 if (0 != status)
2149 {
2150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2151 "%s: HDD context is not valid", __func__);
2152 return status;
2153 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002154 /* Allocate +1 for '\0' */
2155 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002156 if (!command)
2157 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002158 hddLog(VOS_TRACE_LEVEL_ERROR,
2159 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002160 ret = -ENOMEM;
2161 goto exit;
2162 }
2163
2164 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2165 {
2166 ret = -EFAULT;
2167 goto exit;
2168 }
2169
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002170 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002171 command[priv_data.total_len] = '\0';
2172
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002173 /* at one time the following block of code was conditional. braces
2174 * have been retained to avoid re-indenting the legacy code
2175 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002176 {
2177 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2178
2179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002180 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002181
2182 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2183 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302184 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2185 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2186 pAdapter->sessionId, (unsigned)
2187 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2188 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2189 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2190 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2192 sizeof(tSirMacAddr)))
2193 {
2194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002195 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 ret = -EFAULT;
2197 }
2198 }
Amar Singhal0974e402013-02-12 14:27:46 -08002199 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 {
Amar Singhal0974e402013-02-12 14:27:46 -08002201 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002202
Jeff Johnson295189b2012-06-20 16:38:30 -07002203 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002204
2205 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002206 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002208 "%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 -07002209 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002210 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302211 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302212 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002213 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002214 }
Kiet Lamf040f472013-11-20 21:15:23 +05302215 else if(strncmp(command, "SETWMMPS", 8) == 0)
2216 {
2217 tANI_U8 *ptr = command;
2218 ret = hdd_wmmps_helper(pAdapter, ptr);
2219 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002220 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2221 {
2222 char *country_code;
2223
2224 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002225
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002226 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002227 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002228#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302229 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002230#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002231 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2232 (void *)(tSmeChangeCountryCallback)
2233 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302234 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002235 if (eHAL_STATUS_SUCCESS == ret)
2236 {
2237 ret = wait_for_completion_interruptible_timeout(
2238 &pAdapter->change_country_code,
2239 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2240 if (0 >= ret)
2241 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002242 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302243 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002244 }
2245 }
2246 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002247 {
2248 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002249 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002250 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002251 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002252
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002253 }
2254 /*
2255 command should be a string having format
2256 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2257 */
Amar Singhal0974e402013-02-12 14:27:46 -08002258 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002259 {
Amar Singhal0974e402013-02-12 14:27:46 -08002260 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002261
2262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002263 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002264
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002265 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002266 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002267 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2268 {
2269 int suspend = 0;
2270 tANI_U8 *ptr = (tANI_U8*)command + 15;
2271
2272 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302273 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2274 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2275 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002276 hdd_set_wlan_suspend_mode(suspend);
2277 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002278#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2279 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2280 {
2281 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002282 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002283 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2284 eHalStatus status = eHAL_STATUS_SUCCESS;
2285
2286 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2287 value = value + 15;
2288
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002289 /* Convert the value from ascii to integer */
2290 ret = kstrtos8(value, 10, &rssi);
2291 if (ret < 0)
2292 {
2293 /* If the input value is greater than max value of datatype, then also
2294 kstrtou8 fails */
2295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2296 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002297 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002298 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2299 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2300 ret = -EINVAL;
2301 goto exit;
2302 }
2303
Srinivas Girigowdade697412013-02-14 16:31:48 -08002304 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002305
Srinivas Girigowdade697412013-02-14 16:31:48 -08002306 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2307 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2308 {
2309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2310 "Neighbor lookup threshold value %d is out of range"
2311 " (Min: %d Max: %d)", lookUpThreshold,
2312 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2313 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2314 ret = -EINVAL;
2315 goto exit;
2316 }
2317
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302318 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2319 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2320 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2322 "%s: Received Command to Set Roam trigger"
2323 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2324
2325 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2326 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2327 if (eHAL_STATUS_SUCCESS != status)
2328 {
2329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2330 "%s: Failed to set roam trigger, try again", __func__);
2331 ret = -EPERM;
2332 goto exit;
2333 }
2334
2335 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302336 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2338 }
2339 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2340 {
2341 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2342 int rssi = (-1) * lookUpThreshold;
2343 char extra[32];
2344 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302345 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2346 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2347 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002348 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002349 if (copy_to_user(priv_data.buf, &extra, len + 1))
2350 {
2351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2352 "%s: failed to copy data to user buffer", __func__);
2353 ret = -EFAULT;
2354 goto exit;
2355 }
2356 }
2357 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2358 {
2359 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002360 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002361 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002362
Srinivas Girigowdade697412013-02-14 16:31:48 -08002363 /* input refresh period is in terms of seconds */
2364 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2365 value = value + 18;
2366 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002367 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368 if (ret < 0)
2369 {
2370 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002371 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002373 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002374 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002375 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2376 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 ret = -EINVAL;
2378 goto exit;
2379 }
2380
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002381 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2382 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002383 {
2384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002385 "Roam scan period value %d is out of range"
2386 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002387 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2388 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002389 ret = -EINVAL;
2390 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302391 }
2392 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2393 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2394 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002395 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002396
2397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2398 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002399 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002400
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002401 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2402 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002403 }
2404 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2405 {
2406 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2407 char extra[32];
2408 tANI_U8 len = 0;
2409
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302410 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2411 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2412 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002413 len = scnprintf(extra, sizeof(extra), "%s %d",
2414 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002415 /* Returned value is in units of seconds */
2416 if (copy_to_user(priv_data.buf, &extra, len + 1))
2417 {
2418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2419 "%s: failed to copy data to user buffer", __func__);
2420 ret = -EFAULT;
2421 goto exit;
2422 }
2423 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002424 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2425 {
2426 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002429
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002430 /* input refresh period is in terms of seconds */
2431 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2432 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002433
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002435 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 if (ret < 0)
2437 {
2438 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002439 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002441 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002442 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002443 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2444 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2445 ret = -EINVAL;
2446 goto exit;
2447 }
2448
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002449 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2450 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2451 {
2452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2453 "Neighbor scan results refresh period value %d is out of range"
2454 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2455 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2456 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2457 ret = -EINVAL;
2458 goto exit;
2459 }
2460 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2461
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2463 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002464 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002465
2466 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2467 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2468 }
2469 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2470 {
2471 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2472 char extra[32];
2473 tANI_U8 len = 0;
2474
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002475 len = scnprintf(extra, sizeof(extra), "%s %d",
2476 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002477 /* Returned value is in units of seconds */
2478 if (copy_to_user(priv_data.buf, &extra, len + 1))
2479 {
2480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2481 "%s: failed to copy data to user buffer", __func__);
2482 ret = -EFAULT;
2483 goto exit;
2484 }
2485 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002486#ifdef FEATURE_WLAN_LFR
2487 /* SETROAMMODE */
2488 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2489 {
2490 tANI_U8 *value = command;
2491 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2492
2493 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2494 value = value + SIZE_OF_SETROAMMODE + 1;
2495
2496 /* Convert the value from ascii to integer */
2497 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2498 if (ret < 0)
2499 {
2500 /* If the input value is greater than max value of datatype, then also
2501 kstrtou8 fails */
2502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2503 "%s: kstrtou8 failed range [%d - %d]", __func__,
2504 CFG_LFR_FEATURE_ENABLED_MIN,
2505 CFG_LFR_FEATURE_ENABLED_MAX);
2506 ret = -EINVAL;
2507 goto exit;
2508 }
2509 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2510 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "Roam Mode value %d is out of range"
2514 " (Min: %d Max: %d)", roamMode,
2515 CFG_LFR_FEATURE_ENABLED_MIN,
2516 CFG_LFR_FEATURE_ENABLED_MAX);
2517 ret = -EINVAL;
2518 goto exit;
2519 }
2520
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2522 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2523 /*
2524 * Note that
2525 * SETROAMMODE 0 is to enable LFR while
2526 * SETROAMMODE 1 is to disable LFR, but
2527 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2528 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2529 */
2530 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2531 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2532 else
2533 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2534
2535 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2536 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2537 }
2538 /* GETROAMMODE */
2539 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2540 {
2541 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2542 char extra[32];
2543 tANI_U8 len = 0;
2544
2545 /*
2546 * roamMode value shall be inverted because the sementics is different.
2547 */
2548 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2549 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2550 else
2551 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2552
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002553 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002554 if (copy_to_user(priv_data.buf, &extra, len + 1))
2555 {
2556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2557 "%s: failed to copy data to user buffer", __func__);
2558 ret = -EFAULT;
2559 goto exit;
2560 }
2561 }
2562#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002563#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002564#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002565 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2566 {
2567 tANI_U8 *value = command;
2568 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2569
2570 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2571 value = value + 13;
2572 /* Convert the value from ascii to integer */
2573 ret = kstrtou8(value, 10, &roamRssiDiff);
2574 if (ret < 0)
2575 {
2576 /* If the input value is greater than max value of datatype, then also
2577 kstrtou8 fails */
2578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2579 "%s: kstrtou8 failed range [%d - %d]", __func__,
2580 CFG_ROAM_RSSI_DIFF_MIN,
2581 CFG_ROAM_RSSI_DIFF_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
2586 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2587 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2588 {
2589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2590 "Roam rssi diff value %d is out of range"
2591 " (Min: %d Max: %d)", roamRssiDiff,
2592 CFG_ROAM_RSSI_DIFF_MIN,
2593 CFG_ROAM_RSSI_DIFF_MAX);
2594 ret = -EINVAL;
2595 goto exit;
2596 }
2597
2598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2599 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2600
2601 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2602 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2603 }
2604 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2605 {
2606 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2607 char extra[32];
2608 tANI_U8 len = 0;
2609
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302610 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2611 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2612 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002613 len = scnprintf(extra, sizeof(extra), "%s %d",
2614 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002615 if (copy_to_user(priv_data.buf, &extra, len + 1))
2616 {
2617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2618 "%s: failed to copy data to user buffer", __func__);
2619 ret = -EFAULT;
2620 goto exit;
2621 }
2622 }
2623#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002624#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002625 else if (strncmp(command, "GETBAND", 7) == 0)
2626 {
2627 int band = -1;
2628 char extra[32];
2629 tANI_U8 len = 0;
2630 hdd_getBand_helper(pHddCtx, &band);
2631
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302632 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2633 TRACE_CODE_HDD_GETBAND_IOCTL,
2634 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002635 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002636 if (copy_to_user(priv_data.buf, &extra, len + 1))
2637 {
2638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2639 "%s: failed to copy data to user buffer", __func__);
2640 ret = -EFAULT;
2641 goto exit;
2642 }
2643 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002644 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2645 {
2646 tANI_U8 *value = command;
2647 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2648 tANI_U8 numChannels = 0;
2649 eHalStatus status = eHAL_STATUS_SUCCESS;
2650
2651 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2652 if (eHAL_STATUS_SUCCESS != status)
2653 {
2654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2655 "%s: Failed to parse channel list information", __func__);
2656 ret = -EINVAL;
2657 goto exit;
2658 }
2659
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302660 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2661 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2662 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002663 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2664 {
2665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2666 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2667 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2668 ret = -EINVAL;
2669 goto exit;
2670 }
2671 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2672 numChannels);
2673 if (eHAL_STATUS_SUCCESS != status)
2674 {
2675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2676 "%s: Failed to update channel list information", __func__);
2677 ret = -EINVAL;
2678 goto exit;
2679 }
2680 }
2681 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2682 {
2683 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2684 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002685 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002686 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002687 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002688
2689 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2690 ChannelList, &numChannels ))
2691 {
2692 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2693 "%s: failed to get roam scan channel list", __func__);
2694 ret = -EFAULT;
2695 goto exit;
2696 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302697 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2698 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2699 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002700 /* output channel list is of the format
2701 [Number of roam scan channels][Channel1][Channel2]... */
2702 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002703 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002704 for (j = 0; (j < numChannels); j++)
2705 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002706 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2707 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002708 }
2709
2710 if (copy_to_user(priv_data.buf, &extra, len + 1))
2711 {
2712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2713 "%s: failed to copy data to user buffer", __func__);
2714 ret = -EFAULT;
2715 goto exit;
2716 }
2717 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002718 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2719 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002720 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002721 char extra[32];
2722 tANI_U8 len = 0;
2723
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002724 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002725 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002726 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002727 hdd_is_okc_mode_enabled(pHddCtx) &&
2728 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2729 {
2730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002731 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002732 " hence this operation is not permitted!", __func__);
2733 ret = -EPERM;
2734 goto exit;
2735 }
2736
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002737 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002738 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002739 if (copy_to_user(priv_data.buf, &extra, len + 1))
2740 {
2741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2742 "%s: failed to copy data to user buffer", __func__);
2743 ret = -EFAULT;
2744 goto exit;
2745 }
2746 }
2747 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2748 {
2749 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2750 char extra[32];
2751 tANI_U8 len = 0;
2752
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002753 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002754 then this operation is not permitted (return FAILURE) */
2755 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002756 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002757 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2758 {
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002760 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002761 " hence this operation is not permitted!", __func__);
2762 ret = -EPERM;
2763 goto exit;
2764 }
2765
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002766 len = scnprintf(extra, sizeof(extra), "%s %d",
2767 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002768 if (copy_to_user(priv_data.buf, &extra, len + 1))
2769 {
2770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: failed to copy data to user buffer", __func__);
2772 ret = -EFAULT;
2773 goto exit;
2774 }
2775 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002776 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002777 {
2778 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2779 char extra[32];
2780 tANI_U8 len = 0;
2781
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002782 len = scnprintf(extra, sizeof(extra), "%s %d",
2783 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002784 if (copy_to_user(priv_data.buf, &extra, len + 1))
2785 {
2786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2787 "%s: failed to copy data to user buffer", __func__);
2788 ret = -EFAULT;
2789 goto exit;
2790 }
2791 }
2792 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2793 {
2794 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2795 char extra[32];
2796 tANI_U8 len = 0;
2797
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002798 len = scnprintf(extra, sizeof(extra), "%s %d",
2799 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002800 if (copy_to_user(priv_data.buf, &extra, len + 1))
2801 {
2802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2803 "%s: failed to copy data to user buffer", __func__);
2804 ret = -EFAULT;
2805 goto exit;
2806 }
2807 }
2808 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2809 {
2810 tANI_U8 *value = command;
2811 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2812
2813 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2814 value = value + 26;
2815 /* Convert the value from ascii to integer */
2816 ret = kstrtou8(value, 10, &minTime);
2817 if (ret < 0)
2818 {
2819 /* If the input value is greater than max value of datatype, then also
2820 kstrtou8 fails */
2821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2822 "%s: kstrtou8 failed range [%d - %d]", __func__,
2823 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2824 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2825 ret = -EINVAL;
2826 goto exit;
2827 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002828 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2829 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2830 {
2831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2832 "scan min channel time value %d is out of range"
2833 " (Min: %d Max: %d)", minTime,
2834 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2835 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
2839
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302840 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2841 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2842 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2844 "%s: Received Command to change channel min time = %d", __func__, minTime);
2845
2846 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2847 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2848 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002849 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2850 {
2851 tANI_U8 *value = command;
2852 tANI_U8 channel = 0;
2853 tANI_U8 dwellTime = 0;
2854 tANI_U8 bufLen = 0;
2855 tANI_U8 *buf = NULL;
2856 tSirMacAddr targetApBssid;
2857 eHalStatus status = eHAL_STATUS_SUCCESS;
2858 struct ieee80211_channel chan;
2859 tANI_U8 finalLen = 0;
2860 tANI_U8 *finalBuf = NULL;
2861 tANI_U8 temp = 0;
2862 u64 cookie;
2863 hdd_station_ctx_t *pHddStaCtx = NULL;
2864 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2865
2866 /* if not associated, no need to send action frame */
2867 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2868 {
2869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2870 ret = -EINVAL;
2871 goto exit;
2872 }
2873
2874 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2875 &dwellTime, &buf, &bufLen);
2876 if (eHAL_STATUS_SUCCESS != status)
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2879 "%s: Failed to parse send action frame data", __func__);
2880 ret = -EINVAL;
2881 goto exit;
2882 }
2883
2884 /* if the target bssid is different from currently associated AP,
2885 then no need to send action frame */
2886 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2887 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2888 {
2889 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2890 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002891 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002892 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002893 goto exit;
2894 }
2895
2896 /* if the channel number is different from operating channel then
2897 no need to send action frame */
2898 if (channel != pHddStaCtx->conn_info.operationChannel)
2899 {
2900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2901 "%s: channel(%d) is different from operating channel(%d)",
2902 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2903 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002904 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002905 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002906 goto exit;
2907 }
2908 chan.center_freq = sme_ChnToFreq(channel);
2909
2910 finalLen = bufLen + 24;
2911 finalBuf = vos_mem_malloc(finalLen);
2912 if (NULL == finalBuf)
2913 {
2914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2915 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002916 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002917 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002918 goto exit;
2919 }
2920 vos_mem_zero(finalBuf, finalLen);
2921
2922 /* Fill subtype */
2923 temp = SIR_MAC_MGMT_ACTION << 4;
2924 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2925
2926 /* Fill type */
2927 temp = SIR_MAC_MGMT_FRAME;
2928 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2929
2930 /* Fill destination address (bssid of the AP) */
2931 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2932
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002933 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002934 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2935
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002936 /* Fill BSSID (AP mac address) */
2937 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002938
2939 /* Fill received buffer from 24th address */
2940 vos_mem_copy(finalBuf + 24, buf, bufLen);
2941
Jeff Johnson11c33152013-04-16 17:52:40 -07002942 /* done with the parsed buffer */
2943 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002944 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002945
DARAM SUDHA39eede62014-02-12 11:16:40 +05302946 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002947#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2948 &(pAdapter->wdev),
2949#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002950 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002951#endif
2952 &chan, 0,
2953#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2954 NL80211_CHAN_HT20, 1,
2955#endif
2956 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002957 1, &cookie );
2958 vos_mem_free(finalBuf);
2959 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002960 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2961 {
2962 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2963 char extra[32];
2964 tANI_U8 len = 0;
2965
2966 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002967 len = scnprintf(extra, sizeof(extra), "%s %d",
2968 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302969 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2970 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2971 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002972 if (copy_to_user(priv_data.buf, &extra, len + 1))
2973 {
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2975 "%s: failed to copy data to user buffer", __func__);
2976 ret = -EFAULT;
2977 goto exit;
2978 }
2979 }
2980 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2981 {
2982 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002983 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002984
2985 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2986 value = value + 19;
2987 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002988 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002989 if (ret < 0)
2990 {
2991 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002992 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002994 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002995 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2996 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2997 ret = -EINVAL;
2998 goto exit;
2999 }
3000
3001 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
3002 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
3003 {
3004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3005 "lfr mode value %d is out of range"
3006 " (Min: %d Max: %d)", maxTime,
3007 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3008 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3009 ret = -EINVAL;
3010 goto exit;
3011 }
3012
3013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3014 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3015
3016 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3017 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3018 }
3019 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3020 {
3021 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3022 char extra[32];
3023 tANI_U8 len = 0;
3024
3025 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003026 len = scnprintf(extra, sizeof(extra), "%s %d",
3027 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003028 if (copy_to_user(priv_data.buf, &extra, len + 1))
3029 {
3030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3031 "%s: failed to copy data to user buffer", __func__);
3032 ret = -EFAULT;
3033 goto exit;
3034 }
3035 }
3036 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3037 {
3038 tANI_U8 *value = command;
3039 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3040
3041 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3042 value = value + 16;
3043 /* Convert the value from ascii to integer */
3044 ret = kstrtou16(value, 10, &val);
3045 if (ret < 0)
3046 {
3047 /* If the input value is greater than max value of datatype, then also
3048 kstrtou16 fails */
3049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3050 "%s: kstrtou16 failed range [%d - %d]", __func__,
3051 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3052 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3053 ret = -EINVAL;
3054 goto exit;
3055 }
3056
3057 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3058 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3059 {
3060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3061 "scan home time value %d is out of range"
3062 " (Min: %d Max: %d)", val,
3063 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3064 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3065 ret = -EINVAL;
3066 goto exit;
3067 }
3068
3069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3070 "%s: Received Command to change scan home time = %d", __func__, val);
3071
3072 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3073 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3074 }
3075 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3076 {
3077 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3078 char extra[32];
3079 tANI_U8 len = 0;
3080
3081 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003082 len = scnprintf(extra, sizeof(extra), "%s %d",
3083 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003084 if (copy_to_user(priv_data.buf, &extra, len + 1))
3085 {
3086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3087 "%s: failed to copy data to user buffer", __func__);
3088 ret = -EFAULT;
3089 goto exit;
3090 }
3091 }
3092 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3093 {
3094 tANI_U8 *value = command;
3095 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3096
3097 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3098 value = value + 17;
3099 /* Convert the value from ascii to integer */
3100 ret = kstrtou8(value, 10, &val);
3101 if (ret < 0)
3102 {
3103 /* If the input value is greater than max value of datatype, then also
3104 kstrtou8 fails */
3105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3106 "%s: kstrtou8 failed range [%d - %d]", __func__,
3107 CFG_ROAM_INTRA_BAND_MIN,
3108 CFG_ROAM_INTRA_BAND_MAX);
3109 ret = -EINVAL;
3110 goto exit;
3111 }
3112
3113 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3114 (val > CFG_ROAM_INTRA_BAND_MAX))
3115 {
3116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3117 "intra band mode value %d is out of range"
3118 " (Min: %d Max: %d)", val,
3119 CFG_ROAM_INTRA_BAND_MIN,
3120 CFG_ROAM_INTRA_BAND_MAX);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3125 "%s: Received Command to change intra band = %d", __func__, val);
3126
3127 pHddCtx->cfg_ini->nRoamIntraBand = val;
3128 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3129 }
3130 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3131 {
3132 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3133 char extra[32];
3134 tANI_U8 len = 0;
3135
3136 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003137 len = scnprintf(extra, sizeof(extra), "%s %d",
3138 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003139 if (copy_to_user(priv_data.buf, &extra, len + 1))
3140 {
3141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3142 "%s: failed to copy data to user buffer", __func__);
3143 ret = -EFAULT;
3144 goto exit;
3145 }
3146 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003147 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3148 {
3149 tANI_U8 *value = command;
3150 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3151
3152 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3153 value = value + 15;
3154 /* Convert the value from ascii to integer */
3155 ret = kstrtou8(value, 10, &nProbes);
3156 if (ret < 0)
3157 {
3158 /* If the input value is greater than max value of datatype, then also
3159 kstrtou8 fails */
3160 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3161 "%s: kstrtou8 failed range [%d - %d]", __func__,
3162 CFG_ROAM_SCAN_N_PROBES_MIN,
3163 CFG_ROAM_SCAN_N_PROBES_MAX);
3164 ret = -EINVAL;
3165 goto exit;
3166 }
3167
3168 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3169 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3170 {
3171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3172 "NProbes value %d is out of range"
3173 " (Min: %d Max: %d)", nProbes,
3174 CFG_ROAM_SCAN_N_PROBES_MIN,
3175 CFG_ROAM_SCAN_N_PROBES_MAX);
3176 ret = -EINVAL;
3177 goto exit;
3178 }
3179
3180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3181 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3182
3183 pHddCtx->cfg_ini->nProbes = nProbes;
3184 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3185 }
3186 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3187 {
3188 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3189 char extra[32];
3190 tANI_U8 len = 0;
3191
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003192 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003193 if (copy_to_user(priv_data.buf, &extra, len + 1))
3194 {
3195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3196 "%s: failed to copy data to user buffer", __func__);
3197 ret = -EFAULT;
3198 goto exit;
3199 }
3200 }
3201 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3202 {
3203 tANI_U8 *value = command;
3204 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3205
3206 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3207 /* input value is in units of msec */
3208 value = value + 20;
3209 /* Convert the value from ascii to integer */
3210 ret = kstrtou16(value, 10, &homeAwayTime);
3211 if (ret < 0)
3212 {
3213 /* If the input value is greater than max value of datatype, then also
3214 kstrtou8 fails */
3215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "%s: kstrtou8 failed range [%d - %d]", __func__,
3217 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3218 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3219 ret = -EINVAL;
3220 goto exit;
3221 }
3222
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003223 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3224 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3225 {
3226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3227 "homeAwayTime value %d is out of range"
3228 " (Min: %d Max: %d)", homeAwayTime,
3229 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3230 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3231 ret = -EINVAL;
3232 goto exit;
3233 }
3234
3235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3236 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003237 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3238 {
3239 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3240 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3241 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003242 }
3243 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3244 {
3245 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3246 char extra[32];
3247 tANI_U8 len = 0;
3248
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003249 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003250 if (copy_to_user(priv_data.buf, &extra, len + 1))
3251 {
3252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3253 "%s: failed to copy data to user buffer", __func__);
3254 ret = -EFAULT;
3255 goto exit;
3256 }
3257 }
3258 else if (strncmp(command, "REASSOC", 7) == 0)
3259 {
3260 tANI_U8 *value = command;
3261 tANI_U8 channel = 0;
3262 tSirMacAddr targetApBssid;
3263 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003264#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3265 tCsrHandoffRequest handoffInfo;
3266#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003267 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003268 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3269
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003270 /* if not associated, no need to proceed with reassoc */
3271 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3272 {
3273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3274 ret = -EINVAL;
3275 goto exit;
3276 }
3277
3278 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3279 if (eHAL_STATUS_SUCCESS != status)
3280 {
3281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "%s: Failed to parse reassoc command data", __func__);
3283 ret = -EINVAL;
3284 goto exit;
3285 }
3286
3287 /* if the target bssid is same as currently associated AP,
3288 then no need to proceed with reassoc */
3289 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3290 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3291 {
3292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3293 ret = -EINVAL;
3294 goto exit;
3295 }
3296
3297 /* Check channel number is a valid channel number */
3298 if(VOS_STATUS_SUCCESS !=
3299 wlan_hdd_validate_operation_channel(pAdapter, channel))
3300 {
3301 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003302 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003303 return -EINVAL;
3304 }
3305
3306 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003307#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3308 handoffInfo.channel = channel;
3309 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3310 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3311#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003312 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003313 else if (strncmp(command, "SETWESMODE", 10) == 0)
3314 {
3315 tANI_U8 *value = command;
3316 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3317
3318 /* Move pointer to ahead of SETWESMODE<delimiter> */
3319 value = value + 11;
3320 /* Convert the value from ascii to integer */
3321 ret = kstrtou8(value, 10, &wesMode);
3322 if (ret < 0)
3323 {
3324 /* If the input value is greater than max value of datatype, then also
3325 kstrtou8 fails */
3326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3327 "%s: kstrtou8 failed range [%d - %d]", __func__,
3328 CFG_ENABLE_WES_MODE_NAME_MIN,
3329 CFG_ENABLE_WES_MODE_NAME_MAX);
3330 ret = -EINVAL;
3331 goto exit;
3332 }
3333
3334 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3335 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3336 {
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3338 "WES Mode value %d is out of range"
3339 " (Min: %d Max: %d)", wesMode,
3340 CFG_ENABLE_WES_MODE_NAME_MIN,
3341 CFG_ENABLE_WES_MODE_NAME_MAX);
3342 ret = -EINVAL;
3343 goto exit;
3344 }
3345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3346 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3347
3348 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3349 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3350 }
3351 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3352 {
3353 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3354 char extra[32];
3355 tANI_U8 len = 0;
3356
Arif Hussain826d9412013-11-12 16:44:54 -08003357 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003358 if (copy_to_user(priv_data.buf, &extra, len + 1))
3359 {
3360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3361 "%s: failed to copy data to user buffer", __func__);
3362 ret = -EFAULT;
3363 goto exit;
3364 }
3365 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003366#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003367#ifdef FEATURE_WLAN_LFR
3368 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3369 {
3370 tANI_U8 *value = command;
3371 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3372
3373 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3374 value = value + 12;
3375 /* Convert the value from ascii to integer */
3376 ret = kstrtou8(value, 10, &lfrMode);
3377 if (ret < 0)
3378 {
3379 /* If the input value is greater than max value of datatype, then also
3380 kstrtou8 fails */
3381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3382 "%s: kstrtou8 failed range [%d - %d]", __func__,
3383 CFG_LFR_FEATURE_ENABLED_MIN,
3384 CFG_LFR_FEATURE_ENABLED_MAX);
3385 ret = -EINVAL;
3386 goto exit;
3387 }
3388
3389 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3390 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3391 {
3392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3393 "lfr mode value %d is out of range"
3394 " (Min: %d Max: %d)", lfrMode,
3395 CFG_LFR_FEATURE_ENABLED_MIN,
3396 CFG_LFR_FEATURE_ENABLED_MAX);
3397 ret = -EINVAL;
3398 goto exit;
3399 }
3400
3401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3402 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3403
3404 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3405 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3406 }
3407#endif
3408#ifdef WLAN_FEATURE_VOWIFI_11R
3409 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3410 {
3411 tANI_U8 *value = command;
3412 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3413
3414 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3415 value = value + 18;
3416 /* Convert the value from ascii to integer */
3417 ret = kstrtou8(value, 10, &ft);
3418 if (ret < 0)
3419 {
3420 /* If the input value is greater than max value of datatype, then also
3421 kstrtou8 fails */
3422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3423 "%s: kstrtou8 failed range [%d - %d]", __func__,
3424 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3425 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3426 ret = -EINVAL;
3427 goto exit;
3428 }
3429
3430 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3431 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3432 {
3433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3434 "ft mode value %d is out of range"
3435 " (Min: %d Max: %d)", ft,
3436 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3437 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3438 ret = -EINVAL;
3439 goto exit;
3440 }
3441
3442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3443 "%s: Received Command to change ft mode = %d", __func__, ft);
3444
3445 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3446 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3447 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303448
3449 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3450 {
3451 tANI_U8 *value = command;
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303452 tANI_U8 channel = 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303453 tSirMacAddr targetApBssid;
3454 tANI_U8 trigger = 0;
3455 eHalStatus status = eHAL_STATUS_SUCCESS;
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303456 tHalHandle hHal;
3457 v_U32_t roamId = 0;
3458 tCsrRoamModifyProfileFields modProfileFields;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303459 hdd_station_ctx_t *pHddStaCtx = NULL;
3460 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303461 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303462
3463 /* if not associated, no need to proceed with reassoc */
3464 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3465 {
3466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3467 ret = -EINVAL;
3468 goto exit;
3469 }
3470
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303471 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303472 if (eHAL_STATUS_SUCCESS != status)
3473 {
3474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3475 "%s: Failed to parse reassoc command data", __func__);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 /* if the target bssid is same as currently associated AP,
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303481 issue reassoc to same AP */
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303482 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3483 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3484 {
3485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3486 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3487 __func__);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303488 sme_GetModifyProfileFields(hHal, pAdapter->sessionId,
3489 &modProfileFields);
3490 sme_RoamReassoc(hHal, pAdapter->sessionId,
3491 NULL, modProfileFields, &roamId, 1);
3492 return 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303493 }
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05303494
3495 /* Check channel number is a valid channel number */
3496 if(VOS_STATUS_SUCCESS !=
3497 wlan_hdd_validate_operation_channel(pAdapter, channel))
3498 {
3499 hddLog(VOS_TRACE_LEVEL_ERROR,
3500 "%s: Invalid Channel [%d]", __func__, channel);
3501 return -EINVAL;
3502 }
3503
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303504 trigger = eSME_ROAM_TRIGGER_SCAN;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303505
3506 /* Proceed with scan/roam */
3507 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3508 &targetApBssid[0],
3509 (tSmeFastRoamTrigger)(trigger));
3510 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003511#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003512#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003513 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3514 {
3515 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003516 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003517
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003518 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003519 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003520 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003521 hdd_is_okc_mode_enabled(pHddCtx) &&
3522 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3523 {
3524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003525 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003526 " hence this operation is not permitted!", __func__);
3527 ret = -EPERM;
3528 goto exit;
3529 }
3530
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003531 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3532 value = value + 11;
3533 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003534 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003535 if (ret < 0)
3536 {
3537 /* If the input value is greater than max value of datatype, then also
3538 kstrtou8 fails */
3539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3540 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003541 CFG_ESE_FEATURE_ENABLED_MIN,
3542 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003543 ret = -EINVAL;
3544 goto exit;
3545 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003546 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3547 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003548 {
3549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003550 "Ese mode value %d is out of range"
3551 " (Min: %d Max: %d)", eseMode,
3552 CFG_ESE_FEATURE_ENABLED_MIN,
3553 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003554 ret = -EINVAL;
3555 goto exit;
3556 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003558 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003559
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003560 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3561 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003562 }
3563#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003564 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3565 {
3566 tANI_U8 *value = command;
3567 tANI_BOOLEAN roamScanControl = 0;
3568
3569 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3570 value = value + 19;
3571 /* Convert the value from ascii to integer */
3572 ret = kstrtou8(value, 10, &roamScanControl);
3573 if (ret < 0)
3574 {
3575 /* If the input value is greater than max value of datatype, then also
3576 kstrtou8 fails */
3577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3578 "%s: kstrtou8 failed ", __func__);
3579 ret = -EINVAL;
3580 goto exit;
3581 }
3582
3583 if (0 != roamScanControl)
3584 {
3585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3586 "roam scan control invalid value = %d",
3587 roamScanControl);
3588 ret = -EINVAL;
3589 goto exit;
3590 }
3591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3592 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3593
3594 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3595 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003596#ifdef FEATURE_WLAN_OKC
3597 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3598 {
3599 tANI_U8 *value = command;
3600 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3601
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003602 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003603 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003604 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003605 hdd_is_okc_mode_enabled(pHddCtx) &&
3606 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3607 {
3608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003609 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003610 " hence this operation is not permitted!", __func__);
3611 ret = -EPERM;
3612 goto exit;
3613 }
3614
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003615 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3616 value = value + 11;
3617 /* Convert the value from ascii to integer */
3618 ret = kstrtou8(value, 10, &okcMode);
3619 if (ret < 0)
3620 {
3621 /* If the input value is greater than max value of datatype, then also
3622 kstrtou8 fails */
3623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3624 "%s: kstrtou8 failed range [%d - %d]", __func__,
3625 CFG_OKC_FEATURE_ENABLED_MIN,
3626 CFG_OKC_FEATURE_ENABLED_MAX);
3627 ret = -EINVAL;
3628 goto exit;
3629 }
3630
3631 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3632 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3633 {
3634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3635 "Okc mode value %d is out of range"
3636 " (Min: %d Max: %d)", okcMode,
3637 CFG_OKC_FEATURE_ENABLED_MIN,
3638 CFG_OKC_FEATURE_ENABLED_MAX);
3639 ret = -EINVAL;
3640 goto exit;
3641 }
3642
3643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3644 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3645
3646 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3647 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003648#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003649 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3650 {
3651 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3652 char extra[32];
3653 tANI_U8 len = 0;
3654
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003655 len = scnprintf(extra, sizeof(extra), "%s %d",
3656 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003657 if (copy_to_user(priv_data.buf, &extra, len + 1))
3658 {
3659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3660 "%s: failed to copy data to user buffer", __func__);
3661 ret = -EFAULT;
3662 goto exit;
3663 }
3664 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303665#ifdef WLAN_FEATURE_PACKET_FILTERING
3666 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3667 {
3668 tANI_U8 filterType = 0;
3669 tANI_U8 *value = command;
3670
3671 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3672 value = value + 22;
3673
3674 /* Convert the value from ascii to integer */
3675 ret = kstrtou8(value, 10, &filterType);
3676 if (ret < 0)
3677 {
3678 /* If the input value is greater than max value of datatype,
3679 * then also kstrtou8 fails
3680 */
3681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3682 "%s: kstrtou8 failed range ", __func__);
3683 ret = -EINVAL;
3684 goto exit;
3685 }
3686
3687 if (filterType != 0 && filterType != 1)
3688 {
3689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3690 "%s: Accepted Values are 0 and 1 ", __func__);
3691 ret = -EINVAL;
3692 goto exit;
3693 }
3694 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3695 pAdapter->sessionId);
3696 }
3697#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303698 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3699 {
Kiet Lamad161252014-07-22 11:23:32 -07003700 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303701 int ret;
3702
Kiet Lamad161252014-07-22 11:23:32 -07003703 dhcpPhase = command + 11;
3704 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303705 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003707 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303708
3709 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003710
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303711 ret = wlan_hdd_scan_abort(pAdapter);
3712 if (ret < 0)
3713 {
3714 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3715 FL("failed to abort existing scan %d"), ret);
3716 }
3717
Kiet Lamad161252014-07-22 11:23:32 -07003718 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3719 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303720 }
Kiet Lamad161252014-07-22 11:23:32 -07003721 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303722 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003724 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303725
3726 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003727
3728 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3729 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303730 }
3731 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003732 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3733 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3735 FL("making default scan to ACTIVE"));
3736 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003737 }
3738 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3739 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3741 FL("making default scan to PASSIVE"));
3742 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003743 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303744 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3745 {
3746 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3747 char extra[32];
3748 tANI_U8 len = 0;
3749
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303750 memset(extra, 0, sizeof(extra));
3751 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3752 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303753 {
3754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3755 "%s: failed to copy data to user buffer", __func__);
3756 ret = -EFAULT;
3757 goto exit;
3758 }
3759 ret = len;
3760 }
3761 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3762 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303763 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303764 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003765 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3766 {
3767 tANI_U8 filterType = 0;
3768 tANI_U8 *value;
3769 value = command + 9;
3770
3771 /* Convert the value from ascii to integer */
3772 ret = kstrtou8(value, 10, &filterType);
3773 if (ret < 0)
3774 {
3775 /* If the input value is greater than max value of datatype,
3776 * then also kstrtou8 fails
3777 */
3778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3779 "%s: kstrtou8 failed range ", __func__);
3780 ret = -EINVAL;
3781 goto exit;
3782 }
3783 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3784 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3785 {
3786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3787 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3788 " 2-Sink ", __func__);
3789 ret = -EINVAL;
3790 goto exit;
3791 }
3792 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3793 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303794 pScanInfo = &pHddCtx->scan_info;
3795 if (filterType && pScanInfo != NULL &&
3796 pHddCtx->scan_info.mScanPending)
3797 {
3798 /*Miracast Session started. Abort Scan */
3799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3800 "%s, Aborting Scan For Miracast",__func__);
3801 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
3802 eCSR_SCAN_ABORT_DEFAULT);
3803 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003804 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303805 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003806 }
Leo Chang614d2072013-08-22 14:59:44 -07003807 else if (strncmp(command, "SETMCRATE", 9) == 0)
3808 {
Leo Chang614d2072013-08-22 14:59:44 -07003809 tANI_U8 *value = command;
3810 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003811 tSirRateUpdateInd *rateUpdate;
3812 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003813
3814 /* Only valid for SAP mode */
3815 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3816 {
3817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3818 "%s: SAP mode is not running", __func__);
3819 ret = -EFAULT;
3820 goto exit;
3821 }
3822
3823 /* Move pointer to ahead of SETMCRATE<delimiter> */
3824 /* input value is in units of hundred kbps */
3825 value = value + 10;
3826 /* Convert the value from ascii to integer, decimal base */
3827 ret = kstrtouint(value, 10, &targetRate);
3828
Leo Chang1f98cbd2013-10-17 15:03:52 -07003829 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3830 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003831 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003832 hddLog(VOS_TRACE_LEVEL_ERROR,
3833 "%s: SETMCRATE indication alloc fail", __func__);
3834 ret = -EFAULT;
3835 goto exit;
3836 }
3837 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3838
3839 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3840 "MC Target rate %d", targetRate);
3841 /* Ignore unicast */
3842 rateUpdate->ucastDataRate = -1;
3843 rateUpdate->mcastDataRate24GHz = targetRate;
3844 rateUpdate->mcastDataRate5GHz = targetRate;
3845 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3846 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3847 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3848 if (eHAL_STATUS_SUCCESS != status)
3849 {
3850 hddLog(VOS_TRACE_LEVEL_ERROR,
3851 "%s: SET_MC_RATE failed", __func__);
3852 vos_mem_free(rateUpdate);
3853 ret = -EFAULT;
3854 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003855 }
3856 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303857#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003858 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303859 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003860 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303861 }
3862#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003863#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003864 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3865 {
3866 tANI_U8 *value = command;
3867 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3868 tANI_U8 numChannels = 0;
3869 eHalStatus status = eHAL_STATUS_SUCCESS;
3870
3871 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3872 if (eHAL_STATUS_SUCCESS != status)
3873 {
3874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3875 "%s: Failed to parse channel list information", __func__);
3876 ret = -EINVAL;
3877 goto exit;
3878 }
3879
3880 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3881 {
3882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3883 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3884 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3885 ret = -EINVAL;
3886 goto exit;
3887 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003888 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003889 ChannelList,
3890 numChannels);
3891 if (eHAL_STATUS_SUCCESS != status)
3892 {
3893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3894 "%s: Failed to update channel list information", __func__);
3895 ret = -EINVAL;
3896 goto exit;
3897 }
3898 }
3899 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3900 {
3901 tANI_U8 *value = command;
3902 char extra[128] = {0};
3903 int len = 0;
3904 tANI_U8 tid = 0;
3905 hdd_station_ctx_t *pHddStaCtx = NULL;
3906 tAniTrafStrmMetrics tsmMetrics;
3907 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3908
3909 /* if not associated, return error */
3910 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3911 {
3912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3913 ret = -EINVAL;
3914 goto exit;
3915 }
3916
3917 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3918 value = value + 12;
3919 /* Convert the value from ascii to integer */
3920 ret = kstrtou8(value, 10, &tid);
3921 if (ret < 0)
3922 {
3923 /* If the input value is greater than max value of datatype, then also
3924 kstrtou8 fails */
3925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3926 "%s: kstrtou8 failed range [%d - %d]", __func__,
3927 TID_MIN_VALUE,
3928 TID_MAX_VALUE);
3929 ret = -EINVAL;
3930 goto exit;
3931 }
3932
3933 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3934 {
3935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3936 "tid value %d is out of range"
3937 " (Min: %d Max: %d)", tid,
3938 TID_MIN_VALUE,
3939 TID_MAX_VALUE);
3940 ret = -EINVAL;
3941 goto exit;
3942 }
3943
3944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3945 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3946
3947 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3948 {
3949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3950 "%s: failed to get tsm stats", __func__);
3951 ret = -EFAULT;
3952 goto exit;
3953 }
3954
3955 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3956 "UplinkPktQueueDly(%d)\n"
3957 "UplinkPktQueueDlyHist[0](%d)\n"
3958 "UplinkPktQueueDlyHist[1](%d)\n"
3959 "UplinkPktQueueDlyHist[2](%d)\n"
3960 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303961 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003962 "UplinkPktLoss(%d)\n"
3963 "UplinkPktCount(%d)\n"
3964 "RoamingCount(%d)\n"
3965 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3966 tsmMetrics.UplinkPktQueueDlyHist[0],
3967 tsmMetrics.UplinkPktQueueDlyHist[1],
3968 tsmMetrics.UplinkPktQueueDlyHist[2],
3969 tsmMetrics.UplinkPktQueueDlyHist[3],
3970 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3971 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3972
3973 /* Output TSM stats is of the format
3974 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3975 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003976 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003977 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3978 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3979 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3980 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3981 tsmMetrics.RoamingDly);
3982
3983 if (copy_to_user(priv_data.buf, &extra, len + 1))
3984 {
3985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3986 "%s: failed to copy data to user buffer", __func__);
3987 ret = -EFAULT;
3988 goto exit;
3989 }
3990 }
3991 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3992 {
3993 tANI_U8 *value = command;
3994 tANI_U8 *cckmIe = NULL;
3995 tANI_U8 cckmIeLen = 0;
3996 eHalStatus status = eHAL_STATUS_SUCCESS;
3997
3998 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3999 if (eHAL_STATUS_SUCCESS != status)
4000 {
4001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4002 "%s: Failed to parse cckm ie data", __func__);
4003 ret = -EINVAL;
4004 goto exit;
4005 }
4006
4007 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
4008 {
4009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4010 "%s: CCKM Ie input length is more than max[%d]", __func__,
4011 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004012 vos_mem_free(cckmIe);
4013 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004014 ret = -EINVAL;
4015 goto exit;
4016 }
4017 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004018 vos_mem_free(cckmIe);
4019 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004020 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004021 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
4022 {
4023 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004024 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004025 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004026
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004027 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004028 if (eHAL_STATUS_SUCCESS != status)
4029 {
4030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004031 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004032 ret = -EINVAL;
4033 goto exit;
4034 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004035 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4036 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4037 hdd_indicateEseBcnReportNoResults (pAdapter,
4038 eseBcnReq.bcnReq[0].measurementToken,
4039 0x02, //BIT(1) set for measurement done
4040 0); // no BSS
4041 goto exit;
4042 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004043
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004044 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4045 if (eHAL_STATUS_SUCCESS != status)
4046 {
4047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4048 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4049 ret = -EINVAL;
4050 goto exit;
4051 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004052 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004053#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304054 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4055 {
4056 eHalStatus status;
4057 char buf[32], len;
4058 long waitRet;
4059 bcnMissRateContext_t getBcnMissRateCtx;
4060
4061 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4062
4063 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4064 {
4065 hddLog(VOS_TRACE_LEVEL_WARN,
4066 FL("GETBCNMISSRATE: STA is not in connected state"));
4067 ret = -1;
4068 goto exit;
4069 }
4070
4071 init_completion(&(getBcnMissRateCtx.completion));
4072 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4073
4074 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4075 pAdapter->sessionId,
4076 (void *)getBcnMissRateCB,
4077 (void *)(&getBcnMissRateCtx));
4078 if( eHAL_STATUS_SUCCESS != status)
4079 {
4080 hddLog(VOS_TRACE_LEVEL_INFO,
4081 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4082 ret = -EINVAL;
4083 goto exit;
4084 }
4085
4086 waitRet = wait_for_completion_interruptible_timeout
4087 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4088 if(waitRet <= 0)
4089 {
4090 hddLog(VOS_TRACE_LEVEL_ERROR,
4091 FL("failed to wait on bcnMissRateComp %d"), ret);
4092
4093 //Make magic number to zero so that callback is not called.
4094 spin_lock(&hdd_context_lock);
4095 getBcnMissRateCtx.magic = 0x0;
4096 spin_unlock(&hdd_context_lock);
4097 ret = -EINVAL;
4098 goto exit;
4099 }
4100
4101 hddLog(VOS_TRACE_LEVEL_INFO,
4102 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4103
4104 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4105 if (copy_to_user(priv_data.buf, &buf, len + 1))
4106 {
4107 hddLog(VOS_TRACE_LEVEL_ERROR,
4108 "%s: failed to copy data to user buffer", __func__);
4109 ret = -EFAULT;
4110 goto exit;
4111 }
4112 ret = len;
4113 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304114#ifdef FEATURE_WLAN_TDLS
4115 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4116 tANI_U8 *value = command;
4117 int set_value;
4118 /* Move pointer to ahead of TDLSOFFCH*/
4119 value += 26;
4120 sscanf(value, "%d", &set_value);
4121 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4122 "%s: Tdls offchannel offset:%d",
4123 __func__, set_value);
4124 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4125 if (ret < 0)
4126 {
4127 ret = -EINVAL;
4128 goto exit;
4129 }
4130
4131 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4132 tANI_U8 *value = command;
4133 int set_value;
4134 /* Move pointer to ahead of tdlsoffchnmode*/
4135 value += 18;
4136 sscanf(value, "%d", &set_value);
4137 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4138 "%s: Tdls offchannel mode:%d",
4139 __func__, set_value);
4140 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4141 if (ret < 0)
4142 {
4143 ret = -EINVAL;
4144 goto exit;
4145 }
4146 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4147 tANI_U8 *value = command;
4148 int set_value;
4149 /* Move pointer to ahead of TDLSOFFCH*/
4150 value += 14;
4151 sscanf(value, "%d", &set_value);
4152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4153 "%s: Tdls offchannel num: %d",
4154 __func__, set_value);
4155 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4156 if (ret < 0)
4157 {
4158 ret = -EINVAL;
4159 goto exit;
4160 }
4161 }
4162#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004163 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304164 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4165 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4166 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004167 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4168 __func__, command);
4169 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004170 }
4171exit:
4172 if (command)
4173 {
4174 kfree(command);
4175 }
4176 return ret;
4177}
4178
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004179#ifdef CONFIG_COMPAT
4180static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4181{
4182 struct {
4183 compat_uptr_t buf;
4184 int used_len;
4185 int total_len;
4186 } compat_priv_data;
4187 hdd_priv_data_t priv_data;
4188 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004189
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004190 /*
4191 * Note that pAdapter and ifr have already been verified by caller,
4192 * and HDD context has also been validated
4193 */
4194 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4195 sizeof(compat_priv_data))) {
4196 ret = -EFAULT;
4197 goto exit;
4198 }
4199 priv_data.buf = compat_ptr(compat_priv_data.buf);
4200 priv_data.used_len = compat_priv_data.used_len;
4201 priv_data.total_len = compat_priv_data.total_len;
4202 ret = hdd_driver_command(pAdapter, &priv_data);
4203 exit:
4204 return ret;
4205}
4206#else /* CONFIG_COMPAT */
4207static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4208{
4209 /* will never be invoked */
4210 return 0;
4211}
4212#endif /* CONFIG_COMPAT */
4213
4214static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4215{
4216 hdd_priv_data_t priv_data;
4217 int ret = 0;
4218
4219 /*
4220 * Note that pAdapter and ifr have already been verified by caller,
4221 * and HDD context has also been validated
4222 */
4223 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4224 ret = -EFAULT;
4225 } else {
4226 ret = hdd_driver_command(pAdapter, &priv_data);
4227 }
4228 return ret;
4229}
4230
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304231int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004232{
4233 hdd_adapter_t *pAdapter;
4234 hdd_context_t *pHddCtx;
4235 int ret;
4236
4237 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4238 if (NULL == pAdapter) {
4239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4240 "%s: HDD adapter context is Null", __func__);
4241 ret = -ENODEV;
4242 goto exit;
4243 }
4244 if (dev != pAdapter->dev) {
4245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4246 "%s: HDD adapter/dev inconsistency", __func__);
4247 ret = -ENODEV;
4248 goto exit;
4249 }
4250
4251 if ((!ifr) || (!ifr->ifr_data)) {
4252 ret = -EINVAL;
4253 goto exit;
4254 }
4255
4256 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4257 ret = wlan_hdd_validate_context(pHddCtx);
4258 if (ret) {
Mahesh A Saptasagar5b16d0a2014-11-03 17:55:29 +05304259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004260 "%s: invalid context", __func__);
4261 ret = -EBUSY;
4262 goto exit;
4263 }
4264
4265 switch (cmd) {
4266 case (SIOCDEVPRIVATE + 1):
4267 if (is_compat_task())
4268 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4269 else
4270 ret = hdd_driver_ioctl(pAdapter, ifr);
4271 break;
4272 default:
4273 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4274 __func__, cmd);
4275 ret = -EINVAL;
4276 break;
4277 }
4278 exit:
4279 return ret;
4280}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004281
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304282int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4283{
4284 int ret;
4285
4286 vos_ssr_protect(__func__);
4287 ret = __hdd_ioctl(dev, ifr, cmd);
4288 vos_ssr_unprotect(__func__);
4289
4290 return ret;
4291}
4292
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004293#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004294/**---------------------------------------------------------------------------
4295
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004296 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004297
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004298 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004299 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4300 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4301 <space>Scan Mode N<space>Meas Duration N
4302 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4303 then take N.
4304 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4305 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4306 This function does not take care of removing duplicate channels from the list
4307
4308 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004309 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004310
4311 \return - 0 for success non-zero for failure
4312
4313 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004314static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4315 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004316{
4317 tANI_U8 *inPtr = pValue;
4318 int tempInt = 0;
4319 int j = 0, i = 0, v = 0;
4320 char buf[32];
4321
4322 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4323 /*no argument after the command*/
4324 if (NULL == inPtr)
4325 {
4326 return -EINVAL;
4327 }
4328 /*no space after the command*/
4329 else if (SPACE_ASCII_VALUE != *inPtr)
4330 {
4331 return -EINVAL;
4332 }
4333
4334 /*removing empty spaces*/
4335 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4336
4337 /*no argument followed by spaces*/
4338 if ('\0' == *inPtr) return -EINVAL;
4339
4340 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004341 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004342 if (1 != v) return -EINVAL;
4343
4344 v = kstrtos32(buf, 10, &tempInt);
4345 if ( v < 0) return -EINVAL;
4346
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004347 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004348
4349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004350 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004351
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004352 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004353 {
4354 for (i = 0; i < 4; i++)
4355 {
4356 /*inPtr pointing to the beginning of first space after number of ie fields*/
4357 inPtr = strpbrk( inPtr, " " );
4358 /*no ie data after the number of ie fields argument*/
4359 if (NULL == inPtr) return -EINVAL;
4360
4361 /*removing empty space*/
4362 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4363
4364 /*no ie data after the number of ie fields argument and spaces*/
4365 if ( '\0' == *inPtr ) return -EINVAL;
4366
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004367 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004368 if (1 != v) return -EINVAL;
4369
4370 v = kstrtos32(buf, 10, &tempInt);
4371 if (v < 0) return -EINVAL;
4372
4373 switch (i)
4374 {
4375 case 0: /* Measurement token */
4376 if (tempInt <= 0)
4377 {
4378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4379 "Invalid Measurement Token(%d)", tempInt);
4380 return -EINVAL;
4381 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004382 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004383 break;
4384
4385 case 1: /* Channel number */
4386 if ((tempInt <= 0) ||
4387 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4388 {
4389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4390 "Invalid Channel Number(%d)", tempInt);
4391 return -EINVAL;
4392 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004393 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004394 break;
4395
4396 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004397 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004398 {
4399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4400 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4401 return -EINVAL;
4402 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004403 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004404 break;
4405
4406 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004407 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4408 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004409 {
4410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4411 "Invalid Measurement Duration(%d)", tempInt);
4412 return -EINVAL;
4413 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004414 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004415 break;
4416 }
4417 }
4418 }
4419
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004420 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004421 {
4422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304423 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004424 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004425 pEseBcnReq->bcnReq[j].measurementToken,
4426 pEseBcnReq->bcnReq[j].channel,
4427 pEseBcnReq->bcnReq[j].scanMode,
4428 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004429 }
4430
4431 return VOS_STATUS_SUCCESS;
4432}
4433
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004434static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4435{
4436 struct statsContext *pStatsContext = NULL;
4437 hdd_adapter_t *pAdapter = NULL;
4438
4439 if (NULL == pContext)
4440 {
4441 hddLog(VOS_TRACE_LEVEL_ERROR,
4442 "%s: Bad param, pContext [%p]",
4443 __func__, pContext);
4444 return;
4445 }
4446
Jeff Johnson72a40512013-12-19 10:14:15 -08004447 /* there is a race condition that exists between this callback
4448 function and the caller since the caller could time out either
4449 before or while this code is executing. we use a spinlock to
4450 serialize these actions */
4451 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004452
4453 pStatsContext = pContext;
4454 pAdapter = pStatsContext->pAdapter;
4455 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4456 {
4457 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004458 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004459 hddLog(VOS_TRACE_LEVEL_WARN,
4460 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4461 __func__, pAdapter, pStatsContext->magic);
4462 return;
4463 }
4464
Jeff Johnson72a40512013-12-19 10:14:15 -08004465 /* context is valid so caller is still waiting */
4466
4467 /* paranoia: invalidate the magic */
4468 pStatsContext->magic = 0;
4469
4470 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004471 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4472 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4473 tsmMetrics.UplinkPktQueueDlyHist,
4474 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4475 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4476 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4477 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4478 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4479 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4480 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4481
Jeff Johnson72a40512013-12-19 10:14:15 -08004482 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004483 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004484
4485 /* serialization is complete */
4486 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004487}
4488
4489
4490
4491static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4492 tAniTrafStrmMetrics* pTsmMetrics)
4493{
4494 hdd_station_ctx_t *pHddStaCtx = NULL;
4495 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004496 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004497 long lrc;
4498 struct statsContext context;
4499 hdd_context_t *pHddCtx = NULL;
4500
4501 if (NULL == pAdapter)
4502 {
4503 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4504 return VOS_STATUS_E_FAULT;
4505 }
4506
4507 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4508 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4509
4510 /* we are connected prepare our callback context */
4511 init_completion(&context.completion);
4512 context.pAdapter = pAdapter;
4513 context.magic = STATS_CONTEXT_MAGIC;
4514
4515 /* query tsm stats */
4516 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4517 pHddStaCtx->conn_info.staId[ 0 ],
4518 pHddStaCtx->conn_info.bssId,
4519 &context, pHddCtx->pvosContext, tid);
4520
4521 if (eHAL_STATUS_SUCCESS != hstatus)
4522 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004523 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4524 __func__);
4525 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004526 }
4527 else
4528 {
4529 /* request was sent -- wait for the response */
4530 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4531 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004532 if (lrc <= 0)
4533 {
4534 hddLog(VOS_TRACE_LEVEL_ERROR,
4535 "%s: SME %s while retrieving statistics",
4536 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004537 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004538 }
4539 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004540
Jeff Johnson72a40512013-12-19 10:14:15 -08004541 /* either we never sent a request, we sent a request and received a
4542 response or we sent a request and timed out. if we never sent a
4543 request or if we sent a request and got a response, we want to
4544 clear the magic out of paranoia. if we timed out there is a
4545 race condition such that the callback function could be
4546 executing at the same time we are. of primary concern is if the
4547 callback function had already verified the "magic" but had not
4548 yet set the completion variable when a timeout occurred. we
4549 serialize these activities by invalidating the magic while
4550 holding a shared spinlock which will cause us to block if the
4551 callback is currently executing */
4552 spin_lock(&hdd_context_lock);
4553 context.magic = 0;
4554 spin_unlock(&hdd_context_lock);
4555
4556 if (VOS_STATUS_SUCCESS == vstatus)
4557 {
4558 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4559 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4560 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4561 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4562 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4563 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4564 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4565 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4566 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4567 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4568 }
4569 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004570}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004571#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004572
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004573#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004574void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4575{
4576 eCsrBand band = -1;
4577 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4578 switch (band)
4579 {
4580 case eCSR_BAND_ALL:
4581 *pBand = WLAN_HDD_UI_BAND_AUTO;
4582 break;
4583
4584 case eCSR_BAND_24:
4585 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4586 break;
4587
4588 case eCSR_BAND_5G:
4589 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4590 break;
4591
4592 default:
4593 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4594 *pBand = -1;
4595 break;
4596 }
4597}
4598
4599/**---------------------------------------------------------------------------
4600
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004601 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4602
4603 This function parses the send action frame data passed in the format
4604 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4605
Srinivas Girigowda56076852013-08-20 14:00:50 -07004606 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004607 \param - pTargetApBssid Pointer to target Ap bssid
4608 \param - pChannel Pointer to the Target AP channel
4609 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4610 \param - pBuf Pointer to data
4611 \param - pBufLen Pointer to data length
4612
4613 \return - 0 for success non-zero for failure
4614
4615 --------------------------------------------------------------------------*/
4616VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4617 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4618{
4619 tANI_U8 *inPtr = pValue;
4620 tANI_U8 *dataEnd;
4621 int tempInt;
4622 int j = 0;
4623 int i = 0;
4624 int v = 0;
4625 tANI_U8 tempBuf[32];
4626 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004627 /* 12 hexa decimal digits, 5 ':' and '\0' */
4628 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004629
4630 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4631 /*no argument after the command*/
4632 if (NULL == inPtr)
4633 {
4634 return -EINVAL;
4635 }
4636
4637 /*no space after the command*/
4638 else if (SPACE_ASCII_VALUE != *inPtr)
4639 {
4640 return -EINVAL;
4641 }
4642
4643 /*removing empty spaces*/
4644 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4645
4646 /*no argument followed by spaces*/
4647 if ('\0' == *inPtr)
4648 {
4649 return -EINVAL;
4650 }
4651
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004652 v = sscanf(inPtr, "%17s", macAddress);
4653 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004654 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4656 "Invalid MAC address or All hex inputs are not read (%d)", v);
4657 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004658 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004659
4660 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4661 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4662 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4663 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4664 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4665 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004666
4667 /* point to the next argument */
4668 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4669 /*no argument after the command*/
4670 if (NULL == inPtr) return -EINVAL;
4671
4672 /*removing empty spaces*/
4673 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4674
4675 /*no argument followed by spaces*/
4676 if ('\0' == *inPtr)
4677 {
4678 return -EINVAL;
4679 }
4680
4681 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004682 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004683 if (1 != v) return -EINVAL;
4684
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004685 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304686 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304687 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004688
4689 *pChannel = tempInt;
4690
4691 /* point to the next argument */
4692 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4693 /*no argument after the command*/
4694 if (NULL == inPtr) return -EINVAL;
4695 /*removing empty spaces*/
4696 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4697
4698 /*no argument followed by spaces*/
4699 if ('\0' == *inPtr)
4700 {
4701 return -EINVAL;
4702 }
4703
4704 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004705 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004706 if (1 != v) return -EINVAL;
4707
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004708 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004709 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004710
4711 *pDwellTime = tempInt;
4712
4713 /* point to the next argument */
4714 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4715 /*no argument after the command*/
4716 if (NULL == inPtr) return -EINVAL;
4717 /*removing empty spaces*/
4718 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4719
4720 /*no argument followed by spaces*/
4721 if ('\0' == *inPtr)
4722 {
4723 return -EINVAL;
4724 }
4725
4726 /* find the length of data */
4727 dataEnd = inPtr;
4728 while(('\0' != *dataEnd) )
4729 {
4730 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004731 }
Kiet Lambe150c22013-11-21 16:30:32 +05304732 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004733 if ( *pBufLen <= 0) return -EINVAL;
4734
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004735 /* Allocate the number of bytes based on the number of input characters
4736 whether it is even or odd.
4737 if the number of input characters are even, then we need N/2 byte.
4738 if the number of input characters are odd, then we need do (N+1)/2 to
4739 compensate rounding off.
4740 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4741 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4742 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004743 if (NULL == *pBuf)
4744 {
4745 hddLog(VOS_TRACE_LEVEL_FATAL,
4746 "%s: vos_mem_alloc failed ", __func__);
4747 return -EINVAL;
4748 }
4749
4750 /* the buffer received from the upper layer is character buffer,
4751 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4752 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4753 and f0 in 3rd location */
4754 for (i = 0, j = 0; j < *pBufLen; j += 2)
4755 {
Kiet Lambe150c22013-11-21 16:30:32 +05304756 if( j+1 == *pBufLen)
4757 {
4758 tempByte = hdd_parse_hex(inPtr[j]);
4759 }
4760 else
4761 {
4762 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4763 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004764 (*pBuf)[i++] = tempByte;
4765 }
4766 *pBufLen = i;
4767 return VOS_STATUS_SUCCESS;
4768}
4769
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004770/**---------------------------------------------------------------------------
4771
Srinivas Girigowdade697412013-02-14 16:31:48 -08004772 \brief hdd_parse_channellist() - HDD Parse channel list
4773
4774 This function parses the channel list passed in the format
4775 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004776 if the Number of channels (N) does not match with the actual number of channels passed
4777 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4778 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4779 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4780 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004781
4782 \param - pValue Pointer to input channel list
4783 \param - ChannelList Pointer to local output array to record channel list
4784 \param - pNumChannels Pointer to number of roam scan channels
4785
4786 \return - 0 for success non-zero for failure
4787
4788 --------------------------------------------------------------------------*/
4789VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4790{
4791 tANI_U8 *inPtr = pValue;
4792 int tempInt;
4793 int j = 0;
4794 int v = 0;
4795 char buf[32];
4796
4797 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4798 /*no argument after the command*/
4799 if (NULL == inPtr)
4800 {
4801 return -EINVAL;
4802 }
4803
4804 /*no space after the command*/
4805 else if (SPACE_ASCII_VALUE != *inPtr)
4806 {
4807 return -EINVAL;
4808 }
4809
4810 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004811 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004812
4813 /*no argument followed by spaces*/
4814 if ('\0' == *inPtr)
4815 {
4816 return -EINVAL;
4817 }
4818
4819 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004820 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004821 if (1 != v) return -EINVAL;
4822
Srinivas Girigowdade697412013-02-14 16:31:48 -08004823 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004824 if ((v < 0) ||
4825 (tempInt <= 0) ||
4826 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4827 {
4828 return -EINVAL;
4829 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004830
4831 *pNumChannels = tempInt;
4832
4833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4834 "Number of channels are: %d", *pNumChannels);
4835
4836 for (j = 0; j < (*pNumChannels); j++)
4837 {
4838 /*inPtr pointing to the beginning of first space after number of channels*/
4839 inPtr = strpbrk( inPtr, " " );
4840 /*no channel list after the number of channels argument*/
4841 if (NULL == inPtr)
4842 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004843 if (0 != j)
4844 {
4845 *pNumChannels = j;
4846 return VOS_STATUS_SUCCESS;
4847 }
4848 else
4849 {
4850 return -EINVAL;
4851 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004852 }
4853
4854 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004855 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004856
4857 /*no channel list after the number of channels argument and spaces*/
4858 if ( '\0' == *inPtr )
4859 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004860 if (0 != j)
4861 {
4862 *pNumChannels = j;
4863 return VOS_STATUS_SUCCESS;
4864 }
4865 else
4866 {
4867 return -EINVAL;
4868 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004869 }
4870
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004871 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004872 if (1 != v) return -EINVAL;
4873
Srinivas Girigowdade697412013-02-14 16:31:48 -08004874 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004875 if ((v < 0) ||
4876 (tempInt <= 0) ||
4877 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4878 {
4879 return -EINVAL;
4880 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004881 pChannelList[j] = tempInt;
4882
4883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4884 "Channel %d added to preferred channel list",
4885 pChannelList[j] );
4886 }
4887
Srinivas Girigowdade697412013-02-14 16:31:48 -08004888 return VOS_STATUS_SUCCESS;
4889}
4890
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004891
4892/**---------------------------------------------------------------------------
4893
4894 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4895
4896 This function parses the reasoc command data passed in the format
4897 REASSOC<space><bssid><space><channel>
4898
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004899 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004900 \param - pTargetApBssid Pointer to target Ap bssid
4901 \param - pChannel Pointer to the Target AP channel
4902
4903 \return - 0 for success non-zero for failure
4904
4905 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004906VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4907 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004908{
4909 tANI_U8 *inPtr = pValue;
4910 int tempInt;
4911 int v = 0;
4912 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004913 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004914 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004915
4916 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4917 /*no argument after the command*/
4918 if (NULL == inPtr)
4919 {
4920 return -EINVAL;
4921 }
4922
4923 /*no space after the command*/
4924 else if (SPACE_ASCII_VALUE != *inPtr)
4925 {
4926 return -EINVAL;
4927 }
4928
4929 /*removing empty spaces*/
4930 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4931
4932 /*no argument followed by spaces*/
4933 if ('\0' == *inPtr)
4934 {
4935 return -EINVAL;
4936 }
4937
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004938 v = sscanf(inPtr, "%17s", macAddress);
4939 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004940 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4942 "Invalid MAC address or All hex inputs are not read (%d)", v);
4943 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004944 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004945
4946 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4947 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4948 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4949 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4950 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4951 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004952
4953 /* point to the next argument */
4954 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4955 /*no argument after the command*/
4956 if (NULL == inPtr) return -EINVAL;
4957
4958 /*removing empty spaces*/
4959 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4960
4961 /*no argument followed by spaces*/
4962 if ('\0' == *inPtr)
4963 {
4964 return -EINVAL;
4965 }
4966
4967 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004968 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004969 if (1 != v) return -EINVAL;
4970
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004971 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004972 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05304973 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004974 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4975 {
4976 return -EINVAL;
4977 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004978
4979 *pChannel = tempInt;
4980 return VOS_STATUS_SUCCESS;
4981}
4982
4983#endif
4984
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004985#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004986/**---------------------------------------------------------------------------
4987
4988 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4989
4990 This function parses the SETCCKM IE command
4991 SETCCKMIE<space><ie data>
4992
4993 \param - pValue Pointer to input data
4994 \param - pCckmIe Pointer to output cckm Ie
4995 \param - pCckmIeLen Pointer to output cckm ie length
4996
4997 \return - 0 for success non-zero for failure
4998
4999 --------------------------------------------------------------------------*/
5000VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
5001 tANI_U8 *pCckmIeLen)
5002{
5003 tANI_U8 *inPtr = pValue;
5004 tANI_U8 *dataEnd;
5005 int j = 0;
5006 int i = 0;
5007 tANI_U8 tempByte = 0;
5008
5009 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
5010 /*no argument after the command*/
5011 if (NULL == inPtr)
5012 {
5013 return -EINVAL;
5014 }
5015
5016 /*no space after the command*/
5017 else if (SPACE_ASCII_VALUE != *inPtr)
5018 {
5019 return -EINVAL;
5020 }
5021
5022 /*removing empty spaces*/
5023 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5024
5025 /*no argument followed by spaces*/
5026 if ('\0' == *inPtr)
5027 {
5028 return -EINVAL;
5029 }
5030
5031 /* find the length of data */
5032 dataEnd = inPtr;
5033 while(('\0' != *dataEnd) )
5034 {
5035 dataEnd++;
5036 ++(*pCckmIeLen);
5037 }
5038 if ( *pCckmIeLen <= 0) return -EINVAL;
5039
5040 /* Allocate the number of bytes based on the number of input characters
5041 whether it is even or odd.
5042 if the number of input characters are even, then we need N/2 byte.
5043 if the number of input characters are odd, then we need do (N+1)/2 to
5044 compensate rounding off.
5045 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5046 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5047 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5048 if (NULL == *pCckmIe)
5049 {
5050 hddLog(VOS_TRACE_LEVEL_FATAL,
5051 "%s: vos_mem_alloc failed ", __func__);
5052 return -EINVAL;
5053 }
5054 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5055 /* the buffer received from the upper layer is character buffer,
5056 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5057 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5058 and f0 in 3rd location */
5059 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5060 {
5061 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5062 (*pCckmIe)[i++] = tempByte;
5063 }
5064 *pCckmIeLen = i;
5065
5066 return VOS_STATUS_SUCCESS;
5067}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005068#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005069
Jeff Johnson295189b2012-06-20 16:38:30 -07005070/**---------------------------------------------------------------------------
5071
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005072 \brief hdd_is_valid_mac_address() - Validate MAC address
5073
5074 This function validates whether the given MAC address is valid or not
5075 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5076 where X is the hexa decimal digit character and separated by ':'
5077 This algorithm works even if MAC address is not separated by ':'
5078
5079 This code checks given input string mac contains exactly 12 hexadecimal digits.
5080 and a separator colon : appears in the input string only after
5081 an even number of hex digits.
5082
5083 \param - pMacAddr pointer to the input MAC address
5084 \return - 1 for valid and 0 for invalid
5085
5086 --------------------------------------------------------------------------*/
5087
5088v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5089{
5090 int xdigit = 0;
5091 int separator = 0;
5092 while (*pMacAddr)
5093 {
5094 if (isxdigit(*pMacAddr))
5095 {
5096 xdigit++;
5097 }
5098 else if (':' == *pMacAddr)
5099 {
5100 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5101 break;
5102
5103 ++separator;
5104 }
5105 else
5106 {
5107 separator = -1;
5108 /* Invalid MAC found */
5109 return 0;
5110 }
5111 ++pMacAddr;
5112 }
5113 return (xdigit == 12 && (separator == 5 || separator == 0));
5114}
5115
5116/**---------------------------------------------------------------------------
5117
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305118 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005119
5120 \param - dev Pointer to net_device structure
5121
5122 \return - 0 for success non-zero for failure
5123
5124 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305125int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005126{
5127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5128 hdd_context_t *pHddCtx;
5129 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5130 VOS_STATUS status;
5131 v_BOOL_t in_standby = TRUE;
5132
5133 if (NULL == pAdapter)
5134 {
5135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305136 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 return -ENODEV;
5138 }
5139
5140 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305141 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5142 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 if (NULL == pHddCtx)
5144 {
5145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005146 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 return -ENODEV;
5148 }
5149
5150 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5151 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5152 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005153 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5154 {
5155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305156 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005157 in_standby = FALSE;
5158 break;
5159 }
5160 else
5161 {
5162 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5163 pAdapterNode = pNext;
5164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 }
5166
5167 if (TRUE == in_standby)
5168 {
5169 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5170 {
5171 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5172 "wlan out of power save", __func__);
5173 return -EINVAL;
5174 }
5175 }
5176
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005177 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005178 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5179 {
5180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005181 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005182 /* Enable TX queues only when we are connected */
5183 netif_tx_start_all_queues(dev);
5184 }
5185
5186 return 0;
5187}
5188
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305189/**---------------------------------------------------------------------------
5190
5191 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5192
5193 This is called in response to ifconfig up
5194
5195 \param - dev Pointer to net_device structure
5196
5197 \return - 0 for success non-zero for failure
5198
5199 --------------------------------------------------------------------------*/
5200int hdd_open(struct net_device *dev)
5201{
5202 int ret;
5203
5204 vos_ssr_protect(__func__);
5205 ret = __hdd_open(dev);
5206 vos_ssr_unprotect(__func__);
5207
5208 return ret;
5209}
5210
Jeff Johnson295189b2012-06-20 16:38:30 -07005211int hdd_mon_open (struct net_device *dev)
5212{
5213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5214
5215 if(pAdapter == NULL) {
5216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005217 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005218 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 }
5220
5221 netif_start_queue(dev);
5222
5223 return 0;
5224}
5225/**---------------------------------------------------------------------------
5226
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305227 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005228
5229 \param - dev Pointer to net_device structure
5230
5231 \return - 0 for success non-zero for failure
5232
5233 --------------------------------------------------------------------------*/
5234
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305235int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005236{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305237 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005238 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5239 hdd_context_t *pHddCtx;
5240 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5241 VOS_STATUS status;
5242 v_BOOL_t enter_standby = TRUE;
5243
5244 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 if (NULL == pAdapter)
5246 {
5247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305248 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005249 return -ENODEV;
5250 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305251 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5252 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305253
5254 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5255 ret = wlan_hdd_validate_context(pHddCtx);
5256 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07005257 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5259 "%s: HDD context is not valid!", __func__);
5260 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 }
5262
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305263 /* Nothing to be done if the interface is not opened */
5264 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5265 {
5266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5267 "%s: NETDEV Interface is not OPENED", __func__);
5268 return -ENODEV;
5269 }
5270
5271 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005272 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305274
5275 /* Disable TX on the interface, after this hard_start_xmit() will not
5276 * be called on that interface
5277 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305279
5280 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 netif_carrier_off(pAdapter->dev);
5282
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305283 /* The interface is marked as down for outside world (aka kernel)
5284 * But the driver is pretty much alive inside. The driver needs to
5285 * tear down the existing connection on the netdev (session)
5286 * cleanup the data pipes and wait until the control plane is stabilized
5287 * for this interface. The call also needs to wait until the above
5288 * mentioned actions are completed before returning to the caller.
5289 * Notice that the hdd_stop_adapter is requested not to close the session
5290 * That is intentional to be able to scan if it is a STA/P2P interface
5291 */
5292 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005293
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305294 /* DeInit the adapter. This ensures datapath cleanup as well */
5295 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005296 /* SoftAP ifaces should never go in power save mode
5297 making sure same here. */
5298 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5299 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 )
5302 {
5303 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5305 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005306 EXIT();
5307 return 0;
5308 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305309 /* Find if any iface is up. If any iface is up then can't put device to
5310 * sleep/power save mode
5311 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005312 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5313 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5314 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005315 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5316 {
5317 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305318 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005319 enter_standby = FALSE;
5320 break;
5321 }
5322 else
5323 {
5324 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5325 pAdapterNode = pNext;
5326 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005327 }
5328
5329 if (TRUE == enter_standby)
5330 {
5331 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5332 "entering standby", __func__);
5333 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5334 {
5335 /*log and return success*/
5336 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5337 "wlan in power save", __func__);
5338 }
5339 }
5340
5341 EXIT();
5342 return 0;
5343}
5344
5345/**---------------------------------------------------------------------------
5346
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305347 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005348
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305349 This is called in response to ifconfig down
5350
5351 \param - dev Pointer to net_device structure
5352
5353 \return - 0 for success non-zero for failure
5354-----------------------------------------------------------------------------*/
5355int hdd_stop (struct net_device *dev)
5356{
5357 int ret;
5358
5359 vos_ssr_protect(__func__);
5360 ret = __hdd_stop(dev);
5361 vos_ssr_unprotect(__func__);
5362
5363 return ret;
5364}
5365
5366/**---------------------------------------------------------------------------
5367
5368 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005369
5370 \param - dev Pointer to net_device structure
5371
5372 \return - void
5373
5374 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305375static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005376{
5377 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5378
5379 ENTER();
5380
5381 do
5382 {
5383 if (NULL == pAdapter)
5384 {
5385 hddLog(VOS_TRACE_LEVEL_FATAL,
5386 "%s: NULL pAdapter", __func__);
5387 break;
5388 }
5389
5390 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5391 {
5392 hddLog(VOS_TRACE_LEVEL_FATAL,
5393 "%s: Invalid magic", __func__);
5394 break;
5395 }
5396
5397 if (NULL == pAdapter->pHddCtx)
5398 {
5399 hddLog(VOS_TRACE_LEVEL_FATAL,
5400 "%s: NULL pHddCtx", __func__);
5401 break;
5402 }
5403
5404 if (dev != pAdapter->dev)
5405 {
5406 hddLog(VOS_TRACE_LEVEL_FATAL,
5407 "%s: Invalid device reference", __func__);
5408 /* we haven't validated all cases so let this go for now */
5409 }
5410
5411 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5412
5413 /* after uninit our adapter structure will no longer be valid */
5414 pAdapter->dev = NULL;
5415 pAdapter->magic = 0;
5416 } while (0);
5417
5418 EXIT();
5419}
5420
5421/**---------------------------------------------------------------------------
5422
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305423 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5424
5425 This is called during the netdev unregister to uninitialize all data
5426associated with the device
5427
5428 \param - dev Pointer to net_device structure
5429
5430 \return - void
5431
5432 --------------------------------------------------------------------------*/
5433static void hdd_uninit (struct net_device *dev)
5434{
5435 vos_ssr_protect(__func__);
5436 __hdd_uninit(dev);
5437 vos_ssr_unprotect(__func__);
5438}
5439
5440/**---------------------------------------------------------------------------
5441
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 \brief hdd_release_firmware() -
5443
5444 This function calls the release firmware API to free the firmware buffer.
5445
5446 \param - pFileName Pointer to the File Name.
5447 pCtx - Pointer to the adapter .
5448
5449
5450 \return - 0 for success, non zero for failure
5451
5452 --------------------------------------------------------------------------*/
5453
5454VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5455{
5456 VOS_STATUS status = VOS_STATUS_SUCCESS;
5457 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5458 ENTER();
5459
5460
5461 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5462
5463 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5464
5465 if(pHddCtx->fw) {
5466 release_firmware(pHddCtx->fw);
5467 pHddCtx->fw = NULL;
5468 }
5469 else
5470 status = VOS_STATUS_E_FAILURE;
5471 }
5472 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5473 if(pHddCtx->nv) {
5474 release_firmware(pHddCtx->nv);
5475 pHddCtx->nv = NULL;
5476 }
5477 else
5478 status = VOS_STATUS_E_FAILURE;
5479
5480 }
5481
5482 EXIT();
5483 return status;
5484}
5485
5486/**---------------------------------------------------------------------------
5487
5488 \brief hdd_request_firmware() -
5489
5490 This function reads the firmware file using the request firmware
5491 API and returns the the firmware data and the firmware file size.
5492
5493 \param - pfileName - Pointer to the file name.
5494 - pCtx - Pointer to the adapter .
5495 - ppfw_data - Pointer to the pointer of the firmware data.
5496 - pSize - Pointer to the file size.
5497
5498 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5499
5500 --------------------------------------------------------------------------*/
5501
5502
5503VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5504{
5505 int status;
5506 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5507 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5508 ENTER();
5509
5510 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5511
5512 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5513
5514 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5515 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5516 __func__, pfileName);
5517 retval = VOS_STATUS_E_FAILURE;
5518 }
5519
5520 else {
5521 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5522 *pSize = pHddCtx->fw->size;
5523 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5524 __func__, *pSize);
5525 }
5526 }
5527 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5528
5529 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5530
5531 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5532 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5533 __func__, pfileName);
5534 retval = VOS_STATUS_E_FAILURE;
5535 }
5536
5537 else {
5538 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5539 *pSize = pHddCtx->nv->size;
5540 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5541 __func__, *pSize);
5542 }
5543 }
5544
5545 EXIT();
5546 return retval;
5547}
5548/**---------------------------------------------------------------------------
5549 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5550
5551 This is the function invoked by SME to inform the result of a full power
5552 request issued by HDD
5553
5554 \param - callbackcontext - Pointer to cookie
5555 status - result of request
5556
5557 \return - None
5558
5559--------------------------------------------------------------------------*/
5560void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5561{
5562 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5563
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005564 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005565 if(&pHddCtx->full_pwr_comp_var)
5566 {
5567 complete(&pHddCtx->full_pwr_comp_var);
5568 }
5569}
5570
5571/**---------------------------------------------------------------------------
5572
5573 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5574
5575 This is the function invoked by SME to inform the result of BMPS
5576 request issued by HDD
5577
5578 \param - callbackcontext - Pointer to cookie
5579 status - result of request
5580
5581 \return - None
5582
5583--------------------------------------------------------------------------*/
5584void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5585{
5586
5587 struct completion *completion_var = (struct completion*) callbackContext;
5588
Arif Hussain6d2a3322013-11-17 19:50:10 -08005589 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 if(completion_var != NULL)
5591 {
5592 complete(completion_var);
5593 }
5594}
5595
5596/**---------------------------------------------------------------------------
5597
5598 \brief hdd_get_cfg_file_size() -
5599
5600 This function reads the configuration file using the request firmware
5601 API and returns the configuration file size.
5602
5603 \param - pCtx - Pointer to the adapter .
5604 - pFileName - Pointer to the file name.
5605 - pBufSize - Pointer to the buffer size.
5606
5607 \return - 0 for success, non zero for failure
5608
5609 --------------------------------------------------------------------------*/
5610
5611VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5612{
5613 int status;
5614 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5615
5616 ENTER();
5617
5618 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5619
5620 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5622 status = VOS_STATUS_E_FAILURE;
5623 }
5624 else {
5625 *pBufSize = pHddCtx->fw->size;
5626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5627 release_firmware(pHddCtx->fw);
5628 pHddCtx->fw = NULL;
5629 }
5630
5631 EXIT();
5632 return VOS_STATUS_SUCCESS;
5633}
5634
5635/**---------------------------------------------------------------------------
5636
5637 \brief hdd_read_cfg_file() -
5638
5639 This function reads the configuration file using the request firmware
5640 API and returns the cfg data and the buffer size of the configuration file.
5641
5642 \param - pCtx - Pointer to the adapter .
5643 - pFileName - Pointer to the file name.
5644 - pBuffer - Pointer to the data buffer.
5645 - pBufSize - Pointer to the buffer size.
5646
5647 \return - 0 for success, non zero for failure
5648
5649 --------------------------------------------------------------------------*/
5650
5651VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5652 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5653{
5654 int status;
5655 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5656
5657 ENTER();
5658
5659 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5660
5661 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5662 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5663 return VOS_STATUS_E_FAILURE;
5664 }
5665 else {
5666 if(*pBufSize != pHddCtx->fw->size) {
5667 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5668 "file size", __func__);
5669 release_firmware(pHddCtx->fw);
5670 pHddCtx->fw = NULL;
5671 return VOS_STATUS_E_FAILURE;
5672 }
5673 else {
5674 if(pBuffer) {
5675 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5676 }
5677 release_firmware(pHddCtx->fw);
5678 pHddCtx->fw = NULL;
5679 }
5680 }
5681
5682 EXIT();
5683
5684 return VOS_STATUS_SUCCESS;
5685}
5686
5687/**---------------------------------------------------------------------------
5688
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305689 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005690
5691 This function sets the user specified mac address using
5692 the command ifconfig wlanX hw ether <mac adress>.
5693
5694 \param - dev - Pointer to the net device.
5695 - addr - Pointer to the sockaddr.
5696 \return - 0 for success, non zero for failure
5697
5698 --------------------------------------------------------------------------*/
5699
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305700static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005701{
5702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5703 struct sockaddr *psta_mac_addr = addr;
5704 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5705
5706 ENTER();
5707
5708 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005709 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5710
5711 EXIT();
5712 return halStatus;
5713}
5714
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305715/**---------------------------------------------------------------------------
5716
5717 \brief hdd_set_mac_address() -
5718
5719 Wrapper function to protect __hdd_set_mac_address() function from ssr
5720
5721 \param - dev - Pointer to the net device.
5722 - addr - Pointer to the sockaddr.
5723 \return - 0 for success, non zero for failure
5724
5725 --------------------------------------------------------------------------*/
5726static int hdd_set_mac_address(struct net_device *dev, void *addr)
5727{
5728 int ret;
5729
5730 vos_ssr_protect(__func__);
5731 ret = __hdd_set_mac_address(dev, addr);
5732 vos_ssr_unprotect(__func__);
5733
5734 return ret;
5735}
5736
Jeff Johnson295189b2012-06-20 16:38:30 -07005737tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5738{
5739 int i;
5740 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5741 {
Abhishek Singheb183782014-02-06 13:37:21 +05305742 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 break;
5744 }
5745
5746 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5747 return NULL;
5748
5749 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5750 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5751}
5752
5753void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5754{
5755 int i;
5756 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5757 {
5758 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5759 {
5760 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5761 break;
5762 }
5763 }
5764 return;
5765}
5766
5767#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5768 static struct net_device_ops wlan_drv_ops = {
5769 .ndo_open = hdd_open,
5770 .ndo_stop = hdd_stop,
5771 .ndo_uninit = hdd_uninit,
5772 .ndo_start_xmit = hdd_hard_start_xmit,
5773 .ndo_tx_timeout = hdd_tx_timeout,
5774 .ndo_get_stats = hdd_stats,
5775 .ndo_do_ioctl = hdd_ioctl,
5776 .ndo_set_mac_address = hdd_set_mac_address,
5777 .ndo_select_queue = hdd_select_queue,
5778#ifdef WLAN_FEATURE_PACKET_FILTERING
5779#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5780 .ndo_set_rx_mode = hdd_set_multicast_list,
5781#else
5782 .ndo_set_multicast_list = hdd_set_multicast_list,
5783#endif //LINUX_VERSION_CODE
5784#endif
5785 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 static struct net_device_ops wlan_mon_drv_ops = {
5787 .ndo_open = hdd_mon_open,
5788 .ndo_stop = hdd_stop,
5789 .ndo_uninit = hdd_uninit,
5790 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5791 .ndo_tx_timeout = hdd_tx_timeout,
5792 .ndo_get_stats = hdd_stats,
5793 .ndo_do_ioctl = hdd_ioctl,
5794 .ndo_set_mac_address = hdd_set_mac_address,
5795 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005796
5797#endif
5798
5799void hdd_set_station_ops( struct net_device *pWlanDev )
5800{
5801#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 pWlanDev->netdev_ops = &wlan_drv_ops;
5803#else
5804 pWlanDev->open = hdd_open;
5805 pWlanDev->stop = hdd_stop;
5806 pWlanDev->uninit = hdd_uninit;
5807 pWlanDev->hard_start_xmit = NULL;
5808 pWlanDev->tx_timeout = hdd_tx_timeout;
5809 pWlanDev->get_stats = hdd_stats;
5810 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 pWlanDev->set_mac_address = hdd_set_mac_address;
5812#endif
5813}
5814
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005815static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005816{
5817 struct net_device *pWlanDev = NULL;
5818 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 /*
5820 * cfg80211 initialization and registration....
5821 */
5822 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5823
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 if(pWlanDev != NULL)
5825 {
5826
5827 //Save the pointer to the net_device in the HDD adapter
5828 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5831
5832 pAdapter->dev = pWlanDev;
5833 pAdapter->pHddCtx = pHddCtx;
5834 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305835 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005836
5837 init_completion(&pAdapter->session_open_comp_var);
5838 init_completion(&pAdapter->session_close_comp_var);
5839 init_completion(&pAdapter->disconnect_comp_var);
5840 init_completion(&pAdapter->linkup_event_var);
5841 init_completion(&pAdapter->cancel_rem_on_chan_var);
5842 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305843 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005844#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5845 init_completion(&pAdapter->offchannel_tx_event);
5846#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005848#ifdef FEATURE_WLAN_TDLS
5849 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005850 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005851 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305852 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005853#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 init_completion(&pHddCtx->mc_sus_event_var);
5855 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305856 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005857 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005858 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005859
Rajeev79dbe4c2013-10-05 11:03:42 +05305860#ifdef FEATURE_WLAN_BATCH_SCAN
5861 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5862 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5863 pAdapter->pBatchScanRsp = NULL;
5864 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005865 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005866 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305867 mutex_init(&pAdapter->hdd_batch_scan_lock);
5868#endif
5869
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 pAdapter->isLinkUpSvcNeeded = FALSE;
5871 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5872 //Init the net_device structure
5873 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5874
5875 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5876 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5877 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5878 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5879
5880 hdd_set_station_ops( pAdapter->dev );
5881
5882 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5884 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5885 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 /* set pWlanDev's parent to underlying device */
5887 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005888
5889 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 }
5891
5892 return pAdapter;
5893}
5894
5895VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5896{
5897 struct net_device *pWlanDev = pAdapter->dev;
5898 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5899 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5900 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5901
5902 if( rtnl_lock_held )
5903 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005904 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5906 {
5907 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5908 return VOS_STATUS_E_FAILURE;
5909 }
5910 }
5911 if (register_netdevice(pWlanDev))
5912 {
5913 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5914 return VOS_STATUS_E_FAILURE;
5915 }
5916 }
5917 else
5918 {
5919 if(register_netdev(pWlanDev))
5920 {
5921 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5922 return VOS_STATUS_E_FAILURE;
5923 }
5924 }
5925 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5926
5927 return VOS_STATUS_SUCCESS;
5928}
5929
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005930static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005931{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005932 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005933
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005934 if (NULL == pAdapter)
5935 {
5936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5937 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005939
5940 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5941 {
5942 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5943 return eHAL_STATUS_NOT_INITIALIZED;
5944 }
5945
5946 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5947
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005948#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005949 /* need to make sure all of our scheduled work has completed.
5950 * This callback is called from MC thread context, so it is safe to
5951 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005952 *
5953 * Even though this is called from MC thread context, if there is a faulty
5954 * work item in the system, that can hang this call forever. So flushing
5955 * this global work queue is not safe; and now we make sure that
5956 * individual work queues are stopped correctly. But the cancel work queue
5957 * is a GPL only API, so the proprietary version of the driver would still
5958 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005959 */
5960 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005961#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005962
5963 /* We can be blocked while waiting for scheduled work to be
5964 * flushed, and the adapter structure can potentially be freed, in
5965 * which case the magic will have been reset. So make sure the
5966 * magic is still good, and hence the adapter structure is still
5967 * valid, before signaling completion */
5968 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5969 {
5970 complete(&pAdapter->session_close_comp_var);
5971 }
5972
Jeff Johnson295189b2012-06-20 16:38:30 -07005973 return eHAL_STATUS_SUCCESS;
5974}
5975
5976VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5977{
5978 struct net_device *pWlanDev = pAdapter->dev;
5979 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5980 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5981 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5982 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305983 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005984
5985 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005986 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 //Open a SME session for future operation
5988 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005989 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005990 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5991 {
5992 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005993 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005994 halStatus, halStatus );
5995 status = VOS_STATUS_E_FAILURE;
5996 goto error_sme_open;
5997 }
5998
5999 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05306000 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006001 &pAdapter->session_open_comp_var,
6002 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306003 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 {
6005 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306006 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 status = VOS_STATUS_E_FAILURE;
6008 goto error_sme_open;
6009 }
6010
6011 // Register wireless extensions
6012 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
6013 {
6014 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006015 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006016 halStatus, halStatus );
6017 status = VOS_STATUS_E_FAILURE;
6018 goto error_register_wext;
6019 }
6020 //Safe to register the hard_start_xmit function again
6021#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
6022 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
6023#else
6024 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
6025#endif
6026
6027 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05306028 hddLog(VOS_TRACE_LEVEL_INFO,
6029 "%s: Set HDD connState to eConnectionState_NotConnected",
6030 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006031 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6032
6033 //Set the default operation channel
6034 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
6035
6036 /* Make the default Auth Type as OPEN*/
6037 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
6038
6039 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6040 {
6041 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006042 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 status, status );
6044 goto error_init_txrx;
6045 }
6046
6047 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6048
6049 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6050 {
6051 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006052 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 status, status );
6054 goto error_wmm_init;
6055 }
6056
6057 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6058
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006059#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306060 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006061 {
6062 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306063 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006064 goto error_tdls_init;
6065 }
6066 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6067#endif
6068
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 return VOS_STATUS_SUCCESS;
6070
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006071#ifdef FEATURE_WLAN_TDLS
6072error_tdls_init:
6073 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6074 hdd_wmm_adapter_close(pAdapter);
6075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006076error_wmm_init:
6077 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6078 hdd_deinit_tx_rx(pAdapter);
6079error_init_txrx:
6080 hdd_UnregisterWext(pWlanDev);
6081error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006082 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006083 {
6084 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006085 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006087 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006088 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306089 unsigned long rc;
6090
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306092 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006094 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306095 if (rc <= 0)
6096 hddLog(VOS_TRACE_LEVEL_ERROR,
6097 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 }
6099}
6100error_sme_open:
6101 return status;
6102}
6103
Jeff Johnson295189b2012-06-20 16:38:30 -07006104void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6105{
6106 hdd_cfg80211_state_t *cfgState;
6107
6108 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6109
6110 if( NULL != cfgState->buf )
6111 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306112 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006113 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6114 rc = wait_for_completion_interruptible_timeout(
6115 &pAdapter->tx_action_cnf_event,
6116 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306117 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006119 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306120 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6121 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 }
6123 }
6124 return;
6125}
Jeff Johnson295189b2012-06-20 16:38:30 -07006126
6127void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6128{
6129 ENTER();
6130 switch ( pAdapter->device_mode )
6131 {
6132 case WLAN_HDD_INFRA_STATION:
6133 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006134 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 {
6136 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6137 {
6138 hdd_deinit_tx_rx( pAdapter );
6139 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6140 }
6141
6142 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6143 {
6144 hdd_wmm_adapter_close( pAdapter );
6145 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6146 }
6147
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006149#ifdef FEATURE_WLAN_TDLS
6150 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6151 {
6152 wlan_hdd_tdls_exit(pAdapter);
6153 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6154 }
6155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006156
6157 break;
6158 }
6159
6160 case WLAN_HDD_SOFTAP:
6161 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306163
6164 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6165 {
6166 hdd_wmm_adapter_close( pAdapter );
6167 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6168 }
6169
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006171
6172 hdd_unregister_hostapd(pAdapter);
6173 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006174 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 break;
6176 }
6177
6178 case WLAN_HDD_MONITOR:
6179 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6182 {
6183 hdd_deinit_tx_rx( pAdapter );
6184 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 if(NULL != pAdapterforTx)
6187 {
6188 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 break;
6191 }
6192
6193
6194 default:
6195 break;
6196 }
6197
6198 EXIT();
6199}
6200
6201void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6202{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006203 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306204
6205 ENTER();
6206 if (NULL == pAdapter)
6207 {
6208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6209 "%s: HDD adapter is Null", __func__);
6210 return;
6211 }
6212
6213 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006214
Rajeev79dbe4c2013-10-05 11:03:42 +05306215#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306216 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6217 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006218 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306219 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6220 )
6221 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006222 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306223 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006224 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6225 {
6226 hdd_deinit_batch_scan(pAdapter);
6227 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306228 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006229 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306230#endif
6231
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6233 if( rtnl_held )
6234 {
6235 unregister_netdevice(pWlanDev);
6236 }
6237 else
6238 {
6239 unregister_netdev(pWlanDev);
6240 }
6241 // note that the pAdapter is no longer valid at this point
6242 // since the memory has been reclaimed
6243 }
6244
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306245 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006246}
6247
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006248void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6249{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306250 VOS_STATUS status;
6251 hdd_adapter_t *pAdapter = NULL;
6252 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006253
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306254 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006255
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306256 /*loop through all adapters.*/
6257 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006258 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306259 pAdapter = pAdapterNode->pAdapter;
6260 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6261 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006262
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306263 { // we skip this registration for modes other than STA and P2P client modes.
6264 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6265 pAdapterNode = pNext;
6266 continue;
6267 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006268
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306269 //Apply Dynamic DTIM For P2P
6270 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6271 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6272 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6273 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6274 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6275 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6276 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6277 (eConnectionState_Associated ==
6278 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6279 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6280 {
6281 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006282
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306283 powerRequest.uIgnoreDTIM = 1;
6284 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6285
6286 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6287 {
6288 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6289 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6290 }
6291 else
6292 {
6293 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6294 }
6295
6296 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6297 * specified during Enter/Exit BMPS when LCD off*/
6298 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6299 NULL, eANI_BOOLEAN_FALSE);
6300 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6301 NULL, eANI_BOOLEAN_FALSE);
6302
6303 /* switch to the DTIM specified in cfg.ini */
6304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6305 "Switch to DTIM %d", powerRequest.uListenInterval);
6306 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6307 break;
6308
6309 }
6310
6311 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6312 pAdapterNode = pNext;
6313 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006314}
6315
6316void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6317{
6318 /*Switch back to DTIM 1*/
6319 tSirSetPowerParamsReq powerRequest = { 0 };
6320
6321 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6322 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006323 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006324
6325 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6326 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6327 NULL, eANI_BOOLEAN_FALSE);
6328 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6329 NULL, eANI_BOOLEAN_FALSE);
6330
6331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6332 "Switch to DTIM%d",powerRequest.uListenInterval);
6333 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6334
6335}
6336
Jeff Johnson295189b2012-06-20 16:38:30 -07006337VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6338{
6339 VOS_STATUS status = VOS_STATUS_SUCCESS;
6340
6341 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6342 {
6343 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6344 }
6345
6346 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6347 {
6348 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6349 }
6350
6351 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6352 {
6353 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6354 }
6355
6356 return status;
6357}
6358
6359VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6360{
6361 hdd_adapter_t *pAdapter = NULL;
6362 eHalStatus halStatus;
6363 VOS_STATUS status = VOS_STATUS_E_INVAL;
6364 v_BOOL_t disableBmps = FALSE;
6365 v_BOOL_t disableImps = FALSE;
6366
6367 switch(session_type)
6368 {
6369 case WLAN_HDD_INFRA_STATION:
6370 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006371 case WLAN_HDD_P2P_CLIENT:
6372 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 //Exit BMPS -> Is Sta/P2P Client is already connected
6374 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6375 if((NULL != pAdapter)&&
6376 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6377 {
6378 disableBmps = TRUE;
6379 }
6380
6381 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6382 if((NULL != pAdapter)&&
6383 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6384 {
6385 disableBmps = TRUE;
6386 }
6387
6388 //Exit both Bmps and Imps incase of Go/SAP Mode
6389 if((WLAN_HDD_SOFTAP == session_type) ||
6390 (WLAN_HDD_P2P_GO == session_type))
6391 {
6392 disableBmps = TRUE;
6393 disableImps = TRUE;
6394 }
6395
6396 if(TRUE == disableImps)
6397 {
6398 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6399 {
6400 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6401 }
6402 }
6403
6404 if(TRUE == disableBmps)
6405 {
6406 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6407 {
6408 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6409
6410 if(eHAL_STATUS_SUCCESS != halStatus)
6411 {
6412 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006413 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006414 VOS_ASSERT(0);
6415 return status;
6416 }
6417 }
6418
6419 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6420 {
6421 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6422
6423 if(eHAL_STATUS_SUCCESS != halStatus)
6424 {
6425 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006426 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006427 VOS_ASSERT(0);
6428 return status;
6429 }
6430 }
6431 }
6432
6433 if((TRUE == disableBmps) ||
6434 (TRUE == disableImps))
6435 {
6436 /* Now, get the chip into Full Power now */
6437 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6438 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6439 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6440
6441 if(halStatus != eHAL_STATUS_SUCCESS)
6442 {
6443 if(halStatus == eHAL_STATUS_PMC_PENDING)
6444 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306445 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006446 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306447 ret = wait_for_completion_interruptible_timeout(
6448 &pHddCtx->full_pwr_comp_var,
6449 msecs_to_jiffies(1000));
6450 if (ret <= 0)
6451 {
6452 hddLog(VOS_TRACE_LEVEL_ERROR,
6453 "%s: wait on full_pwr_comp_var failed %ld",
6454 __func__, ret);
6455 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006456 }
6457 else
6458 {
6459 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006460 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006461 VOS_ASSERT(0);
6462 return status;
6463 }
6464 }
6465
6466 status = VOS_STATUS_SUCCESS;
6467 }
6468
6469 break;
6470 }
6471 return status;
6472}
6473
6474hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006475 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 tANI_U8 rtnl_held )
6477{
6478 hdd_adapter_t *pAdapter = NULL;
6479 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6480 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6481 VOS_STATUS exitbmpsStatus;
6482
Arif Hussain6d2a3322013-11-17 19:50:10 -08006483 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006484
Nirav Shah436658f2014-02-28 17:05:45 +05306485 if(macAddr == NULL)
6486 {
6487 /* Not received valid macAddr */
6488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6489 "%s:Unable to add virtual intf: Not able to get"
6490 "valid mac address",__func__);
6491 return NULL;
6492 }
6493
Jeff Johnson295189b2012-06-20 16:38:30 -07006494 //Disable BMPS incase of Concurrency
6495 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6496
6497 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6498 {
6499 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306500 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006501 VOS_ASSERT(0);
6502 return NULL;
6503 }
6504
6505 switch(session_type)
6506 {
6507 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006508 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006509 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006510 {
6511 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6512
6513 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306514 {
6515 hddLog(VOS_TRACE_LEVEL_FATAL,
6516 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306518 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006519
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306520#ifdef FEATURE_WLAN_TDLS
6521 /* A Mutex Lock is introduced while changing/initializing the mode to
6522 * protect the concurrent access for the Adapters by TDLS module.
6523 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306524 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306525#endif
6526
Jeff Johnsone7245742012-09-05 17:12:55 -07006527 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6528 NL80211_IFTYPE_P2P_CLIENT:
6529 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006530
Jeff Johnson295189b2012-06-20 16:38:30 -07006531 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306532#ifdef FEATURE_WLAN_TDLS
6533 mutex_unlock(&pHddCtx->tdls_lock);
6534#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306535
6536 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006537 if( VOS_STATUS_SUCCESS != status )
6538 goto err_free_netdev;
6539
6540 status = hdd_register_interface( pAdapter, rtnl_held );
6541 if( VOS_STATUS_SUCCESS != status )
6542 {
6543 hdd_deinit_adapter(pHddCtx, pAdapter);
6544 goto err_free_netdev;
6545 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306546
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306547 // Workqueue which gets scheduled in IPv4 notification callback.
6548 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6549
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306550#ifdef WLAN_NS_OFFLOAD
6551 // Workqueue which gets scheduled in IPv6 notification callback.
6552 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6553#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006554 //Stop the Interface TX queue.
6555 netif_tx_disable(pAdapter->dev);
6556 //netif_tx_disable(pWlanDev);
6557 netif_carrier_off(pAdapter->dev);
6558
6559 break;
6560 }
6561
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006563 case WLAN_HDD_SOFTAP:
6564 {
6565 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6566 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306567 {
6568 hddLog(VOS_TRACE_LEVEL_FATAL,
6569 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006570 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306571 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006572
Jeff Johnson295189b2012-06-20 16:38:30 -07006573 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6574 NL80211_IFTYPE_AP:
6575 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006576 pAdapter->device_mode = session_type;
6577
6578 status = hdd_init_ap_mode(pAdapter);
6579 if( VOS_STATUS_SUCCESS != status )
6580 goto err_free_netdev;
6581
6582 status = hdd_register_hostapd( pAdapter, rtnl_held );
6583 if( VOS_STATUS_SUCCESS != status )
6584 {
6585 hdd_deinit_adapter(pHddCtx, pAdapter);
6586 goto err_free_netdev;
6587 }
6588
6589 netif_tx_disable(pAdapter->dev);
6590 netif_carrier_off(pAdapter->dev);
6591
6592 hdd_set_conparam( 1 );
6593 break;
6594 }
6595 case WLAN_HDD_MONITOR:
6596 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6598 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306599 {
6600 hddLog(VOS_TRACE_LEVEL_FATAL,
6601 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006602 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306603 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006604
6605 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6606 pAdapter->device_mode = session_type;
6607 status = hdd_register_interface( pAdapter, rtnl_held );
6608#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6609 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6610#else
6611 pAdapter->dev->open = hdd_mon_open;
6612 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6613#endif
6614 hdd_init_tx_rx( pAdapter );
6615 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6616 //Set adapter to be used for data tx. It will use either GO or softap.
6617 pAdapter->sessionCtx.monitor.pAdapterForTx =
6618 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6620 {
6621 pAdapter->sessionCtx.monitor.pAdapterForTx =
6622 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006624 /* This workqueue will be used to transmit management packet over
6625 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006626 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6627 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6628 return NULL;
6629 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006630
Jeff Johnson295189b2012-06-20 16:38:30 -07006631 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6632 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006633 }
6634 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006635 case WLAN_HDD_FTM:
6636 {
6637 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6638
6639 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306640 {
6641 hddLog(VOS_TRACE_LEVEL_FATAL,
6642 FL("failed to allocate adapter for session %d"), session_type);
6643 return NULL;
6644 }
6645
Jeff Johnson295189b2012-06-20 16:38:30 -07006646 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6647 * message while loading driver in FTM mode. */
6648 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6649 pAdapter->device_mode = session_type;
6650 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306651
6652 hdd_init_tx_rx( pAdapter );
6653
6654 //Stop the Interface TX queue.
6655 netif_tx_disable(pAdapter->dev);
6656 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006657 }
6658 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 default:
6660 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306661 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6662 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006663 VOS_ASSERT(0);
6664 return NULL;
6665 }
6666 }
6667
Jeff Johnson295189b2012-06-20 16:38:30 -07006668 if( VOS_STATUS_SUCCESS == status )
6669 {
6670 //Add it to the hdd's session list.
6671 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6672 if( NULL == pHddAdapterNode )
6673 {
6674 status = VOS_STATUS_E_NOMEM;
6675 }
6676 else
6677 {
6678 pHddAdapterNode->pAdapter = pAdapter;
6679 status = hdd_add_adapter_back ( pHddCtx,
6680 pHddAdapterNode );
6681 }
6682 }
6683
6684 if( VOS_STATUS_SUCCESS != status )
6685 {
6686 if( NULL != pAdapter )
6687 {
6688 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6689 pAdapter = NULL;
6690 }
6691 if( NULL != pHddAdapterNode )
6692 {
6693 vos_mem_free( pHddAdapterNode );
6694 }
6695
6696 goto resume_bmps;
6697 }
6698
6699 if(VOS_STATUS_SUCCESS == status)
6700 {
6701 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6702
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006703 //Initialize the WoWL service
6704 if(!hdd_init_wowl(pAdapter))
6705 {
6706 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6707 goto err_free_netdev;
6708 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006709 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006710 return pAdapter;
6711
6712err_free_netdev:
6713 free_netdev(pAdapter->dev);
6714 wlan_hdd_release_intf_addr( pHddCtx,
6715 pAdapter->macAddressCurrent.bytes );
6716
6717resume_bmps:
6718 //If bmps disabled enable it
6719 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6720 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306721 if (pHddCtx->hdd_wlan_suspended)
6722 {
6723 hdd_set_pwrparams(pHddCtx);
6724 }
6725 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 }
6727 return NULL;
6728}
6729
6730VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6731 tANI_U8 rtnl_held )
6732{
6733 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6734 VOS_STATUS status;
6735
6736 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6737 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306738 {
6739 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6740 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006741 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306742 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006743
6744 while ( pCurrent->pAdapter != pAdapter )
6745 {
6746 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6747 if( VOS_STATUS_SUCCESS != status )
6748 break;
6749
6750 pCurrent = pNext;
6751 }
6752 pAdapterNode = pCurrent;
6753 if( VOS_STATUS_SUCCESS == status )
6754 {
6755 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6756 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306757
6758#ifdef FEATURE_WLAN_TDLS
6759
6760 /* A Mutex Lock is introduced while changing/initializing the mode to
6761 * protect the concurrent access for the Adapters by TDLS module.
6762 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306763 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306764#endif
6765
Jeff Johnson295189b2012-06-20 16:38:30 -07006766 hdd_remove_adapter( pHddCtx, pAdapterNode );
6767 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006768 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006769
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306770#ifdef FEATURE_WLAN_TDLS
6771 mutex_unlock(&pHddCtx->tdls_lock);
6772#endif
6773
Jeff Johnson295189b2012-06-20 16:38:30 -07006774
6775 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306776 if ((!vos_concurrent_open_sessions_running()) &&
6777 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6778 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006779 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306780 if (pHddCtx->hdd_wlan_suspended)
6781 {
6782 hdd_set_pwrparams(pHddCtx);
6783 }
6784 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 }
6786
6787 return VOS_STATUS_SUCCESS;
6788 }
6789
6790 return VOS_STATUS_E_FAILURE;
6791}
6792
6793VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6794{
6795 hdd_adapter_list_node_t *pHddAdapterNode;
6796 VOS_STATUS status;
6797
6798 ENTER();
6799
6800 do
6801 {
6802 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6803 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6804 {
6805 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6806 vos_mem_free( pHddAdapterNode );
6807 }
6808 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6809
6810 EXIT();
6811
6812 return VOS_STATUS_SUCCESS;
6813}
6814
6815void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6816{
6817 v_U8_t addIE[1] = {0};
6818
6819 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6820 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6821 eANI_BOOLEAN_FALSE) )
6822 {
6823 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006824 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006825 }
6826
6827 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6828 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6829 eANI_BOOLEAN_FALSE) )
6830 {
6831 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006832 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006833 }
6834
6835 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6836 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6837 eANI_BOOLEAN_FALSE) )
6838 {
6839 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006840 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006841 }
6842}
6843
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306844VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6845 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006846{
6847 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6848 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306849 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006850 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306851 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306852 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006853
6854 ENTER();
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306855 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07006856 switch(pAdapter->device_mode)
6857 {
6858 case WLAN_HDD_INFRA_STATION:
6859 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006860 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306861 {
6862 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6863 if( hdd_connIsConnected(pstation) ||
6864 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 {
6866 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6867 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6868 pAdapter->sessionId,
6869 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6870 else
6871 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6872 pAdapter->sessionId,
6873 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6874 //success implies disconnect command got queued up successfully
6875 if(halStatus == eHAL_STATUS_SUCCESS)
6876 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306877 ret = wait_for_completion_interruptible_timeout(
6878 &pAdapter->disconnect_comp_var,
6879 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6880 if (ret <= 0)
6881 {
6882 hddLog(VOS_TRACE_LEVEL_ERROR,
6883 "%s: wait on disconnect_comp_var failed %ld",
6884 __func__, ret);
6885 }
6886 }
6887 else
6888 {
6889 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6890 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006891 }
6892 memset(&wrqu, '\0', sizeof(wrqu));
6893 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6894 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6895 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6896 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306897 else if(pstation->conn_info.connState ==
6898 eConnectionState_Disconnecting)
6899 {
6900 ret = wait_for_completion_interruptible_timeout(
6901 &pAdapter->disconnect_comp_var,
6902 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6903 if (ret <= 0)
6904 {
6905 hddLog(VOS_TRACE_LEVEL_ERROR,
6906 FL("wait on disconnect_comp_var failed %ld"), ret);
6907 }
6908 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306909 else if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07006910 {
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306911 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306912 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006913 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306914 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6915 {
6916 while (pAdapter->is_roc_inprogress)
6917 {
6918 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6919 "%s: ROC in progress for session %d!!!",
6920 __func__, pAdapter->sessionId);
6921 // waiting for ROC to expire
6922 msleep(500);
6923 /* In GO present case , if retry exceeds 3,
6924 it means something went wrong. */
6925 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6926 {
6927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6928 "%s: ROC completion is not received.!!!", __func__);
6929 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6930 pAdapter->sessionId);
6931 wait_for_completion_interruptible_timeout(
6932 &pAdapter->cancel_rem_on_chan_var,
6933 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6934 break;
6935 }
6936 }
6937 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306938#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306939#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306940 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6941#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306942 if (pAdapter->ipv6_notifier_registered)
6943 {
6944 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6945 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6946 pAdapter->ipv6_notifier_registered = false;
6947 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306948#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306949 if (pAdapter->ipv4_notifier_registered)
6950 {
6951 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6952 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6953 pAdapter->ipv4_notifier_registered = false;
6954 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306955#ifdef WLAN_OPEN_SOURCE
6956 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6957#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306958 /* It is possible that the caller of this function does not
6959 * wish to close the session
6960 */
6961 if (VOS_TRUE == bCloseSession &&
6962 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006963 {
6964 INIT_COMPLETION(pAdapter->session_close_comp_var);
6965 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306966 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6967 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306969 unsigned long ret;
6970
Jeff Johnson295189b2012-06-20 16:38:30 -07006971 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306972 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306973 &pAdapter->session_close_comp_var,
6974 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306975 if ( 0 >= ret)
6976 {
6977 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306978 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306979 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 }
6981 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306982 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006983 break;
6984
6985 case WLAN_HDD_SOFTAP:
6986 case WLAN_HDD_P2P_GO:
6987 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306988 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6989 while (pAdapter->is_roc_inprogress) {
6990 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6991 "%s: ROC in progress for session %d!!!",
6992 __func__, pAdapter->sessionId);
6993 msleep(500);
6994 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6995 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6996 "%s: ROC completion is not received.!!!", __func__);
6997 WLANSAP_CancelRemainOnChannel(
6998 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6999 wait_for_completion_interruptible_timeout(
7000 &pAdapter->cancel_rem_on_chan_var,
7001 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
7002 break;
7003 }
7004 }
7005 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007006 mutex_lock(&pHddCtx->sap_lock);
7007 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7008 {
7009 VOS_STATUS status;
7010 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7011
7012 //Stop Bss.
7013 status = WLANSAP_StopBss(pHddCtx->pvosContext);
7014 if (VOS_IS_STATUS_SUCCESS(status))
7015 {
7016 hdd_hostapd_state_t *pHostapdState =
7017 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7018
7019 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7020
7021 if (!VOS_IS_STATUS_SUCCESS(status))
7022 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307023 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
7024 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007025 }
7026 }
7027 else
7028 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007029 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007030 }
7031 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05307032 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07007033
7034 if (eHAL_STATUS_FAILURE ==
7035 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
7036 0, NULL, eANI_BOOLEAN_FALSE))
7037 {
7038 hddLog(LOGE,
7039 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007040 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 }
7042
7043 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7044 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7045 eANI_BOOLEAN_FALSE) )
7046 {
7047 hddLog(LOGE,
7048 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7049 }
7050
7051 // Reset WNI_CFG_PROBE_RSP Flags
7052 wlan_hdd_reset_prob_rspies(pAdapter);
7053 kfree(pAdapter->sessionCtx.ap.beacon);
7054 pAdapter->sessionCtx.ap.beacon = NULL;
7055 }
7056 mutex_unlock(&pHddCtx->sap_lock);
7057 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007058
Jeff Johnson295189b2012-06-20 16:38:30 -07007059 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007060#ifdef WLAN_OPEN_SOURCE
7061 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7062#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007063 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007064
Jeff Johnson295189b2012-06-20 16:38:30 -07007065 default:
7066 break;
7067 }
7068
7069 EXIT();
7070 return VOS_STATUS_SUCCESS;
7071}
7072
7073VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7074{
7075 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7076 VOS_STATUS status;
7077 hdd_adapter_t *pAdapter;
7078
7079 ENTER();
7080
7081 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7082
7083 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7084 {
7085 pAdapter = pAdapterNode->pAdapter;
7086 netif_tx_disable(pAdapter->dev);
7087 netif_carrier_off(pAdapter->dev);
7088
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307089 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007090
7091 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7092 pAdapterNode = pNext;
7093 }
7094
7095 EXIT();
7096
7097 return VOS_STATUS_SUCCESS;
7098}
7099
Rajeev Kumarf999e582014-01-09 17:33:29 -08007100
7101#ifdef FEATURE_WLAN_BATCH_SCAN
7102/**---------------------------------------------------------------------------
7103
7104 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7105 structures
7106
7107 \param - pAdapter Pointer to HDD adapter
7108
7109 \return - None
7110
7111 --------------------------------------------------------------------------*/
7112void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7113{
7114 tHddBatchScanRsp *pNode;
7115 tHddBatchScanRsp *pPrev;
7116
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307117 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007118 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307119 hddLog(VOS_TRACE_LEVEL_ERROR,
7120 "%s: Adapter context is Null", __func__);
7121 return;
7122 }
7123
7124 pNode = pAdapter->pBatchScanRsp;
7125 while (pNode)
7126 {
7127 pPrev = pNode;
7128 pNode = pNode->pNext;
7129 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007130 }
7131
7132 pAdapter->pBatchScanRsp = NULL;
7133 pAdapter->numScanList = 0;
7134 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7135 pAdapter->prev_batch_id = 0;
7136
7137 return;
7138}
7139#endif
7140
7141
Jeff Johnson295189b2012-06-20 16:38:30 -07007142VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7143{
7144 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7145 VOS_STATUS status;
7146 hdd_adapter_t *pAdapter;
7147
7148 ENTER();
7149
7150 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7151
7152 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7153 {
7154 pAdapter = pAdapterNode->pAdapter;
7155 netif_tx_disable(pAdapter->dev);
7156 netif_carrier_off(pAdapter->dev);
7157
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007158 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7159
Jeff Johnson295189b2012-06-20 16:38:30 -07007160 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307161
7162 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7163
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307164 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7165 {
7166 hdd_wmm_adapter_close( pAdapter );
7167 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7168 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007169
Rajeev Kumarf999e582014-01-09 17:33:29 -08007170#ifdef FEATURE_WLAN_BATCH_SCAN
7171 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7172 {
7173 hdd_deinit_batch_scan(pAdapter);
7174 }
7175#endif
7176
Jeff Johnson295189b2012-06-20 16:38:30 -07007177 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7178 pAdapterNode = pNext;
7179 }
7180
7181 EXIT();
7182
7183 return VOS_STATUS_SUCCESS;
7184}
7185
7186VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7187{
7188 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7189 VOS_STATUS status;
7190 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307191 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007192
7193 ENTER();
7194
7195 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7196
7197 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7198 {
7199 pAdapter = pAdapterNode->pAdapter;
7200
Kumar Anand82c009f2014-05-29 00:29:42 -07007201 hdd_wmm_init( pAdapter );
7202
Jeff Johnson295189b2012-06-20 16:38:30 -07007203 switch(pAdapter->device_mode)
7204 {
7205 case WLAN_HDD_INFRA_STATION:
7206 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007207 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307208
7209 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7210
Jeff Johnson295189b2012-06-20 16:38:30 -07007211 hdd_init_station_mode(pAdapter);
7212 /* Open the gates for HDD to receive Wext commands */
7213 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007214 pHddCtx->scan_info.mScanPending = FALSE;
7215 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007216
7217 //Trigger the initial scan
7218 hdd_wlan_initial_scan(pAdapter);
7219
7220 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307221 if (eConnectionState_Associated == connState ||
7222 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007223 {
7224 union iwreq_data wrqu;
7225 memset(&wrqu, '\0', sizeof(wrqu));
7226 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7227 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7228 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007229 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007230
Jeff Johnson295189b2012-06-20 16:38:30 -07007231 /* indicate disconnected event to nl80211 */
7232 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7233 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007234 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307235 else if (eConnectionState_Connecting == connState)
7236 {
7237 /*
7238 * Indicate connect failure to supplicant if we were in the
7239 * process of connecting
7240 */
7241 cfg80211_connect_result(pAdapter->dev, NULL,
7242 NULL, 0, NULL, 0,
7243 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7244 GFP_KERNEL);
7245 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007246 break;
7247
7248 case WLAN_HDD_SOFTAP:
7249 /* softAP can handle SSR */
7250 break;
7251
7252 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007253 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007254 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007255 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007256 break;
7257
7258 case WLAN_HDD_MONITOR:
7259 /* monitor interface start */
7260 break;
7261 default:
7262 break;
7263 }
7264
7265 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7266 pAdapterNode = pNext;
7267 }
7268
7269 EXIT();
7270
7271 return VOS_STATUS_SUCCESS;
7272}
7273
7274VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7275{
7276 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7277 hdd_adapter_t *pAdapter;
7278 VOS_STATUS status;
7279 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307280 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007281
7282 ENTER();
7283
7284 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7285
7286 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7287 {
7288 pAdapter = pAdapterNode->pAdapter;
7289
7290 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7291 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7292 {
7293 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7294 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7295
Abhishek Singhf4669da2014-05-26 15:07:49 +05307296 hddLog(VOS_TRACE_LEVEL_INFO,
7297 "%s: Set HDD connState to eConnectionState_NotConnected",
7298 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007299 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7300 init_completion(&pAdapter->disconnect_comp_var);
7301 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7302 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7303
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307304 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 &pAdapter->disconnect_comp_var,
7306 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307307 if (0 >= ret)
7308 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7309 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007310
7311 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7312 pHddCtx->isAmpAllowed = VOS_FALSE;
7313 sme_RoamConnect(pHddCtx->hHal,
7314 pAdapter->sessionId, &(pWextState->roamProfile),
7315 &roamId);
7316 }
7317
7318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7319 pAdapterNode = pNext;
7320 }
7321
7322 EXIT();
7323
7324 return VOS_STATUS_SUCCESS;
7325}
7326
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007327void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7328{
7329 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7330 VOS_STATUS status;
7331 hdd_adapter_t *pAdapter;
7332 hdd_station_ctx_t *pHddStaCtx;
7333 hdd_ap_ctx_t *pHddApCtx;
7334 hdd_hostapd_state_t * pHostapdState;
7335 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7336 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7337 const char *p2pMode = "DEV";
7338 const char *ccMode = "Standalone";
7339 int n;
7340
7341 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7342 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7343 {
7344 pAdapter = pAdapterNode->pAdapter;
7345 switch (pAdapter->device_mode) {
7346 case WLAN_HDD_INFRA_STATION:
7347 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7348 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7349 staChannel = pHddStaCtx->conn_info.operationChannel;
7350 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7351 }
7352 break;
7353 case WLAN_HDD_P2P_CLIENT:
7354 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7355 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7356 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7357 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7358 p2pMode = "CLI";
7359 }
7360 break;
7361 case WLAN_HDD_P2P_GO:
7362 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7363 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7364 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7365 p2pChannel = pHddApCtx->operatingChannel;
7366 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7367 }
7368 p2pMode = "GO";
7369 break;
7370 case WLAN_HDD_SOFTAP:
7371 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7372 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7373 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7374 apChannel = pHddApCtx->operatingChannel;
7375 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7376 }
7377 break;
7378 default:
7379 break;
7380 }
7381 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7382 pAdapterNode = pNext;
7383 }
7384 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7385 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7386 }
7387 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7388 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7389 if (p2pChannel > 0) {
7390 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7391 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7392 }
7393 if (apChannel > 0) {
7394 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7395 apChannel, MAC_ADDR_ARRAY(apBssid));
7396 }
7397
7398 if (p2pChannel > 0 && apChannel > 0) {
7399 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7400 }
7401}
7402
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007403bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007404{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007405 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007406}
7407
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007408/* Once SSR is disabled then it cannot be set. */
7409void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007410{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007411 if (HDD_SSR_DISABLED == isSsrRequired)
7412 return;
7413
Jeff Johnson295189b2012-06-20 16:38:30 -07007414 isSsrRequired = value;
7415}
7416
7417VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7418 hdd_adapter_list_node_t** ppAdapterNode)
7419{
7420 VOS_STATUS status;
7421 spin_lock(&pHddCtx->hddAdapters.lock);
7422 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7423 (hdd_list_node_t**) ppAdapterNode );
7424 spin_unlock(&pHddCtx->hddAdapters.lock);
7425 return status;
7426}
7427
7428VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7429 hdd_adapter_list_node_t* pAdapterNode,
7430 hdd_adapter_list_node_t** pNextAdapterNode)
7431{
7432 VOS_STATUS status;
7433 spin_lock(&pHddCtx->hddAdapters.lock);
7434 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7435 (hdd_list_node_t*) pAdapterNode,
7436 (hdd_list_node_t**)pNextAdapterNode );
7437
7438 spin_unlock(&pHddCtx->hddAdapters.lock);
7439 return status;
7440}
7441
7442VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7443 hdd_adapter_list_node_t* pAdapterNode)
7444{
7445 VOS_STATUS status;
7446 spin_lock(&pHddCtx->hddAdapters.lock);
7447 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7448 &pAdapterNode->node );
7449 spin_unlock(&pHddCtx->hddAdapters.lock);
7450 return status;
7451}
7452
7453VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7454 hdd_adapter_list_node_t** ppAdapterNode)
7455{
7456 VOS_STATUS status;
7457 spin_lock(&pHddCtx->hddAdapters.lock);
7458 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7459 (hdd_list_node_t**) ppAdapterNode );
7460 spin_unlock(&pHddCtx->hddAdapters.lock);
7461 return status;
7462}
7463
7464VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7465 hdd_adapter_list_node_t* pAdapterNode)
7466{
7467 VOS_STATUS status;
7468 spin_lock(&pHddCtx->hddAdapters.lock);
7469 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7470 (hdd_list_node_t*) pAdapterNode );
7471 spin_unlock(&pHddCtx->hddAdapters.lock);
7472 return status;
7473}
7474
7475VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7476 hdd_adapter_list_node_t* pAdapterNode)
7477{
7478 VOS_STATUS status;
7479 spin_lock(&pHddCtx->hddAdapters.lock);
7480 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7481 (hdd_list_node_t*) pAdapterNode );
7482 spin_unlock(&pHddCtx->hddAdapters.lock);
7483 return status;
7484}
7485
7486hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7487 tSirMacAddr macAddr )
7488{
7489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7490 hdd_adapter_t *pAdapter;
7491 VOS_STATUS status;
7492
7493 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7494
7495 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7496 {
7497 pAdapter = pAdapterNode->pAdapter;
7498
7499 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7500 macAddr, sizeof(tSirMacAddr) ) )
7501 {
7502 return pAdapter;
7503 }
7504 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7505 pAdapterNode = pNext;
7506 }
7507
7508 return NULL;
7509
7510}
7511
7512hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7513{
7514 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7515 hdd_adapter_t *pAdapter;
7516 VOS_STATUS status;
7517
7518 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7519
7520 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7521 {
7522 pAdapter = pAdapterNode->pAdapter;
7523
7524 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7525 IFNAMSIZ ) )
7526 {
7527 return pAdapter;
7528 }
7529 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7530 pAdapterNode = pNext;
7531 }
7532
7533 return NULL;
7534
7535}
7536
7537hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7538{
7539 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7540 hdd_adapter_t *pAdapter;
7541 VOS_STATUS status;
7542
7543 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7544
7545 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7546 {
7547 pAdapter = pAdapterNode->pAdapter;
7548
7549 if( pAdapter && (mode == pAdapter->device_mode) )
7550 {
7551 return pAdapter;
7552 }
7553 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7554 pAdapterNode = pNext;
7555 }
7556
7557 return NULL;
7558
7559}
7560
7561//Remove this function later
7562hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7563{
7564 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7565 hdd_adapter_t *pAdapter;
7566 VOS_STATUS status;
7567
7568 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7569
7570 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7571 {
7572 pAdapter = pAdapterNode->pAdapter;
7573
7574 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7575 {
7576 return pAdapter;
7577 }
7578
7579 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7580 pAdapterNode = pNext;
7581 }
7582
7583 return NULL;
7584
7585}
7586
Jeff Johnson295189b2012-06-20 16:38:30 -07007587/**---------------------------------------------------------------------------
7588
7589 \brief hdd_set_monitor_tx_adapter() -
7590
7591 This API initializes the adapter to be used while transmitting on monitor
7592 adapter.
7593
7594 \param - pHddCtx - Pointer to the HDD context.
7595 pAdapter - Adapter that will used for TX. This can be NULL.
7596 \return - None.
7597 --------------------------------------------------------------------------*/
7598void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7599{
7600 hdd_adapter_t *pMonAdapter;
7601
7602 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7603
7604 if( NULL != pMonAdapter )
7605 {
7606 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7607 }
7608}
Jeff Johnson295189b2012-06-20 16:38:30 -07007609/**---------------------------------------------------------------------------
7610
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307611 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007612
7613 This API returns the operating channel of the requested device mode
7614
7615 \param - pHddCtx - Pointer to the HDD context.
7616 - mode - Device mode for which operating channel is required
7617 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7618 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7619 \return - channel number. "0" id the requested device is not found OR it is not connected.
7620 --------------------------------------------------------------------------*/
7621v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7622{
7623 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7624 VOS_STATUS status;
7625 hdd_adapter_t *pAdapter;
7626 v_U8_t operatingChannel = 0;
7627
7628 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7629
7630 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7631 {
7632 pAdapter = pAdapterNode->pAdapter;
7633
7634 if( mode == pAdapter->device_mode )
7635 {
7636 switch(pAdapter->device_mode)
7637 {
7638 case WLAN_HDD_INFRA_STATION:
7639 case WLAN_HDD_P2P_CLIENT:
7640 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7641 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7642 break;
7643 case WLAN_HDD_SOFTAP:
7644 case WLAN_HDD_P2P_GO:
7645 /*softap connection info */
7646 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7647 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7648 break;
7649 default:
7650 break;
7651 }
7652
7653 break; //Found the device of interest. break the loop
7654 }
7655
7656 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7657 pAdapterNode = pNext;
7658 }
7659 return operatingChannel;
7660}
7661
7662#ifdef WLAN_FEATURE_PACKET_FILTERING
7663/**---------------------------------------------------------------------------
7664
7665 \brief hdd_set_multicast_list() -
7666
7667 This used to set the multicast address list.
7668
7669 \param - dev - Pointer to the WLAN device.
7670 - skb - Pointer to OS packet (sk_buff).
7671 \return - success/fail
7672
7673 --------------------------------------------------------------------------*/
7674static void hdd_set_multicast_list(struct net_device *dev)
7675{
7676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007677 int mc_count;
7678 int i = 0;
7679 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307680
7681 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007682 {
7683 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307684 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007685 return;
7686 }
7687
7688 if (dev->flags & IFF_ALLMULTI)
7689 {
7690 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007691 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307692 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 }
7694 else
7695 {
7696 mc_count = netdev_mc_count(dev);
7697 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007698 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7700 {
7701 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007702 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307703 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007704 return;
7705 }
7706
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307707 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007708
7709 netdev_for_each_mc_addr(ha, dev) {
7710 if (i == mc_count)
7711 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307712 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7713 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007714 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007715 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307716 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007717 i++;
7718 }
7719 }
7720 return;
7721}
7722#endif
7723
7724/**---------------------------------------------------------------------------
7725
7726 \brief hdd_select_queue() -
7727
7728 This function is registered with the Linux OS for network
7729 core to decide which queue to use first.
7730
7731 \param - dev - Pointer to the WLAN device.
7732 - skb - Pointer to OS packet (sk_buff).
7733 \return - ac, Queue Index/access category corresponding to UP in IP header
7734
7735 --------------------------------------------------------------------------*/
7736v_U16_t hdd_select_queue(struct net_device *dev,
7737 struct sk_buff *skb)
7738{
7739 return hdd_wmm_select_queue(dev, skb);
7740}
7741
7742
7743/**---------------------------------------------------------------------------
7744
7745 \brief hdd_wlan_initial_scan() -
7746
7747 This function triggers the initial scan
7748
7749 \param - pAdapter - Pointer to the HDD adapter.
7750
7751 --------------------------------------------------------------------------*/
7752void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7753{
7754 tCsrScanRequest scanReq;
7755 tCsrChannelInfo channelInfo;
7756 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007757 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007758 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7759
7760 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7761 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7762 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7763
7764 if(sme_Is11dSupported(pHddCtx->hHal))
7765 {
7766 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7767 if ( HAL_STATUS_SUCCESS( halStatus ) )
7768 {
7769 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7770 if( !scanReq.ChannelInfo.ChannelList )
7771 {
7772 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7773 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007774 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007775 return;
7776 }
7777 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7778 channelInfo.numOfChannels);
7779 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7780 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007781 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 }
7783
7784 scanReq.scanType = eSIR_PASSIVE_SCAN;
7785 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7786 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7787 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7788 }
7789 else
7790 {
7791 scanReq.scanType = eSIR_ACTIVE_SCAN;
7792 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7793 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7794 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7795 }
7796
7797 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7798 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7799 {
7800 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7801 __func__, halStatus );
7802 }
7803
7804 if(sme_Is11dSupported(pHddCtx->hHal))
7805 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7806}
7807
Jeff Johnson295189b2012-06-20 16:38:30 -07007808/**---------------------------------------------------------------------------
7809
7810 \brief hdd_full_power_callback() - HDD full power callback function
7811
7812 This is the function invoked by SME to inform the result of a full power
7813 request issued by HDD
7814
7815 \param - callbackcontext - Pointer to cookie
7816 \param - status - result of request
7817
7818 \return - None
7819
7820 --------------------------------------------------------------------------*/
7821static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7822{
Jeff Johnson72a40512013-12-19 10:14:15 -08007823 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007824
7825 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307826 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007827
7828 if (NULL == callbackContext)
7829 {
7830 hddLog(VOS_TRACE_LEVEL_ERROR,
7831 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007832 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007833 return;
7834 }
7835
Jeff Johnson72a40512013-12-19 10:14:15 -08007836 /* there is a race condition that exists between this callback
7837 function and the caller since the caller could time out either
7838 before or while this code is executing. we use a spinlock to
7839 serialize these actions */
7840 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007841
7842 if (POWER_CONTEXT_MAGIC != pContext->magic)
7843 {
7844 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007845 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007846 hddLog(VOS_TRACE_LEVEL_WARN,
7847 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007848 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007849 return;
7850 }
7851
Jeff Johnson72a40512013-12-19 10:14:15 -08007852 /* context is valid so caller is still waiting */
7853
7854 /* paranoia: invalidate the magic */
7855 pContext->magic = 0;
7856
7857 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007858 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007859
7860 /* serialization is complete */
7861 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007862}
7863
7864/**---------------------------------------------------------------------------
7865
7866 \brief hdd_wlan_exit() - HDD WLAN exit function
7867
7868 This is the driver exit point (invoked during rmmod)
7869
7870 \param - pHddCtx - Pointer to the HDD Context
7871
7872 \return - None
7873
7874 --------------------------------------------------------------------------*/
7875void hdd_wlan_exit(hdd_context_t *pHddCtx)
7876{
7877 eHalStatus halStatus;
7878 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7879 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307880 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007881 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007882 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007883 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307884 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007885
7886 ENTER();
7887
Jeff Johnson88ba7742013-02-27 14:36:02 -08007888 if (VOS_FTM_MODE != hdd_get_conparam())
7889 {
7890 // Unloading, restart logic is no more required.
7891 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007892
c_hpothu5ab05e92014-06-13 17:34:05 +05307893 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7894 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007895 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307896 pAdapter = pAdapterNode->pAdapter;
7897 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007898 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307899 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7900 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7901 {
7902 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7903 hdd_UnregisterWext(pAdapter->dev);
7904 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307905
Jeff Johnson295189b2012-06-20 16:38:30 -07007906 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307907 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7908 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007909 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307910 // Cancel any outstanding scan requests. We are about to close all
7911 // of our adapters, but an adapter structure is what SME passes back
7912 // to our callback function. Hence if there are any outstanding scan
7913 // requests then there is a race condition between when the adapter
7914 // is closed and when the callback is invoked.We try to resolve that
7915 // race condition here by canceling any outstanding scans before we
7916 // close the adapters.
7917 // Note that the scans may be cancelled in an asynchronous manner,
7918 // so ideally there needs to be some kind of synchronization. Rather
7919 // than introduce a new synchronization here, we will utilize the
7920 // fact that we are about to Request Full Power, and since that is
7921 // synchronized, the expectation is that by the time Request Full
7922 // Power has completed all scans will be cancelled.
7923 if (pHddCtx->scan_info.mScanPending)
7924 {
7925 hddLog(VOS_TRACE_LEVEL_INFO,
7926 FL("abort scan mode: %d sessionId: %d"),
7927 pAdapter->device_mode,
7928 pAdapter->sessionId);
7929 hdd_abort_mac_scan(pHddCtx,
7930 pHddCtx->scan_info.sessionId,
7931 eCSR_SCAN_ABORT_DEFAULT);
7932 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307934 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007935 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307936 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007937 wlan_hdd_ftm_close(pHddCtx);
7938 goto free_hdd_ctx;
7939 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307940
Jeff Johnson295189b2012-06-20 16:38:30 -07007941 /* DeRegister with platform driver as client for Suspend/Resume */
7942 vosStatus = hddDeregisterPmOps(pHddCtx);
7943 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7944 {
7945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7946 VOS_ASSERT(0);
7947 }
7948
7949 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7950 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7951 {
7952 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7953 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007954
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007955 //Stop the traffic monitor timer
7956 if ( VOS_TIMER_STATE_RUNNING ==
7957 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7958 {
7959 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7960 }
7961
7962 // Destroy the traffic monitor timer
7963 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7964 &pHddCtx->tx_rx_trafficTmr)))
7965 {
7966 hddLog(VOS_TRACE_LEVEL_ERROR,
7967 "%s: Cannot deallocate Traffic monitor timer", __func__);
7968 }
7969
Jeff Johnson295189b2012-06-20 16:38:30 -07007970 //Disable IMPS/BMPS as we do not want the device to enter any power
7971 //save mode during shutdown
7972 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7973 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7974 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7975
7976 //Ensure that device is in full power as we will touch H/W during vos_Stop
7977 init_completion(&powerContext.completion);
7978 powerContext.magic = POWER_CONTEXT_MAGIC;
7979
7980 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7981 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7982
7983 if (eHAL_STATUS_SUCCESS != halStatus)
7984 {
7985 if (eHAL_STATUS_PMC_PENDING == halStatus)
7986 {
7987 /* request was sent -- wait for the response */
7988 lrc = wait_for_completion_interruptible_timeout(
7989 &powerContext.completion,
7990 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007991 if (lrc <= 0)
7992 {
7993 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007994 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007995 }
7996 }
7997 else
7998 {
7999 hddLog(VOS_TRACE_LEVEL_ERROR,
8000 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008001 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07008002 /* continue -- need to clean up as much as possible */
8003 }
8004 }
8005
Jeff Johnson72a40512013-12-19 10:14:15 -08008006 /* either we never sent a request, we sent a request and received a
8007 response or we sent a request and timed out. if we never sent a
8008 request or if we sent a request and got a response, we want to
8009 clear the magic out of paranoia. if we timed out there is a
8010 race condition such that the callback function could be
8011 executing at the same time we are. of primary concern is if the
8012 callback function had already verified the "magic" but had not
8013 yet set the completion variable when a timeout occurred. we
8014 serialize these activities by invalidating the magic while
8015 holding a shared spinlock which will cause us to block if the
8016 callback is currently executing */
8017 spin_lock(&hdd_context_lock);
8018 powerContext.magic = 0;
8019 spin_unlock(&hdd_context_lock);
8020
Yue Ma0d4891e2013-08-06 17:01:45 -07008021 hdd_debugfs_exit(pHddCtx);
8022
Jeff Johnson295189b2012-06-20 16:38:30 -07008023 // Unregister the Net Device Notifier
8024 unregister_netdevice_notifier(&hdd_netdev_notifier);
8025
Jeff Johnson295189b2012-06-20 16:38:30 -07008026 hdd_stop_all_adapters( pHddCtx );
8027
Jeff Johnson295189b2012-06-20 16:38:30 -07008028#ifdef WLAN_BTAMP_FEATURE
8029 vosStatus = WLANBAP_Stop(pVosContext);
8030 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8031 {
8032 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8033 "%s: Failed to stop BAP",__func__);
8034 }
8035#endif //WLAN_BTAMP_FEATURE
8036
8037 //Stop all the modules
8038 vosStatus = vos_stop( pVosContext );
8039 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8040 {
8041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8042 "%s: Failed to stop VOSS",__func__);
8043 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8044 }
8045
Jeff Johnson295189b2012-06-20 16:38:30 -07008046 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008047 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008048
8049 //Close the scheduler before calling vos_close to make sure no thread is
8050 // scheduled after the each module close is called i.e after all the data
8051 // structures are freed.
8052 vosStatus = vos_sched_close( pVosContext );
8053 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8054 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8055 "%s: Failed to close VOSS Scheduler",__func__);
8056 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8057 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008058#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008059#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8060 /* Destroy the wake lock */
8061 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8062#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008063 /* Destroy the wake lock */
8064 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008065#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008066
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308067#ifdef CONFIG_ENABLE_LINUX_REG
8068 vosStatus = vos_nv_close();
8069 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8070 {
8071 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8072 "%s: Failed to close NV", __func__);
8073 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8074 }
8075#endif
8076
Jeff Johnson295189b2012-06-20 16:38:30 -07008077 //Close VOSS
8078 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8079 vos_close(pVosContext);
8080
Jeff Johnson295189b2012-06-20 16:38:30 -07008081 //Close Watchdog
8082 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8083 vos_watchdog_close(pVosContext);
8084
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308085 //Clean up HDD Nlink Service
8086 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308087
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308088#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308089 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308090 {
8091 wlan_logging_sock_deactivate_svc();
8092 }
8093#endif
8094
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308095#ifdef WLAN_KD_READY_NOTIFIER
8096 nl_srv_exit(pHddCtx->ptt_pid);
8097#else
8098 nl_srv_exit();
8099#endif /* WLAN_KD_READY_NOTIFIER */
8100
8101
Jeff Johnson295189b2012-06-20 16:38:30 -07008102 hdd_close_all_adapters( pHddCtx );
8103
Jeff Johnson295189b2012-06-20 16:38:30 -07008104 /* free the power on lock from platform driver */
8105 if (free_riva_power_on_lock("wlan"))
8106 {
8107 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8108 __func__);
8109 }
8110
Jeff Johnson88ba7742013-02-27 14:36:02 -08008111free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308112
8113 //Free up dynamically allocated members inside HDD Adapter
8114 if (pHddCtx->cfg_ini)
8115 {
8116 kfree(pHddCtx->cfg_ini);
8117 pHddCtx->cfg_ini= NULL;
8118 }
8119
Leo Changf04ddad2013-09-18 13:46:38 -07008120 /* FTM mode, WIPHY did not registered
8121 If un-register here, system crash will happen */
8122 if (VOS_FTM_MODE != hdd_get_conparam())
8123 {
8124 wiphy_unregister(wiphy) ;
8125 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008126 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008127 if (hdd_is_ssr_required())
8128 {
8129 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008130 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008131 msleep(5000);
8132 }
8133 hdd_set_ssr_required (VOS_FALSE);
8134}
8135
8136
8137/**---------------------------------------------------------------------------
8138
8139 \brief hdd_update_config_from_nv() - Function to update the contents of
8140 the running configuration with parameters taken from NV storage
8141
8142 \param - pHddCtx - Pointer to the HDD global context
8143
8144 \return - VOS_STATUS_SUCCESS if successful
8145
8146 --------------------------------------------------------------------------*/
8147static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8148{
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 v_BOOL_t itemIsValid = VOS_FALSE;
8150 VOS_STATUS status;
8151 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8152 v_U8_t macLoop;
8153
8154 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8155 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8156 if(status != VOS_STATUS_SUCCESS)
8157 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008158 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008159 return VOS_STATUS_E_FAILURE;
8160 }
8161
8162 if (itemIsValid == VOS_TRUE)
8163 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008164 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008165 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8166 VOS_MAX_CONCURRENCY_PERSONA);
8167 if(status != VOS_STATUS_SUCCESS)
8168 {
8169 /* Get MAC from NV fail, not update CFG info
8170 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008171 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008172 return VOS_STATUS_E_FAILURE;
8173 }
8174
8175 /* If first MAC is not valid, treat all others are not valid
8176 * Then all MACs will be got from ini file */
8177 if(vos_is_macaddr_zero(&macFromNV[0]))
8178 {
8179 /* MAC address in NV file is not configured yet */
8180 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8181 return VOS_STATUS_E_INVAL;
8182 }
8183
8184 /* Get MAC address from NV, update CFG info */
8185 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8186 {
8187 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8188 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308189 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008190 /* This MAC is not valid, skip it
8191 * This MAC will be got from ini file */
8192 }
8193 else
8194 {
8195 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8196 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8197 VOS_MAC_ADDR_SIZE);
8198 }
8199 }
8200 }
8201 else
8202 {
8203 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8204 return VOS_STATUS_E_FAILURE;
8205 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008206
Jeff Johnson295189b2012-06-20 16:38:30 -07008207
8208 return VOS_STATUS_SUCCESS;
8209}
8210
8211/**---------------------------------------------------------------------------
8212
8213 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8214
8215 \param - pAdapter - Pointer to the HDD
8216
8217 \return - None
8218
8219 --------------------------------------------------------------------------*/
8220VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8221{
8222 eHalStatus halStatus;
8223 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308224 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008225
Jeff Johnson295189b2012-06-20 16:38:30 -07008226
8227 // Send ready indication to the HDD. This will kick off the MAC
8228 // into a 'running' state and should kick off an initial scan.
8229 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8230 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8231 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308232 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008233 "code %08d [x%08x]",__func__, halStatus, halStatus );
8234 return VOS_STATUS_E_FAILURE;
8235 }
8236
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308237 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008238 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8239 // And RIVA will crash
8240 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8241 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308242 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8243 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8244
8245
Jeff Johnson295189b2012-06-20 16:38:30 -07008246 return VOS_STATUS_SUCCESS;
8247}
8248
Jeff Johnson295189b2012-06-20 16:38:30 -07008249/* wake lock APIs for HDD */
8250void hdd_prevent_suspend(void)
8251{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008252#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008253 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008254#else
8255 wcnss_prevent_suspend();
8256#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008257}
8258
8259void hdd_allow_suspend(void)
8260{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008261#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008262 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008263#else
8264 wcnss_allow_suspend();
8265#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008266}
8267
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308268void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008269{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008270#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008271 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008272#else
8273 /* Do nothing as there is no API in wcnss for timeout*/
8274#endif
8275}
8276
Jeff Johnson295189b2012-06-20 16:38:30 -07008277/**---------------------------------------------------------------------------
8278
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008279 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8280 information between Host and Riva
8281
8282 This function gets reported version of FW
8283 It also finds the version of Riva headers used to compile the host
8284 It compares the above two and prints a warning if they are different
8285 It gets the SW and HW version string
8286 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8287 indicating the features they support through a bitmap
8288
8289 \param - pHddCtx - Pointer to HDD context
8290
8291 \return - void
8292
8293 --------------------------------------------------------------------------*/
8294
8295void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8296{
8297
8298 tSirVersionType versionCompiled;
8299 tSirVersionType versionReported;
8300 tSirVersionString versionString;
8301 tANI_U8 fwFeatCapsMsgSupported = 0;
8302 VOS_STATUS vstatus;
8303
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008304 memset(&versionCompiled, 0, sizeof(versionCompiled));
8305 memset(&versionReported, 0, sizeof(versionReported));
8306
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008307 /* retrieve and display WCNSS version information */
8308 do {
8309
8310 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8311 &versionCompiled);
8312 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8313 {
8314 hddLog(VOS_TRACE_LEVEL_FATAL,
8315 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008316 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008317 break;
8318 }
8319
8320 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8321 &versionReported);
8322 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8323 {
8324 hddLog(VOS_TRACE_LEVEL_FATAL,
8325 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008326 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008327 break;
8328 }
8329
8330 if ((versionCompiled.major != versionReported.major) ||
8331 (versionCompiled.minor != versionReported.minor) ||
8332 (versionCompiled.version != versionReported.version) ||
8333 (versionCompiled.revision != versionReported.revision))
8334 {
8335 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8336 "Host expected %u.%u.%u.%u\n",
8337 WLAN_MODULE_NAME,
8338 (int)versionReported.major,
8339 (int)versionReported.minor,
8340 (int)versionReported.version,
8341 (int)versionReported.revision,
8342 (int)versionCompiled.major,
8343 (int)versionCompiled.minor,
8344 (int)versionCompiled.version,
8345 (int)versionCompiled.revision);
8346 }
8347 else
8348 {
8349 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8350 WLAN_MODULE_NAME,
8351 (int)versionReported.major,
8352 (int)versionReported.minor,
8353 (int)versionReported.version,
8354 (int)versionReported.revision);
8355 }
8356
8357 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8358 versionString,
8359 sizeof(versionString));
8360 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8361 {
8362 hddLog(VOS_TRACE_LEVEL_FATAL,
8363 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008364 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008365 break;
8366 }
8367
8368 pr_info("%s: WCNSS software version %s\n",
8369 WLAN_MODULE_NAME, versionString);
8370
8371 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8372 versionString,
8373 sizeof(versionString));
8374 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8375 {
8376 hddLog(VOS_TRACE_LEVEL_FATAL,
8377 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008378 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008379 break;
8380 }
8381
8382 pr_info("%s: WCNSS hardware version %s\n",
8383 WLAN_MODULE_NAME, versionString);
8384
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008385 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8386 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008387 send the message only if it the riva is 1.1
8388 minor numbers for different riva branches:
8389 0 -> (1.0)Mainline Build
8390 1 -> (1.1)Mainline Build
8391 2->(1.04) Stability Build
8392 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008393 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008394 ((versionReported.minor>=1) && (versionReported.version>=1)))
8395 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8396 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008397
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008398 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008399 {
8400#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8401 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8402 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8403#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008404 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8405 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8406 {
8407 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8408 }
8409
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008410 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008411 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008412
8413 } while (0);
8414
8415}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308416void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8417{
8418 struct sk_buff *skb;
8419 struct nlmsghdr *nlh;
8420 tAniMsgHdr *ani_hdr;
8421
8422 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8423
8424 if(skb == NULL) {
8425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8426 "%s: alloc_skb failed", __func__);
8427 return;
8428 }
8429
8430 nlh = (struct nlmsghdr *)skb->data;
8431 nlh->nlmsg_pid = 0; /* from kernel */
8432 nlh->nlmsg_flags = 0;
8433 nlh->nlmsg_seq = 0;
8434 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8435
8436 ani_hdr = NLMSG_DATA(nlh);
8437 ani_hdr->type = type;
8438
8439 switch(type) {
8440 case WLAN_SVC_SAP_RESTART_IND:
8441 ani_hdr->length = 0;
8442 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8443 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8444 break;
8445 default:
8446 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8447 "Attempt to send unknown nlink message %d", type);
8448 kfree_skb(skb);
8449 return;
8450 }
8451
8452 nl_srv_bcast(skb);
8453
8454 return;
8455}
8456
8457
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008458
8459/**---------------------------------------------------------------------------
8460
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308461 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8462
8463 \param - pHddCtx - Pointer to the hdd context
8464
8465 \return - true if hardware supports 5GHz
8466
8467 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308468boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308469{
8470 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8471 * then hardware support 5Ghz.
8472 */
8473 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8474 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308475 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308476 return true;
8477 }
8478 else
8479 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308480 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308481 __func__);
8482 return false;
8483 }
8484}
8485
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308486/**---------------------------------------------------------------------------
8487
8488 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8489 generate function
8490
8491 This is generate the random mac address for WLAN interface
8492
8493 \param - pHddCtx - Pointer to HDD context
8494 idx - Start interface index to get auto
8495 generated mac addr.
8496 mac_addr - Mac address
8497
8498 \return - 0 for success, < 0 for failure
8499
8500 --------------------------------------------------------------------------*/
8501
8502static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8503 int idx, v_MACADDR_t mac_addr)
8504{
8505 int i;
8506 unsigned int serialno;
8507 serialno = wcnss_get_serial_number();
8508
8509 if (0 != serialno)
8510 {
8511 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8512 bytes of the serial number that can be used to generate
8513 the other 3 bytes of the MAC address. Mask off all but
8514 the lower 3 bytes (this will also make sure we don't
8515 overflow in the next step) */
8516 serialno &= 0x00FFFFFF;
8517
8518 /* we need a unique address for each session */
8519 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8520
8521 /* autogen other Mac addresses */
8522 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8523 {
8524 /* start with the entire default address */
8525 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8526 /* then replace the lower 3 bytes */
8527 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8528 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8529 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8530
8531 serialno++;
8532 hddLog(VOS_TRACE_LEVEL_ERROR,
8533 "%s: Derived Mac Addr: "
8534 MAC_ADDRESS_STR, __func__,
8535 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8536 }
8537
8538 }
8539 else
8540 {
8541 hddLog(LOGE, FL("Failed to Get Serial NO"));
8542 return -1;
8543 }
8544 return 0;
8545}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308546
8547/**---------------------------------------------------------------------------
8548
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308549 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8550 completed to flush out the scan results
8551
8552 11d scan is done during driver load and is a passive scan on all
8553 channels supported by the device, 11d scans may find some APs on
8554 frequencies which are forbidden to be used in the regulatory domain
8555 the device is operating in. If these APs are notified to the supplicant
8556 it may try to connect to these APs, thus flush out all the scan results
8557 which are present in SME after 11d scan is done.
8558
8559 \return - eHalStatus
8560
8561 --------------------------------------------------------------------------*/
8562static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8563 tANI_U32 scanId, eCsrScanStatus status)
8564{
8565 ENTER();
8566
8567 sme_ScanFlushResult(halHandle, 0);
8568
8569 EXIT();
8570
8571 return eHAL_STATUS_SUCCESS;
8572}
8573
8574/**---------------------------------------------------------------------------
8575
Jeff Johnson295189b2012-06-20 16:38:30 -07008576 \brief hdd_wlan_startup() - HDD init function
8577
8578 This is the driver startup code executed once a WLAN device has been detected
8579
8580 \param - dev - Pointer to the underlying device
8581
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008582 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008583
8584 --------------------------------------------------------------------------*/
8585
8586int hdd_wlan_startup(struct device *dev )
8587{
8588 VOS_STATUS status;
8589 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008590 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008591 hdd_context_t *pHddCtx = NULL;
8592 v_CONTEXT_t pVosContext= NULL;
8593#ifdef WLAN_BTAMP_FEATURE
8594 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8595 WLANBAP_ConfigType btAmpConfig;
8596 hdd_config_t *pConfig;
8597#endif
8598 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008599 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308600 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008601
8602 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 /*
8604 * cfg80211: wiphy allocation
8605 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308606 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008607
8608 if(wiphy == NULL)
8609 {
8610 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008611 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008612 }
8613
8614 pHddCtx = wiphy_priv(wiphy);
8615
Jeff Johnson295189b2012-06-20 16:38:30 -07008616 //Initialize the adapter context to zeros.
8617 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8618
Jeff Johnson295189b2012-06-20 16:38:30 -07008619 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008620 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308621 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008622
8623 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8624
8625 /*Get vos context here bcoz vos_open requires it*/
8626 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8627
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008628 if(pVosContext == NULL)
8629 {
8630 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8631 goto err_free_hdd_context;
8632 }
8633
Jeff Johnson295189b2012-06-20 16:38:30 -07008634 //Save the Global VOSS context in adapter context for future.
8635 pHddCtx->pvosContext = pVosContext;
8636
8637 //Save the adapter context in global context for future.
8638 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8639
Jeff Johnson295189b2012-06-20 16:38:30 -07008640 pHddCtx->parent_dev = dev;
8641
8642 init_completion(&pHddCtx->full_pwr_comp_var);
8643 init_completion(&pHddCtx->standby_comp_var);
8644 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008645 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008646 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308647 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308648 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008649
8650#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008651 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008652#else
8653 init_completion(&pHddCtx->driver_crda_req);
8654#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008655
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308656 spin_lock_init(&pHddCtx->schedScan_lock);
8657
Jeff Johnson295189b2012-06-20 16:38:30 -07008658 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8659
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308660#ifdef FEATURE_WLAN_TDLS
8661 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8662 * invoked by other instances also) to protect the concurrent
8663 * access for the Adapters by TDLS module.
8664 */
8665 mutex_init(&pHddCtx->tdls_lock);
8666#endif
Siddharth Bhal76972212014-10-15 16:22:51 +05308667 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Agarwal Ashish1f422872014-07-22 00:11:55 +05308668 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308669
Agarwal Ashish1f422872014-07-22 00:11:55 +05308670 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 // Load all config first as TL config is needed during vos_open
8672 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8673 if(pHddCtx->cfg_ini == NULL)
8674 {
8675 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8676 goto err_free_hdd_context;
8677 }
8678
8679 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8680
8681 // Read and parse the qcom_cfg.ini file
8682 status = hdd_parse_config_ini( pHddCtx );
8683 if ( VOS_STATUS_SUCCESS != status )
8684 {
8685 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8686 __func__, WLAN_INI_FILE);
8687 goto err_config;
8688 }
Arif Hussaind5218912013-12-05 01:10:55 -08008689#ifdef MEMORY_DEBUG
8690 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8691 vos_mem_init();
8692
8693 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8694 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8695#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008696
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308697 /* INI has been read, initialise the configuredMcastBcastFilter with
8698 * INI value as this will serve as the default value
8699 */
8700 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8701 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8702 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308703
8704 if (false == hdd_is_5g_supported(pHddCtx))
8705 {
8706 //5Ghz is not supported.
8707 if (1 != pHddCtx->cfg_ini->nBandCapability)
8708 {
8709 hddLog(VOS_TRACE_LEVEL_INFO,
8710 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8711 pHddCtx->cfg_ini->nBandCapability = 1;
8712 }
8713 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308714
8715 /* If SNR Monitoring is enabled, FW has to parse all beacons
8716 * for calcaluting and storing the average SNR, so set Nth beacon
8717 * filter to 1 to enable FW to parse all the beaocons
8718 */
8719 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8720 {
8721 /* The log level is deliberately set to WARN as overriding
8722 * nthBeaconFilter to 1 will increase power cosumption and this
8723 * might just prove helpful to detect the power issue.
8724 */
8725 hddLog(VOS_TRACE_LEVEL_WARN,
8726 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8727 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8728 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008729 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308730 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008731 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008732 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008733 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008734 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8735 {
8736 hddLog(VOS_TRACE_LEVEL_FATAL,
8737 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8738 goto err_config;
8739 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008740 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008741
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008742 // Update VOS trace levels based upon the cfg.ini
8743 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8744 pHddCtx->cfg_ini->vosTraceEnableBAP);
8745 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8746 pHddCtx->cfg_ini->vosTraceEnableTL);
8747 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8748 pHddCtx->cfg_ini->vosTraceEnableWDI);
8749 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8750 pHddCtx->cfg_ini->vosTraceEnableHDD);
8751 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8752 pHddCtx->cfg_ini->vosTraceEnableSME);
8753 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8754 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308755 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8756 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008757 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8758 pHddCtx->cfg_ini->vosTraceEnableWDA);
8759 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8760 pHddCtx->cfg_ini->vosTraceEnableSYS);
8761 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8762 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008763 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8764 pHddCtx->cfg_ini->vosTraceEnableSAP);
8765 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8766 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008767
Jeff Johnson295189b2012-06-20 16:38:30 -07008768 // Update WDI trace levels based upon the cfg.ini
8769 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8770 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8771 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8772 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8773 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8774 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8775 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8776 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008777
Jeff Johnson88ba7742013-02-27 14:36:02 -08008778 if (VOS_FTM_MODE == hdd_get_conparam())
8779 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008780 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8781 {
8782 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8783 goto err_free_hdd_context;
8784 }
8785 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308786
8787 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008788 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008789 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008790
Jeff Johnson88ba7742013-02-27 14:36:02 -08008791 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008792 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8793 {
8794 status = vos_watchdog_open(pVosContext,
8795 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8796
8797 if(!VOS_IS_STATUS_SUCCESS( status ))
8798 {
8799 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308800 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008801 }
8802 }
8803
8804 pHddCtx->isLogpInProgress = FALSE;
8805 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8806
Amar Singhala49cbc52013-10-08 18:37:44 -07008807#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008808 /* initialize the NV module. This is required so that
8809 we can initialize the channel information in wiphy
8810 from the NV.bin data. The channel information in
8811 wiphy needs to be initialized before wiphy registration */
8812
8813 status = vos_nv_open();
8814 if (!VOS_IS_STATUS_SUCCESS(status))
8815 {
8816 /* NV module cannot be initialized */
8817 hddLog( VOS_TRACE_LEVEL_FATAL,
8818 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05308819 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07008820 }
8821
8822 status = vos_init_wiphy_from_nv_bin();
8823 if (!VOS_IS_STATUS_SUCCESS(status))
8824 {
8825 /* NV module cannot be initialized */
8826 hddLog( VOS_TRACE_LEVEL_FATAL,
8827 "%s: vos_init_wiphy failed", __func__);
8828 goto err_vos_nv_close;
8829 }
8830
Amar Singhala49cbc52013-10-08 18:37:44 -07008831#endif
8832
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308833 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008834 if ( !VOS_IS_STATUS_SUCCESS( status ))
8835 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308837 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008838 }
8839
Jeff Johnson295189b2012-06-20 16:38:30 -07008840 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8841
8842 if ( NULL == pHddCtx->hHal )
8843 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008844 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008845 goto err_vosclose;
8846 }
8847
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008848 status = vos_preStart( pHddCtx->pvosContext );
8849 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8850 {
8851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308852 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008853 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008854
Arif Hussaineaf68602013-12-30 23:10:44 -08008855 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8856 {
8857 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8858 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8859 __func__, enable_dfs_chan_scan);
8860 }
8861 if (0 == enable_11d || 1 == enable_11d)
8862 {
8863 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8864 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8865 __func__, enable_11d);
8866 }
8867
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008868 /* Note that the vos_preStart() sequence triggers the cfg download.
8869 The cfg download must occur before we update the SME config
8870 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008871 status = hdd_set_sme_config( pHddCtx );
8872
8873 if ( VOS_STATUS_SUCCESS != status )
8874 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008875 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308876 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008877 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008878
Jeff Johnson295189b2012-06-20 16:38:30 -07008879 /* In the integrated architecture we update the configuration from
8880 the INI file and from NV before vOSS has been started so that
8881 the final contents are available to send down to the cCPU */
8882
8883 // Apply the cfg.ini to cfg.dat
8884 if (FALSE == hdd_update_config_dat(pHddCtx))
8885 {
8886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308887 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008888 }
8889
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308890 // Get mac addr from platform driver
8891 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8892
8893 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008894 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308895 /* Store the mac addr for first interface */
8896 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8897
8898 hddLog(VOS_TRACE_LEVEL_ERROR,
8899 "%s: WLAN Mac Addr: "
8900 MAC_ADDRESS_STR, __func__,
8901 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8902
8903 /* Here, passing Arg2 as 1 because we do not want to change the
8904 last 3 bytes (means non OUI bytes) of first interface mac
8905 addr.
8906 */
8907 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8908 {
8909 hddLog(VOS_TRACE_LEVEL_ERROR,
8910 "%s: Failed to generate wlan interface mac addr "
8911 "using MAC from ini file ", __func__);
8912 }
8913 }
8914 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8915 {
8916 // Apply the NV to cfg.dat
8917 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008918#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8919 /* There was not a valid set of MAC Addresses in NV. See if the
8920 default addresses were modified by the cfg.ini settings. If so,
8921 we'll use them, but if not, we'll autogenerate a set of MAC
8922 addresses based upon the device serial number */
8923
8924 static const v_MACADDR_t default_address =
8925 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008926
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308927 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8928 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008929 {
8930 /* cfg.ini has the default address, invoke autogen logic */
8931
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308932 /* Here, passing Arg2 as 0 because we want to change the
8933 last 3 bytes (means non OUI bytes) of all the interfaces
8934 mac addr.
8935 */
8936 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8937 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008938 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308939 hddLog(VOS_TRACE_LEVEL_ERROR,
8940 "%s: Failed to generate wlan interface mac addr "
8941 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8942 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008944 }
8945 else
8946#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8947 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008948 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008949 "%s: Invalid MAC address in NV, using MAC from ini file "
8950 MAC_ADDRESS_STR, __func__,
8951 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8952 }
8953 }
8954 {
8955 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308956
8957 /* Set the MAC Address Currently this is used by HAL to
8958 * add self sta. Remove this once self sta is added as
8959 * part of session open.
8960 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008961 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8962 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8963 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308964
Jeff Johnson295189b2012-06-20 16:38:30 -07008965 if (!HAL_STATUS_SUCCESS( halStatus ))
8966 {
8967 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8968 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308969 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008970 }
8971 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008972
8973 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8974 Note: Firmware image will be read and downloaded inside vos_start API */
8975 status = vos_start( pHddCtx->pvosContext );
8976 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8977 {
8978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308979 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008980 }
8981
Leo Chang6cec3e22014-01-21 15:33:49 -08008982#ifdef FEATURE_WLAN_CH_AVOID
8983 /* Plug in avoid channel notification callback
8984 * This should happen before ADD_SELF_STA
8985 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308986
8987 /* check the Channel Avoidance is enabled */
8988 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8989 {
8990 sme_AddChAvoidCallback(pHddCtx->hHal,
8991 hdd_hostapd_ch_avoid_cb);
8992 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008993#endif /* FEATURE_WLAN_CH_AVOID */
8994
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008995 /* Exchange capability info between Host and FW and also get versioning info from FW */
8996 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008997
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308998#ifdef CONFIG_ENABLE_LINUX_REG
8999 status = wlan_hdd_init_channels(pHddCtx);
9000 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9001 {
9002 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
9003 __func__);
9004 goto err_vosstop;
9005 }
9006#endif
9007
Jeff Johnson295189b2012-06-20 16:38:30 -07009008 status = hdd_post_voss_start_config( pHddCtx );
9009 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9010 {
9011 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
9012 __func__);
9013 goto err_vosstop;
9014 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009015
9016#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309017 wlan_hdd_cfg80211_update_reg_info( wiphy );
9018
9019 /* registration of wiphy dev with cfg80211 */
9020 if (0 > wlan_hdd_cfg80211_register(wiphy))
9021 {
9022 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9023 goto err_vosstop;
9024 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009025#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009026
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309027#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309028 /* registration of wiphy dev with cfg80211 */
9029 if (0 > wlan_hdd_cfg80211_register(wiphy))
9030 {
9031 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9032 goto err_vosstop;
9033 }
9034
Agarwal Ashish6db9d532014-09-30 18:19:10 +05309035 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309036 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9037 {
9038 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
9039 __func__);
9040 goto err_unregister_wiphy;
9041 }
9042#endif
9043
Jeff Johnson295189b2012-06-20 16:38:30 -07009044 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9045 {
9046 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9047 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9048 }
9049 else
9050 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009051 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9052 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9053 if (pAdapter != NULL)
9054 {
kaidde69982014-06-18 13:23:21 +08009055 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009056 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309057 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9058 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9059 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009060
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309061 /* Generate the P2P Device Address. This consists of the device's
9062 * primary MAC address with the locally administered bit set.
9063 */
9064 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009065 }
9066 else
9067 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309068 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9069 if (p2p_dev_addr != NULL)
9070 {
9071 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9072 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9073 }
9074 else
9075 {
9076 hddLog(VOS_TRACE_LEVEL_FATAL,
9077 "%s: Failed to allocate mac_address for p2p_device",
9078 __func__);
9079 goto err_close_adapter;
9080 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009081 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009082
9083 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9084 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9085 if ( NULL == pP2pAdapter )
9086 {
9087 hddLog(VOS_TRACE_LEVEL_FATAL,
9088 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009089 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009090 goto err_close_adapter;
9091 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009093 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009094
9095 if( pAdapter == NULL )
9096 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9098 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009099 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009100
Arif Hussain66559122013-11-21 10:11:40 -08009101 if (country_code)
9102 {
9103 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009104 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009105 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9106#ifndef CONFIG_ENABLE_LINUX_REG
9107 hdd_checkandupdate_phymode(pAdapter, country_code);
9108#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009109 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9110 (void *)(tSmeChangeCountryCallback)
9111 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009112 country_code,
9113 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309114 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009115 if (eHAL_STATUS_SUCCESS == ret)
9116 {
Arif Hussaincb607082013-12-20 11:57:42 -08009117 ret = wait_for_completion_interruptible_timeout(
9118 &pAdapter->change_country_code,
9119 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9120
9121 if (0 >= ret)
9122 {
9123 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9124 "%s: SME while setting country code timed out", __func__);
9125 }
Arif Hussain66559122013-11-21 10:11:40 -08009126 }
9127 else
9128 {
Arif Hussaincb607082013-12-20 11:57:42 -08009129 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9130 "%s: SME Change Country code from module param fail ret=%d",
9131 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009132 }
9133 }
9134
Jeff Johnson295189b2012-06-20 16:38:30 -07009135#ifdef WLAN_BTAMP_FEATURE
9136 vStatus = WLANBAP_Open(pVosContext);
9137 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9138 {
9139 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9140 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009141 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009142 }
9143
9144 vStatus = BSL_Init(pVosContext);
9145 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9146 {
9147 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9148 "%s: Failed to Init BSL",__func__);
9149 goto err_bap_close;
9150 }
9151 vStatus = WLANBAP_Start(pVosContext);
9152 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9153 {
9154 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9155 "%s: Failed to start TL",__func__);
9156 goto err_bap_close;
9157 }
9158
9159 pConfig = pHddCtx->cfg_ini;
9160 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9161 status = WLANBAP_SetConfig(&btAmpConfig);
9162
9163#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009164
Mihir Shete9c238772014-10-15 14:35:16 +05309165 /*
9166 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
9167 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
9168 * which is greater than 0xf. So the below check is safe to make
9169 * sure that there is no entry for UapsdMask in the ini
9170 */
9171 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
9172 {
9173 if(IS_DYNAMIC_WMM_PS_ENABLED)
9174 {
9175 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
9176 __func__);
9177 pHddCtx->cfg_ini->UapsdMask =
9178 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
9179 }
9180 else
9181 {
9182 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
9183 __func__);
9184 pHddCtx->cfg_ini->UapsdMask =
9185 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
9186 }
9187 }
9188
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009189#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9190 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9191 {
9192 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9193 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9194 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9195 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9196 }
9197#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009198
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309199 wlan_hdd_tdls_init(pHddCtx);
9200
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309201 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9202
Jeff Johnson295189b2012-06-20 16:38:30 -07009203 /* Register with platform driver as client for Suspend/Resume */
9204 status = hddRegisterPmOps(pHddCtx);
9205 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9206 {
9207 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9208#ifdef WLAN_BTAMP_FEATURE
9209 goto err_bap_stop;
9210#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009211 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009212#endif //WLAN_BTAMP_FEATURE
9213 }
9214
Yue Ma0d4891e2013-08-06 17:01:45 -07009215 /* Open debugfs interface */
9216 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9217 {
9218 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9219 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009220 }
9221
Jeff Johnson295189b2012-06-20 16:38:30 -07009222 /* Register TM level change handler function to the platform */
9223 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9224 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9225 {
9226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9227 goto err_unregister_pmops;
9228 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009229
9230 /* register for riva power on lock to platform driver */
9231 if (req_riva_power_on_lock("wlan"))
9232 {
9233 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9234 __func__);
9235 goto err_unregister_pmops;
9236 }
9237
Jeff Johnson295189b2012-06-20 16:38:30 -07009238 // register net device notifier for device change notification
9239 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9240
9241 if(ret < 0)
9242 {
9243 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9244 goto err_free_power_on_lock;
9245 }
9246
9247 //Initialize the nlink service
9248 if(nl_srv_init() != 0)
9249 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309250 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009251 goto err_reg_netdev;
9252 }
9253
Leo Chang4ce1cc52013-10-21 18:27:15 -07009254#ifdef WLAN_KD_READY_NOTIFIER
9255 pHddCtx->kd_nl_init = 1;
9256#endif /* WLAN_KD_READY_NOTIFIER */
9257
Jeff Johnson295189b2012-06-20 16:38:30 -07009258 //Initialize the BTC service
9259 if(btc_activate_service(pHddCtx) != 0)
9260 {
9261 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9262 goto err_nl_srv;
9263 }
9264
9265#ifdef PTT_SOCK_SVC_ENABLE
9266 //Initialize the PTT service
9267 if(ptt_sock_activate_svc(pHddCtx) != 0)
9268 {
9269 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9270 goto err_nl_srv;
9271 }
9272#endif
9273
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309274#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9275 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9276 {
Deepthi Gowri78083a32014-11-04 12:55:51 +05309277 if(wlan_logging_sock_activate_svc(
9278 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9279 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9280 {
9281 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9282 " failed", __func__);
9283 goto err_nl_srv;
9284 }
9285 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
9286 //EAPOL and DHCP
9287 pHddCtx->cfg_ini->enableDhcpDebug = CFG_DEBUG_DHCP_ENABLE;
9288 pHddCtx->cfg_ini->gEnableDebugLog = VOS_PKT_PROTO_TYPE_EAPOL;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309289 }
9290#endif
9291
Jeff Johnson295189b2012-06-20 16:38:30 -07009292 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009293 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009294 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009295 /* Action frame registered in one adapter which will
9296 * applicable to all interfaces
9297 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309298 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009299 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009300
9301 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +05309302 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009303
Jeff Johnson295189b2012-06-20 16:38:30 -07009304
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009305#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009306#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9307 /* Initialize the wake lcok */
9308 wake_lock_init(&pHddCtx->rx_wake_lock,
9309 WAKE_LOCK_SUSPEND,
9310 "qcom_rx_wakelock");
9311#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009312 /* Initialize the wake lcok */
9313 wake_lock_init(&pHddCtx->sap_wake_lock,
9314 WAKE_LOCK_SUSPEND,
9315 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009316#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009317
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009318 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9319 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009320
Katya Nigam5c306ea2014-06-19 15:39:54 +05309321 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009322 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9323 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309324
9325#ifdef FEATURE_WLAN_SCAN_PNO
9326 /*SME must send channel update configuration to RIVA*/
9327 sme_UpdateChannelConfig(pHddCtx->hHal);
9328#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309329 /* Send the update default channel list to the FW*/
9330 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309331#ifndef CONFIG_ENABLE_LINUX_REG
9332 /*updating wiphy so that regulatory user hints can be processed*/
9333 if (wiphy)
9334 {
9335 regulatory_hint(wiphy, "00");
9336 }
9337#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009338 // Initialize the restart logic
9339 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309340
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009341 //Register the traffic monitor timer now
9342 if ( pHddCtx->cfg_ini->dynSplitscan)
9343 {
9344 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9345 VOS_TIMER_TYPE_SW,
9346 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9347 (void *)pHddCtx);
9348 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309349#ifdef WLAN_FEATURE_EXTSCAN
9350 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9351 wlan_hdd_cfg80211_extscan_callback,
9352 pHddCtx);
9353#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009354 goto success;
9355
9356err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009357#ifdef WLAN_KD_READY_NOTIFIER
9358 nl_srv_exit(pHddCtx->ptt_pid);
9359#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009360 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009361#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009362err_reg_netdev:
9363 unregister_netdevice_notifier(&hdd_netdev_notifier);
9364
9365err_free_power_on_lock:
9366 free_riva_power_on_lock("wlan");
9367
9368err_unregister_pmops:
9369 hddDevTmUnregisterNotifyCallback(pHddCtx);
9370 hddDeregisterPmOps(pHddCtx);
9371
Yue Ma0d4891e2013-08-06 17:01:45 -07009372 hdd_debugfs_exit(pHddCtx);
9373
Jeff Johnson295189b2012-06-20 16:38:30 -07009374#ifdef WLAN_BTAMP_FEATURE
9375err_bap_stop:
9376 WLANBAP_Stop(pVosContext);
9377#endif
9378
9379#ifdef WLAN_BTAMP_FEATURE
9380err_bap_close:
9381 WLANBAP_Close(pVosContext);
9382#endif
9383
Jeff Johnson295189b2012-06-20 16:38:30 -07009384err_close_adapter:
9385 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309386#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309387err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309388#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309389 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009390err_vosstop:
9391 vos_stop(pVosContext);
9392
Amar Singhala49cbc52013-10-08 18:37:44 -07009393err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009394 status = vos_sched_close( pVosContext );
9395 if (!VOS_IS_STATUS_SUCCESS(status)) {
9396 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9397 "%s: Failed to close VOSS Scheduler", __func__);
9398 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9399 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009400 vos_close(pVosContext );
9401
Amar Singhal0a402232013-10-11 20:57:16 -07009402err_vos_nv_close:
9403
c_hpothue6a36282014-03-19 12:27:38 +05309404#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009405 vos_nv_close();
9406
c_hpothu70f8d812014-03-22 22:59:23 +05309407#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009408
9409err_wdclose:
9410 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9411 vos_watchdog_close(pVosContext);
9412
Jeff Johnson295189b2012-06-20 16:38:30 -07009413err_config:
9414 kfree(pHddCtx->cfg_ini);
9415 pHddCtx->cfg_ini= NULL;
9416
9417err_free_hdd_context:
9418 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009419 wiphy_free(wiphy) ;
9420 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009421 VOS_BUG(1);
9422
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009423 if (hdd_is_ssr_required())
9424 {
9425 /* WDI timeout had happened during load, so SSR is needed here */
9426 subsystem_restart("wcnss");
9427 msleep(5000);
9428 }
9429 hdd_set_ssr_required (VOS_FALSE);
9430
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009431 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009432
9433success:
9434 EXIT();
9435 return 0;
9436}
9437
9438/**---------------------------------------------------------------------------
9439
Jeff Johnson32d95a32012-09-10 13:15:23 -07009440 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009441
Jeff Johnson32d95a32012-09-10 13:15:23 -07009442 This is the driver entry point - called in different timeline depending
9443 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009444
9445 \param - None
9446
9447 \return - 0 for success, non zero for failure
9448
9449 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009450static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009451{
9452 VOS_STATUS status;
9453 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009454 struct device *dev = NULL;
9455 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009456#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9457 int max_retries = 0;
9458#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009459
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309460#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9461 wlan_logging_sock_init_svc();
9462#endif
9463
Jeff Johnson295189b2012-06-20 16:38:30 -07009464 ENTER();
9465
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009466#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009467 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009468#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009469
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309470 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009471 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9472 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9473
Jeff Johnson295189b2012-06-20 16:38:30 -07009474#ifdef ANI_BUS_TYPE_PCI
9475
9476 dev = wcnss_wlan_get_device();
9477
9478#endif // ANI_BUS_TYPE_PCI
9479
9480#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009481
9482#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9483 /* wait until WCNSS driver downloads NV */
9484 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9485 msleep(1000);
9486 }
9487 if (max_retries >= 5) {
9488 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309489#ifdef WLAN_OPEN_SOURCE
9490 wake_lock_destroy(&wlan_wake_lock);
9491#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309492
9493#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9494 wlan_logging_sock_deinit_svc();
9495#endif
9496
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009497 return -ENODEV;
9498 }
9499#endif
9500
Jeff Johnson295189b2012-06-20 16:38:30 -07009501 dev = wcnss_wlan_get_device();
9502#endif // ANI_BUS_TYPE_PLATFORM
9503
9504
9505 do {
9506 if (NULL == dev) {
9507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9508 ret_status = -1;
9509 break;
9510 }
9511
Jeff Johnson295189b2012-06-20 16:38:30 -07009512#ifdef TIMER_MANAGER
9513 vos_timer_manager_init();
9514#endif
9515
9516 /* Preopen VOSS so that it is ready to start at least SAL */
9517 status = vos_preOpen(&pVosContext);
9518
9519 if (!VOS_IS_STATUS_SUCCESS(status))
9520 {
9521 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9522 ret_status = -1;
9523 break;
9524 }
9525
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009526#ifndef MODULE
9527 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9528 */
9529 hdd_set_conparam((v_UINT_t)con_mode);
9530#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009531
9532 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009533 if (hdd_wlan_startup(dev))
9534 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009535 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009536 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009537 vos_preClose( &pVosContext );
9538 ret_status = -1;
9539 break;
9540 }
9541
Jeff Johnson295189b2012-06-20 16:38:30 -07009542 } while (0);
9543
9544 if (0 != ret_status)
9545 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009546#ifdef TIMER_MANAGER
9547 vos_timer_exit();
9548#endif
9549#ifdef MEMORY_DEBUG
9550 vos_mem_exit();
9551#endif
9552
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009553#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009554 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009555#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309556
9557#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9558 wlan_logging_sock_deinit_svc();
9559#endif
9560
Jeff Johnson295189b2012-06-20 16:38:30 -07009561 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9562 }
9563 else
9564 {
9565 //Send WLAN UP indication to Nlink Service
9566 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9567
9568 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009569 }
9570
9571 EXIT();
9572
9573 return ret_status;
9574}
9575
Jeff Johnson32d95a32012-09-10 13:15:23 -07009576/**---------------------------------------------------------------------------
9577
9578 \brief hdd_module_init() - Init Function
9579
9580 This is the driver entry point (invoked when module is loaded using insmod)
9581
9582 \param - None
9583
9584 \return - 0 for success, non zero for failure
9585
9586 --------------------------------------------------------------------------*/
9587#ifdef MODULE
9588static int __init hdd_module_init ( void)
9589{
9590 return hdd_driver_init();
9591}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009592#else /* #ifdef MODULE */
9593static int __init hdd_module_init ( void)
9594{
9595 /* Driver initialization is delayed to fwpath_changed_handler */
9596 return 0;
9597}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009598#endif /* #ifdef MODULE */
9599
Jeff Johnson295189b2012-06-20 16:38:30 -07009600
9601/**---------------------------------------------------------------------------
9602
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009603 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009604
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009605 This is the driver exit point (invoked when module is unloaded using rmmod
9606 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009607
9608 \param - None
9609
9610 \return - None
9611
9612 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009613static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009614{
9615 hdd_context_t *pHddCtx = NULL;
9616 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309617 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309618 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009619
9620 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9621
9622 //Get the global vos context
9623 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9624
9625 if(!pVosContext)
9626 {
9627 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9628 goto done;
9629 }
9630
9631 //Get the HDD context.
9632 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9633
9634 if(!pHddCtx)
9635 {
9636 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9637 }
9638 else
9639 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309640 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9641
9642 if (pHddCtx->isLogpInProgress)
9643 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309645 "%s:SSR in Progress; block rmmod !!!", __func__);
9646 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9647 msecs_to_jiffies(30000));
9648 if(!rc)
9649 {
9650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9651 "%s:SSR timedout, fatal error", __func__);
9652 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009653 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309654 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009655
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309656 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309657 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009658 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309659 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009660
Agarwal Ashish8db39882014-07-30 21:56:07 +05309661 /* Driver Need to send country code 00 in below condition
9662 * 1) If gCountryCodePriority is set to 1; and last country
9663 * code set is through 11d. This needs to be done in case
9664 * when NV country code is 00.
9665 * This Needs to be done as when kernel store last country
9666 * code and if stored country code is not through 11d,
9667 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9668 * in next load/unload as soon as we get any country through
9669 * 11d. In sme_HandleChangeCountryCodeByUser
9670 * pMsg->countryCode will be last countryCode and
9671 * pMac->scan.countryCode11d will be country through 11d so
9672 * due to mismatch driver will disable 11d.
9673 *
Agarwal Ashish8db39882014-07-30 21:56:07 +05309674 */
9675
9676 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309677 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +05309678 sme_Is11dSupported(pHddCtx->hHal)))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309679 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309680 hddLog(VOS_TRACE_LEVEL_INFO,
9681 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309682 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9683 }
9684
Jeff Johnson295189b2012-06-20 16:38:30 -07009685 //Do all the cleanup before deregistering the driver
9686 hdd_wlan_exit(pHddCtx);
9687 }
9688
Jeff Johnson295189b2012-06-20 16:38:30 -07009689 vos_preClose( &pVosContext );
9690
9691#ifdef TIMER_MANAGER
9692 vos_timer_exit();
9693#endif
9694#ifdef MEMORY_DEBUG
9695 vos_mem_exit();
9696#endif
9697
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309698#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9699 wlan_logging_sock_deinit_svc();
9700#endif
9701
Jeff Johnson295189b2012-06-20 16:38:30 -07009702done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009703#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009704 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009705#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309706
Jeff Johnson295189b2012-06-20 16:38:30 -07009707 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9708}
9709
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009710/**---------------------------------------------------------------------------
9711
9712 \brief hdd_module_exit() - Exit function
9713
9714 This is the driver exit point (invoked when module is unloaded using rmmod)
9715
9716 \param - None
9717
9718 \return - None
9719
9720 --------------------------------------------------------------------------*/
9721static void __exit hdd_module_exit(void)
9722{
9723 hdd_driver_exit();
9724}
9725
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009726#ifdef MODULE
9727static int fwpath_changed_handler(const char *kmessage,
9728 struct kernel_param *kp)
9729{
Jeff Johnson76052702013-04-16 13:55:05 -07009730 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009731}
9732
9733static int con_mode_handler(const char *kmessage,
9734 struct kernel_param *kp)
9735{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009736 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009737}
9738#else /* #ifdef MODULE */
9739/**---------------------------------------------------------------------------
9740
Jeff Johnson76052702013-04-16 13:55:05 -07009741 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009742
Jeff Johnson76052702013-04-16 13:55:05 -07009743 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009744 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009745 - invoked when module parameter fwpath is modified from userspace to signal
9746 initializing the WLAN driver or when con_mode is modified from userspace
9747 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009748
9749 \return - 0 for success, non zero for failure
9750
9751 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009752static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009753{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009754 int ret_status;
9755
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009756 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009757 ret_status = hdd_driver_init();
9758 wlan_hdd_inited = ret_status ? 0 : 1;
9759 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009760 }
9761
9762 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009763
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009764 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009765
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009766 ret_status = hdd_driver_init();
9767 wlan_hdd_inited = ret_status ? 0 : 1;
9768 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009769}
9770
Jeff Johnson295189b2012-06-20 16:38:30 -07009771/**---------------------------------------------------------------------------
9772
Jeff Johnson76052702013-04-16 13:55:05 -07009773 \brief fwpath_changed_handler() - Handler Function
9774
9775 Handle changes to the fwpath parameter
9776
9777 \return - 0 for success, non zero for failure
9778
9779 --------------------------------------------------------------------------*/
9780static int fwpath_changed_handler(const char *kmessage,
9781 struct kernel_param *kp)
9782{
9783 int ret;
9784
9785 ret = param_set_copystring(kmessage, kp);
9786 if (0 == ret)
9787 ret = kickstart_driver();
9788 return ret;
9789}
9790
9791/**---------------------------------------------------------------------------
9792
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009793 \brief con_mode_handler() -
9794
9795 Handler function for module param con_mode when it is changed by userspace
9796 Dynamically linked - do nothing
9797 Statically linked - exit and init driver, as in rmmod and insmod
9798
Jeff Johnson76052702013-04-16 13:55:05 -07009799 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009800
Jeff Johnson76052702013-04-16 13:55:05 -07009801 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009802
9803 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009804static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009805{
Jeff Johnson76052702013-04-16 13:55:05 -07009806 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009807
Jeff Johnson76052702013-04-16 13:55:05 -07009808 ret = param_set_int(kmessage, kp);
9809 if (0 == ret)
9810 ret = kickstart_driver();
9811 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009812}
9813#endif /* #ifdef MODULE */
9814
9815/**---------------------------------------------------------------------------
9816
Jeff Johnson295189b2012-06-20 16:38:30 -07009817 \brief hdd_get_conparam() -
9818
9819 This is the driver exit point (invoked when module is unloaded using rmmod)
9820
9821 \param - None
9822
9823 \return - tVOS_CON_MODE
9824
9825 --------------------------------------------------------------------------*/
9826tVOS_CON_MODE hdd_get_conparam ( void )
9827{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009828#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009829 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009830#else
9831 return (tVOS_CON_MODE)curr_con_mode;
9832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009833}
9834void hdd_set_conparam ( v_UINT_t newParam )
9835{
9836 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009837#ifndef MODULE
9838 curr_con_mode = con_mode;
9839#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009840}
9841/**---------------------------------------------------------------------------
9842
9843 \brief hdd_softap_sta_deauth() - function
9844
9845 This to take counter measure to handle deauth req from HDD
9846
9847 \param - pAdapter - Pointer to the HDD
9848
9849 \param - enable - boolean value
9850
9851 \return - None
9852
9853 --------------------------------------------------------------------------*/
9854
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309855VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
9856 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -07009857{
Jeff Johnson295189b2012-06-20 16:38:30 -07009858 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009859 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009860
9861 ENTER();
9862
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009863 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9864 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009865
9866 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309867 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009868 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009869
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309870 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -07009871
9872 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009873 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009874}
9875
9876/**---------------------------------------------------------------------------
9877
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309878 \brief hdd_del_all_sta() - function
9879
9880 This function removes all the stations associated on stopping AP/P2P GO.
9881
9882 \param - pAdapter - Pointer to the HDD
9883
9884 \return - None
9885
9886 --------------------------------------------------------------------------*/
9887
9888int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9889{
9890 v_U16_t i;
9891 VOS_STATUS vos_status;
9892
9893 ENTER();
9894
9895 hddLog(VOS_TRACE_LEVEL_INFO,
9896 "%s: Delete all STAs associated.",__func__);
9897 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9898 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9899 )
9900 {
9901 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9902 {
9903 if ((pAdapter->aStaInfo[i].isUsed) &&
9904 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9905 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309906 struct tagCsrDelStaParams delStaParams;
9907
9908 WLANSAP_PopulateDelStaParams(
9909 pAdapter->aStaInfo[i].macAddrSTA.bytes,
9910 eCsrForcedDeauthSta, SIR_MAC_MGMT_DEAUTH >> 4,
9911 &delStaParams);
9912 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309913 if (VOS_IS_STATUS_SUCCESS(vos_status))
9914 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9915 }
9916 }
9917 }
9918
9919 EXIT();
9920 return 0;
9921}
9922
9923/**---------------------------------------------------------------------------
9924
Jeff Johnson295189b2012-06-20 16:38:30 -07009925 \brief hdd_softap_sta_disassoc() - function
9926
9927 This to take counter measure to handle deauth req from HDD
9928
9929 \param - pAdapter - Pointer to the HDD
9930
9931 \param - enable - boolean value
9932
9933 \return - None
9934
9935 --------------------------------------------------------------------------*/
9936
9937void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9938{
9939 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9940
9941 ENTER();
9942
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309943 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009944
9945 //Ignore request to disassoc bcmc station
9946 if( pDestMacAddress[0] & 0x1 )
9947 return;
9948
9949 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9950}
9951
9952void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9953{
9954 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9955
9956 ENTER();
9957
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309958 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009959
9960 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9961}
9962
Jeff Johnson295189b2012-06-20 16:38:30 -07009963/**---------------------------------------------------------------------------
9964 *
9965 * \brief hdd_get__concurrency_mode() -
9966 *
9967 *
9968 * \param - None
9969 *
9970 * \return - CONCURRENCY MODE
9971 *
9972 * --------------------------------------------------------------------------*/
9973tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9974{
9975 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9976 hdd_context_t *pHddCtx;
9977
9978 if (NULL != pVosContext)
9979 {
9980 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9981 if (NULL != pHddCtx)
9982 {
9983 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9984 }
9985 }
9986
9987 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009988 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009989 return VOS_STA;
9990}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309991v_BOOL_t
9992wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9993{
9994 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009995
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309996 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9997 if (pAdapter == NULL)
9998 {
9999 hddLog(VOS_TRACE_LEVEL_INFO,
10000 FL("GO doesn't exist"));
10001 return TRUE;
10002 }
10003 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10004 {
10005 hddLog(VOS_TRACE_LEVEL_INFO,
10006 FL("GO started"));
10007 return TRUE;
10008 }
10009 else
10010 /* wait till GO changes its interface to p2p device */
10011 hddLog(VOS_TRACE_LEVEL_INFO,
10012 FL("Del_bss called, avoid apps suspend"));
10013 return FALSE;
10014
10015}
Jeff Johnson295189b2012-06-20 16:38:30 -070010016/* Decide whether to allow/not the apps power collapse.
10017 * Allow apps power collapse if we are in connected state.
10018 * if not, allow only if we are in IMPS */
10019v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
10020{
10021 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080010022 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010023 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070010024 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10025 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10026 hdd_adapter_t *pAdapter = NULL;
10027 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080010028 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010029
Jeff Johnson295189b2012-06-20 16:38:30 -070010030 if (VOS_STA_SAP_MODE == hdd_get_conparam())
10031 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010032
Yathish9f22e662012-12-10 14:21:35 -080010033 concurrent_state = hdd_get_concurrency_mode();
10034
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010035 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
10036 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
10037 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080010038#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010039
Yathish9f22e662012-12-10 14:21:35 -080010040 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010041 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080010042 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
10043 return TRUE;
10044#endif
10045
Jeff Johnson295189b2012-06-20 16:38:30 -070010046 /*loop through all adapters. TBD fix for Concurrency */
10047 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10048 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10049 {
10050 pAdapter = pAdapterNode->pAdapter;
10051 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10052 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10053 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010054 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010055 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010056 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010057 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10058 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010059 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010060 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010061 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10062 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010063 return FALSE;
10064 }
10065 }
10066 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10067 pAdapterNode = pNext;
10068 }
10069 return TRUE;
10070}
10071
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010072/* Decides whether to send suspend notification to Riva
10073 * if any adapter is in BMPS; then it is required */
10074v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10075{
10076 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10077 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10078
10079 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10080 {
10081 return TRUE;
10082 }
10083 return FALSE;
10084}
10085
Jeff Johnson295189b2012-06-20 16:38:30 -070010086void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10087{
10088 switch(mode)
10089 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010090 case VOS_STA_MODE:
10091 case VOS_P2P_CLIENT_MODE:
10092 case VOS_P2P_GO_MODE:
10093 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010094 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010095 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010096 break;
10097 default:
10098 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010099 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010100 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10101 "Number of open sessions for mode %d = %d"),
10102 pHddCtx->concurrency_mode, mode,
10103 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010104}
10105
10106
10107void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10108{
10109 switch(mode)
10110 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010111 case VOS_STA_MODE:
10112 case VOS_P2P_CLIENT_MODE:
10113 case VOS_P2P_GO_MODE:
10114 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010115 pHddCtx->no_of_open_sessions[mode]--;
10116 if (!(pHddCtx->no_of_open_sessions[mode]))
10117 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010118 break;
10119 default:
10120 break;
10121 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010122 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10123 "Number of open sessions for mode %d = %d"),
10124 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10125
10126}
10127/**---------------------------------------------------------------------------
10128 *
10129 * \brief wlan_hdd_incr_active_session()
10130 *
10131 * This function increments the number of active sessions
10132 * maintained per device mode
10133 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10134 * Incase of SAP/P2P GO upon bss start it is incremented
10135 *
10136 * \param pHddCtx - HDD Context
10137 * \param mode - device mode
10138 *
10139 * \return - None
10140 *
10141 * --------------------------------------------------------------------------*/
10142void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10143{
10144 switch (mode) {
10145 case VOS_STA_MODE:
10146 case VOS_P2P_CLIENT_MODE:
10147 case VOS_P2P_GO_MODE:
10148 case VOS_STA_SAP_MODE:
10149 pHddCtx->no_of_active_sessions[mode]++;
10150 break;
10151 default:
10152 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10153 break;
10154 }
10155 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10156 mode,
10157 pHddCtx->no_of_active_sessions[mode]);
10158}
10159
10160/**---------------------------------------------------------------------------
10161 *
10162 * \brief wlan_hdd_decr_active_session()
10163 *
10164 * This function decrements the number of active sessions
10165 * maintained per device mode
10166 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10167 * Incase of SAP/P2P GO upon bss stop it is decremented
10168 *
10169 * \param pHddCtx - HDD Context
10170 * \param mode - device mode
10171 *
10172 * \return - None
10173 *
10174 * --------------------------------------------------------------------------*/
10175void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10176{
10177 switch (mode) {
10178 case VOS_STA_MODE:
10179 case VOS_P2P_CLIENT_MODE:
10180 case VOS_P2P_GO_MODE:
10181 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010182 if (pHddCtx->no_of_active_sessions[mode] > 0)
10183 pHddCtx->no_of_active_sessions[mode]--;
10184 else
10185 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10186 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010187 break;
10188 default:
10189 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10190 break;
10191 }
10192 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10193 mode,
10194 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010195}
10196
Jeff Johnsone7245742012-09-05 17:12:55 -070010197/**---------------------------------------------------------------------------
10198 *
10199 * \brief wlan_hdd_restart_init
10200 *
10201 * This function initalizes restart timer/flag. An internal function.
10202 *
10203 * \param - pHddCtx
10204 *
10205 * \return - None
10206 *
10207 * --------------------------------------------------------------------------*/
10208
10209static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10210{
10211 /* Initialize */
10212 pHddCtx->hdd_restart_retries = 0;
10213 atomic_set(&pHddCtx->isRestartInProgress, 0);
10214 vos_timer_init(&pHddCtx->hdd_restart_timer,
10215 VOS_TIMER_TYPE_SW,
10216 wlan_hdd_restart_timer_cb,
10217 pHddCtx);
10218}
10219/**---------------------------------------------------------------------------
10220 *
10221 * \brief wlan_hdd_restart_deinit
10222 *
10223 * This function cleans up the resources used. An internal function.
10224 *
10225 * \param - pHddCtx
10226 *
10227 * \return - None
10228 *
10229 * --------------------------------------------------------------------------*/
10230
10231static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10232{
10233
10234 VOS_STATUS vos_status;
10235 /* Block any further calls */
10236 atomic_set(&pHddCtx->isRestartInProgress, 1);
10237 /* Cleanup */
10238 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10239 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010240 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010241 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10242 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010243 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010244
10245}
10246
10247/**---------------------------------------------------------------------------
10248 *
10249 * \brief wlan_hdd_framework_restart
10250 *
10251 * This function uses a cfg80211 API to start a framework initiated WLAN
10252 * driver module unload/load.
10253 *
10254 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10255 *
10256 *
10257 * \param - pHddCtx
10258 *
10259 * \return - VOS_STATUS_SUCCESS: Success
10260 * VOS_STATUS_E_EMPTY: Adapter is Empty
10261 * VOS_STATUS_E_NOMEM: No memory
10262
10263 * --------------------------------------------------------------------------*/
10264
10265static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10266{
10267 VOS_STATUS status = VOS_STATUS_SUCCESS;
10268 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010269 int len = (sizeof (struct ieee80211_mgmt));
10270 struct ieee80211_mgmt *mgmt = NULL;
10271
10272 /* Prepare the DEAUTH managment frame with reason code */
10273 mgmt = kzalloc(len, GFP_KERNEL);
10274 if(mgmt == NULL)
10275 {
10276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10277 "%s: memory allocation failed (%d bytes)", __func__, len);
10278 return VOS_STATUS_E_NOMEM;
10279 }
10280 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010281
10282 /* Iterate over all adapters/devices */
10283 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10284 do
10285 {
10286 if( (status == VOS_STATUS_SUCCESS) &&
10287 pAdapterNode &&
10288 pAdapterNode->pAdapter)
10289 {
10290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10291 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10292 pAdapterNode->pAdapter->dev->name,
10293 pAdapterNode->pAdapter->device_mode,
10294 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010295 /*
10296 * CFG80211 event to restart the driver
10297 *
10298 * 'cfg80211_send_unprot_deauth' sends a
10299 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10300 * of SME(Linux Kernel) state machine.
10301 *
10302 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10303 * the driver.
10304 *
10305 */
10306
10307 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010308 }
10309 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10310 pAdapterNode = pNext;
10311 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10312
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010313
10314 /* Free the allocated management frame */
10315 kfree(mgmt);
10316
Jeff Johnsone7245742012-09-05 17:12:55 -070010317 /* Retry until we unload or reach max count */
10318 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10319 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10320
10321 return status;
10322
10323}
10324/**---------------------------------------------------------------------------
10325 *
10326 * \brief wlan_hdd_restart_timer_cb
10327 *
10328 * Restart timer callback. An internal function.
10329 *
10330 * \param - User data:
10331 *
10332 * \return - None
10333 *
10334 * --------------------------------------------------------------------------*/
10335
10336void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10337{
10338 hdd_context_t *pHddCtx = usrDataForCallback;
10339 wlan_hdd_framework_restart(pHddCtx);
10340 return;
10341
10342}
10343
10344
10345/**---------------------------------------------------------------------------
10346 *
10347 * \brief wlan_hdd_restart_driver
10348 *
10349 * This function sends an event to supplicant to restart the WLAN driver.
10350 *
10351 * This function is called from vos_wlanRestart.
10352 *
10353 * \param - pHddCtx
10354 *
10355 * \return - VOS_STATUS_SUCCESS: Success
10356 * VOS_STATUS_E_EMPTY: Adapter is Empty
10357 * VOS_STATUS_E_ALREADY: Request already in progress
10358
10359 * --------------------------------------------------------------------------*/
10360VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10361{
10362 VOS_STATUS status = VOS_STATUS_SUCCESS;
10363
10364 /* A tight check to make sure reentrancy */
10365 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10366 {
Mihir Shetefd528652014-06-23 19:07:50 +053010367 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010368 "%s: WLAN restart is already in progress", __func__);
10369
10370 return VOS_STATUS_E_ALREADY;
10371 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010372 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010373#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010374 wcnss_reset_intr();
10375#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010376
Jeff Johnsone7245742012-09-05 17:12:55 -070010377 return status;
10378}
10379
Mihir Shetee1093ba2014-01-21 20:13:32 +053010380/**---------------------------------------------------------------------------
10381 *
10382 * \brief wlan_hdd_init_channels
10383 *
10384 * This function is used to initialize the channel list in CSR
10385 *
10386 * This function is called from hdd_wlan_startup
10387 *
10388 * \param - pHddCtx: HDD context
10389 *
10390 * \return - VOS_STATUS_SUCCESS: Success
10391 * VOS_STATUS_E_FAULT: Failure reported by SME
10392
10393 * --------------------------------------------------------------------------*/
10394static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10395{
10396 eHalStatus status;
10397
10398 status = sme_InitChannels(pHddCtx->hHal);
10399 if (HAL_STATUS_SUCCESS(status))
10400 {
10401 return VOS_STATUS_SUCCESS;
10402 }
10403 else
10404 {
10405 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10406 __func__, status);
10407 return VOS_STATUS_E_FAULT;
10408 }
10409}
10410
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010411VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010412{
10413 eHalStatus status;
10414
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010415 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010416 if (HAL_STATUS_SUCCESS(status))
10417 {
10418 return VOS_STATUS_SUCCESS;
10419 }
10420 else
10421 {
10422 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10423 __func__, status);
10424 return VOS_STATUS_E_FAULT;
10425 }
10426}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010427/*
10428 * API to find if there is any STA or P2P-Client is connected
10429 */
10430VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10431{
10432 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10433}
Jeff Johnsone7245742012-09-05 17:12:55 -070010434
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010435int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10436{
10437 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10438 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010439 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010440
10441 pScanInfo = &pHddCtx->scan_info;
10442 if (pScanInfo->mScanPending)
10443 {
10444 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010445 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010446 eCSR_SCAN_ABORT_DEFAULT);
10447
10448 status = wait_for_completion_interruptible_timeout(
10449 &pScanInfo->abortscan_event_var,
10450 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010451 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010452 {
10453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010454 "%s: Timeout or Interrupt occurred while waiting for abort"
10455 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010456 return -ETIMEDOUT;
10457 }
10458 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010459 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010460}
10461
c_hpothu225aa7c2014-10-22 17:45:13 +053010462VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
10463{
10464 hdd_adapter_t *pAdapter;
10465 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10466 VOS_STATUS vosStatus;
10467
10468 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10469 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
10470 {
10471 pAdapter = pAdapterNode->pAdapter;
10472 if (NULL != pAdapter)
10473 {
10474 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
10475 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
10476 WLAN_HDD_P2P_GO == pAdapter->device_mode)
10477 {
10478 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
10479 pAdapter->device_mode);
10480 if (VOS_STATUS_SUCCESS !=
10481 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
10482 {
10483 hddLog(LOGE, FL("failed to abort ROC"));
10484 return VOS_STATUS_E_FAILURE;
10485 }
10486 }
10487 }
10488 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10489 pAdapterNode = pNext;
10490 }
10491 return VOS_STATUS_SUCCESS;
10492}
Jeff Johnson295189b2012-06-20 16:38:30 -070010493//Register the module init/exit functions
10494module_init(hdd_module_init);
10495module_exit(hdd_module_exit);
10496
10497MODULE_LICENSE("Dual BSD/GPL");
10498MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10499MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10500
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010501module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10502 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010503
Jeff Johnson76052702013-04-16 13:55:05 -070010504module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010505 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010506
10507module_param(enable_dfs_chan_scan, int,
10508 S_IRUSR | S_IRGRP | S_IROTH);
10509
10510module_param(enable_11d, int,
10511 S_IRUSR | S_IRGRP | S_IROTH);
10512
10513module_param(country_code, charp,
10514 S_IRUSR | S_IRGRP | S_IROTH);