blob: 60308128e71d4c424b1d98a4fda5e705e9b22598 [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 {
1842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1843 "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 {
1887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1888 "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;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002127 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002128
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002129 /*
2130 * Note that valid pointers are provided by caller
2131 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002132
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002133 /* copy to local struct to avoid numerous changes to legacy code */
2134 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002135
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002136 if (priv_data.total_len <= 0 ||
2137 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002138 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002139 hddLog(VOS_TRACE_LEVEL_WARN,
2140 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2141 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002142 ret = -EINVAL;
2143 goto exit;
2144 }
2145
2146 /* Allocate +1 for '\0' */
2147 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002148 if (!command)
2149 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002150 hddLog(VOS_TRACE_LEVEL_ERROR,
2151 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002152 ret = -ENOMEM;
2153 goto exit;
2154 }
2155
2156 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2157 {
2158 ret = -EFAULT;
2159 goto exit;
2160 }
2161
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002162 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002163 command[priv_data.total_len] = '\0';
2164
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002165 /* at one time the following block of code was conditional. braces
2166 * have been retained to avoid re-indenting the legacy code
2167 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002168 {
2169 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2170
2171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002172 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002173
2174 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2175 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302176 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2177 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2178 pAdapter->sessionId, (unsigned)
2179 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2180 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2181 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2182 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002183 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2184 sizeof(tSirMacAddr)))
2185 {
2186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002187 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002188 ret = -EFAULT;
2189 }
2190 }
Amar Singhal0974e402013-02-12 14:27:46 -08002191 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002192 {
Amar Singhal0974e402013-02-12 14:27:46 -08002193 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002194
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002196
2197 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002200 "%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 -07002201 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002202 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302203 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302204 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002205 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002206 }
Kiet Lamf040f472013-11-20 21:15:23 +05302207 else if(strncmp(command, "SETWMMPS", 8) == 0)
2208 {
2209 tANI_U8 *ptr = command;
2210 ret = hdd_wmmps_helper(pAdapter, ptr);
2211 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002212 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2213 {
2214 char *country_code;
2215
2216 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002217
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002218 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002219 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002220#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302221 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002222#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002223 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2224 (void *)(tSmeChangeCountryCallback)
2225 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302226 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002227 if (eHAL_STATUS_SUCCESS == ret)
2228 {
2229 ret = wait_for_completion_interruptible_timeout(
2230 &pAdapter->change_country_code,
2231 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2232 if (0 >= ret)
2233 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002234 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302235 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002236 }
2237 }
2238 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002239 {
2240 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002241 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002242 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002243 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002244
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002245 }
2246 /*
2247 command should be a string having format
2248 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2249 */
Amar Singhal0974e402013-02-12 14:27:46 -08002250 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002251 {
Amar Singhal0974e402013-02-12 14:27:46 -08002252 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002253
2254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002255 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002256
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002257 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002258 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002259 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2260 {
2261 int suspend = 0;
2262 tANI_U8 *ptr = (tANI_U8*)command + 15;
2263
2264 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302265 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2266 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2267 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002268 hdd_set_wlan_suspend_mode(suspend);
2269 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002270#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2271 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2272 {
2273 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002274 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002275 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2276 eHalStatus status = eHAL_STATUS_SUCCESS;
2277
2278 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2279 value = value + 15;
2280
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002281 /* Convert the value from ascii to integer */
2282 ret = kstrtos8(value, 10, &rssi);
2283 if (ret < 0)
2284 {
2285 /* If the input value is greater than max value of datatype, then also
2286 kstrtou8 fails */
2287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2288 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002289 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002290 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2291 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2292 ret = -EINVAL;
2293 goto exit;
2294 }
2295
Srinivas Girigowdade697412013-02-14 16:31:48 -08002296 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002297
Srinivas Girigowdade697412013-02-14 16:31:48 -08002298 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2299 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2300 {
2301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2302 "Neighbor lookup threshold value %d is out of range"
2303 " (Min: %d Max: %d)", lookUpThreshold,
2304 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2305 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2306 ret = -EINVAL;
2307 goto exit;
2308 }
2309
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302310 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2311 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2312 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2314 "%s: Received Command to Set Roam trigger"
2315 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2316
2317 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2318 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2319 if (eHAL_STATUS_SUCCESS != status)
2320 {
2321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2322 "%s: Failed to set roam trigger, try again", __func__);
2323 ret = -EPERM;
2324 goto exit;
2325 }
2326
2327 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302328 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002329 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2330 }
2331 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2332 {
2333 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2334 int rssi = (-1) * lookUpThreshold;
2335 char extra[32];
2336 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302337 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2338 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2339 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002340 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002341 if (copy_to_user(priv_data.buf, &extra, len + 1))
2342 {
2343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2344 "%s: failed to copy data to user buffer", __func__);
2345 ret = -EFAULT;
2346 goto exit;
2347 }
2348 }
2349 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2350 {
2351 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002352 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002353 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002354
Srinivas Girigowdade697412013-02-14 16:31:48 -08002355 /* input refresh period is in terms of seconds */
2356 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2357 value = value + 18;
2358 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002359 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002360 if (ret < 0)
2361 {
2362 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002363 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002364 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002365 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002366 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002367 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2368 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002369 ret = -EINVAL;
2370 goto exit;
2371 }
2372
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002373 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2374 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002375 {
2376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002377 "Roam scan period value %d is out of range"
2378 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002379 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2380 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002381 ret = -EINVAL;
2382 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302383 }
2384 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2385 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2386 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002387 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002388
2389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2390 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002391 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002392
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002393 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2394 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002395 }
2396 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2397 {
2398 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2399 char extra[32];
2400 tANI_U8 len = 0;
2401
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302402 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2403 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2404 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002405 len = scnprintf(extra, sizeof(extra), "%s %d",
2406 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002407 /* Returned value is in units of seconds */
2408 if (copy_to_user(priv_data.buf, &extra, len + 1))
2409 {
2410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2411 "%s: failed to copy data to user buffer", __func__);
2412 ret = -EFAULT;
2413 goto exit;
2414 }
2415 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002416 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2417 {
2418 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002419 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002420 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002421
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002422 /* input refresh period is in terms of seconds */
2423 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2424 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002425
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002426 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 if (ret < 0)
2429 {
2430 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002431 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002433 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002435 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2436 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2437 ret = -EINVAL;
2438 goto exit;
2439 }
2440
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002441 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2442 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2443 {
2444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2445 "Neighbor scan results refresh period value %d is out of range"
2446 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2447 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2448 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2449 ret = -EINVAL;
2450 goto exit;
2451 }
2452 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2453
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2455 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002456 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002457
2458 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2459 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2460 }
2461 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2462 {
2463 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2464 char extra[32];
2465 tANI_U8 len = 0;
2466
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002467 len = scnprintf(extra, sizeof(extra), "%s %d",
2468 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002469 /* Returned value is in units of seconds */
2470 if (copy_to_user(priv_data.buf, &extra, len + 1))
2471 {
2472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2473 "%s: failed to copy data to user buffer", __func__);
2474 ret = -EFAULT;
2475 goto exit;
2476 }
2477 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002478#ifdef FEATURE_WLAN_LFR
2479 /* SETROAMMODE */
2480 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2481 {
2482 tANI_U8 *value = command;
2483 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2484
2485 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2486 value = value + SIZE_OF_SETROAMMODE + 1;
2487
2488 /* Convert the value from ascii to integer */
2489 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2490 if (ret < 0)
2491 {
2492 /* If the input value is greater than max value of datatype, then also
2493 kstrtou8 fails */
2494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2495 "%s: kstrtou8 failed range [%d - %d]", __func__,
2496 CFG_LFR_FEATURE_ENABLED_MIN,
2497 CFG_LFR_FEATURE_ENABLED_MAX);
2498 ret = -EINVAL;
2499 goto exit;
2500 }
2501 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2502 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2505 "Roam Mode value %d is out of range"
2506 " (Min: %d Max: %d)", roamMode,
2507 CFG_LFR_FEATURE_ENABLED_MIN,
2508 CFG_LFR_FEATURE_ENABLED_MAX);
2509 ret = -EINVAL;
2510 goto exit;
2511 }
2512
2513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2514 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2515 /*
2516 * Note that
2517 * SETROAMMODE 0 is to enable LFR while
2518 * SETROAMMODE 1 is to disable LFR, but
2519 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2520 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2521 */
2522 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2523 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2524 else
2525 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2526
2527 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2528 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2529 }
2530 /* GETROAMMODE */
2531 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2532 {
2533 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2534 char extra[32];
2535 tANI_U8 len = 0;
2536
2537 /*
2538 * roamMode value shall be inverted because the sementics is different.
2539 */
2540 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2541 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2542 else
2543 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2544
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002545 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002546 if (copy_to_user(priv_data.buf, &extra, len + 1))
2547 {
2548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2549 "%s: failed to copy data to user buffer", __func__);
2550 ret = -EFAULT;
2551 goto exit;
2552 }
2553 }
2554#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002555#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002556#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002557 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2558 {
2559 tANI_U8 *value = command;
2560 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2561
2562 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2563 value = value + 13;
2564 /* Convert the value from ascii to integer */
2565 ret = kstrtou8(value, 10, &roamRssiDiff);
2566 if (ret < 0)
2567 {
2568 /* If the input value is greater than max value of datatype, then also
2569 kstrtou8 fails */
2570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2571 "%s: kstrtou8 failed range [%d - %d]", __func__,
2572 CFG_ROAM_RSSI_DIFF_MIN,
2573 CFG_ROAM_RSSI_DIFF_MAX);
2574 ret = -EINVAL;
2575 goto exit;
2576 }
2577
2578 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2579 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2580 {
2581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2582 "Roam rssi diff value %d is out of range"
2583 " (Min: %d Max: %d)", roamRssiDiff,
2584 CFG_ROAM_RSSI_DIFF_MIN,
2585 CFG_ROAM_RSSI_DIFF_MAX);
2586 ret = -EINVAL;
2587 goto exit;
2588 }
2589
2590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2591 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2592
2593 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2594 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2595 }
2596 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2597 {
2598 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2599 char extra[32];
2600 tANI_U8 len = 0;
2601
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302602 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2603 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2604 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002605 len = scnprintf(extra, sizeof(extra), "%s %d",
2606 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002607 if (copy_to_user(priv_data.buf, &extra, len + 1))
2608 {
2609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2610 "%s: failed to copy data to user buffer", __func__);
2611 ret = -EFAULT;
2612 goto exit;
2613 }
2614 }
2615#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002616#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002617 else if (strncmp(command, "GETBAND", 7) == 0)
2618 {
2619 int band = -1;
2620 char extra[32];
2621 tANI_U8 len = 0;
2622 hdd_getBand_helper(pHddCtx, &band);
2623
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302624 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2625 TRACE_CODE_HDD_GETBAND_IOCTL,
2626 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002627 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002628 if (copy_to_user(priv_data.buf, &extra, len + 1))
2629 {
2630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2631 "%s: failed to copy data to user buffer", __func__);
2632 ret = -EFAULT;
2633 goto exit;
2634 }
2635 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002636 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2637 {
2638 tANI_U8 *value = command;
2639 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2640 tANI_U8 numChannels = 0;
2641 eHalStatus status = eHAL_STATUS_SUCCESS;
2642
2643 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2644 if (eHAL_STATUS_SUCCESS != status)
2645 {
2646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2647 "%s: Failed to parse channel list information", __func__);
2648 ret = -EINVAL;
2649 goto exit;
2650 }
2651
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302652 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2653 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2654 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002655 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2656 {
2657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2658 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2659 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2660 ret = -EINVAL;
2661 goto exit;
2662 }
2663 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2664 numChannels);
2665 if (eHAL_STATUS_SUCCESS != status)
2666 {
2667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2668 "%s: Failed to update channel list information", __func__);
2669 ret = -EINVAL;
2670 goto exit;
2671 }
2672 }
2673 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2674 {
2675 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2676 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002677 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002678 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002679 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002680
2681 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2682 ChannelList, &numChannels ))
2683 {
2684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2685 "%s: failed to get roam scan channel list", __func__);
2686 ret = -EFAULT;
2687 goto exit;
2688 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302689 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2690 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2691 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002692 /* output channel list is of the format
2693 [Number of roam scan channels][Channel1][Channel2]... */
2694 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002695 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002696 for (j = 0; (j < numChannels); j++)
2697 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002698 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2699 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002700 }
2701
2702 if (copy_to_user(priv_data.buf, &extra, len + 1))
2703 {
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "%s: failed to copy data to user buffer", __func__);
2706 ret = -EFAULT;
2707 goto exit;
2708 }
2709 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002710 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2711 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002712 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002713 char extra[32];
2714 tANI_U8 len = 0;
2715
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002716 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002717 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002718 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002719 hdd_is_okc_mode_enabled(pHddCtx) &&
2720 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2721 {
2722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002723 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002724 " hence this operation is not permitted!", __func__);
2725 ret = -EPERM;
2726 goto exit;
2727 }
2728
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002729 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002730 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002731 if (copy_to_user(priv_data.buf, &extra, len + 1))
2732 {
2733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2734 "%s: failed to copy data to user buffer", __func__);
2735 ret = -EFAULT;
2736 goto exit;
2737 }
2738 }
2739 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2740 {
2741 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2742 char extra[32];
2743 tANI_U8 len = 0;
2744
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002745 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002746 then this operation is not permitted (return FAILURE) */
2747 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002748 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002749 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2750 {
2751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002752 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002753 " hence this operation is not permitted!", __func__);
2754 ret = -EPERM;
2755 goto exit;
2756 }
2757
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002758 len = scnprintf(extra, sizeof(extra), "%s %d",
2759 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002760 if (copy_to_user(priv_data.buf, &extra, len + 1))
2761 {
2762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2763 "%s: failed to copy data to user buffer", __func__);
2764 ret = -EFAULT;
2765 goto exit;
2766 }
2767 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002768 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002769 {
2770 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2771 char extra[32];
2772 tANI_U8 len = 0;
2773
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002774 len = scnprintf(extra, sizeof(extra), "%s %d",
2775 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002776 if (copy_to_user(priv_data.buf, &extra, len + 1))
2777 {
2778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2779 "%s: failed to copy data to user buffer", __func__);
2780 ret = -EFAULT;
2781 goto exit;
2782 }
2783 }
2784 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2785 {
2786 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2787 char extra[32];
2788 tANI_U8 len = 0;
2789
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002790 len = scnprintf(extra, sizeof(extra), "%s %d",
2791 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002792 if (copy_to_user(priv_data.buf, &extra, len + 1))
2793 {
2794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2795 "%s: failed to copy data to user buffer", __func__);
2796 ret = -EFAULT;
2797 goto exit;
2798 }
2799 }
2800 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2801 {
2802 tANI_U8 *value = command;
2803 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2804
2805 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2806 value = value + 26;
2807 /* Convert the value from ascii to integer */
2808 ret = kstrtou8(value, 10, &minTime);
2809 if (ret < 0)
2810 {
2811 /* If the input value is greater than max value of datatype, then also
2812 kstrtou8 fails */
2813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2814 "%s: kstrtou8 failed range [%d - %d]", __func__,
2815 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2816 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2817 ret = -EINVAL;
2818 goto exit;
2819 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002820 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2821 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2822 {
2823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2824 "scan min channel time value %d is out of range"
2825 " (Min: %d Max: %d)", minTime,
2826 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2827 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2828 ret = -EINVAL;
2829 goto exit;
2830 }
2831
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302832 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2833 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2834 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2836 "%s: Received Command to change channel min time = %d", __func__, minTime);
2837
2838 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2839 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2840 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002841 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2842 {
2843 tANI_U8 *value = command;
2844 tANI_U8 channel = 0;
2845 tANI_U8 dwellTime = 0;
2846 tANI_U8 bufLen = 0;
2847 tANI_U8 *buf = NULL;
2848 tSirMacAddr targetApBssid;
2849 eHalStatus status = eHAL_STATUS_SUCCESS;
2850 struct ieee80211_channel chan;
2851 tANI_U8 finalLen = 0;
2852 tANI_U8 *finalBuf = NULL;
2853 tANI_U8 temp = 0;
2854 u64 cookie;
2855 hdd_station_ctx_t *pHddStaCtx = NULL;
2856 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2857
2858 /* if not associated, no need to send action frame */
2859 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2860 {
2861 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2862 ret = -EINVAL;
2863 goto exit;
2864 }
2865
2866 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2867 &dwellTime, &buf, &bufLen);
2868 if (eHAL_STATUS_SUCCESS != status)
2869 {
2870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2871 "%s: Failed to parse send action frame data", __func__);
2872 ret = -EINVAL;
2873 goto exit;
2874 }
2875
2876 /* if the target bssid is different from currently associated AP,
2877 then no need to send action frame */
2878 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2879 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2880 {
2881 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2882 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002883 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002884 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002885 goto exit;
2886 }
2887
2888 /* if the channel number is different from operating channel then
2889 no need to send action frame */
2890 if (channel != pHddStaCtx->conn_info.operationChannel)
2891 {
2892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2893 "%s: channel(%d) is different from operating channel(%d)",
2894 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2895 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002896 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002897 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002898 goto exit;
2899 }
2900 chan.center_freq = sme_ChnToFreq(channel);
2901
2902 finalLen = bufLen + 24;
2903 finalBuf = vos_mem_malloc(finalLen);
2904 if (NULL == finalBuf)
2905 {
2906 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2907 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002908 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002909 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002910 goto exit;
2911 }
2912 vos_mem_zero(finalBuf, finalLen);
2913
2914 /* Fill subtype */
2915 temp = SIR_MAC_MGMT_ACTION << 4;
2916 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2917
2918 /* Fill type */
2919 temp = SIR_MAC_MGMT_FRAME;
2920 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2921
2922 /* Fill destination address (bssid of the AP) */
2923 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2924
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002925 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002926 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2927
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002928 /* Fill BSSID (AP mac address) */
2929 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002930
2931 /* Fill received buffer from 24th address */
2932 vos_mem_copy(finalBuf + 24, buf, bufLen);
2933
Jeff Johnson11c33152013-04-16 17:52:40 -07002934 /* done with the parsed buffer */
2935 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002936 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002937
DARAM SUDHA39eede62014-02-12 11:16:40 +05302938 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002939#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2940 &(pAdapter->wdev),
2941#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002942 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002943#endif
2944 &chan, 0,
2945#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2946 NL80211_CHAN_HT20, 1,
2947#endif
2948 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002949 1, &cookie );
2950 vos_mem_free(finalBuf);
2951 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002952 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2953 {
2954 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2955 char extra[32];
2956 tANI_U8 len = 0;
2957
2958 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002959 len = scnprintf(extra, sizeof(extra), "%s %d",
2960 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302961 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2962 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2963 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002964 if (copy_to_user(priv_data.buf, &extra, len + 1))
2965 {
2966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2967 "%s: failed to copy data to user buffer", __func__);
2968 ret = -EFAULT;
2969 goto exit;
2970 }
2971 }
2972 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2973 {
2974 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002975 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002976
2977 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2978 value = value + 19;
2979 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002980 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002981 if (ret < 0)
2982 {
2983 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002984 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002986 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002987 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2988 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2989 ret = -EINVAL;
2990 goto exit;
2991 }
2992
2993 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2994 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2995 {
2996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2997 "lfr mode value %d is out of range"
2998 " (Min: %d Max: %d)", maxTime,
2999 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3000 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3001 ret = -EINVAL;
3002 goto exit;
3003 }
3004
3005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3006 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3007
3008 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3009 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3010 }
3011 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3012 {
3013 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3014 char extra[32];
3015 tANI_U8 len = 0;
3016
3017 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003018 len = scnprintf(extra, sizeof(extra), "%s %d",
3019 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003020 if (copy_to_user(priv_data.buf, &extra, len + 1))
3021 {
3022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3023 "%s: failed to copy data to user buffer", __func__);
3024 ret = -EFAULT;
3025 goto exit;
3026 }
3027 }
3028 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3029 {
3030 tANI_U8 *value = command;
3031 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3032
3033 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3034 value = value + 16;
3035 /* Convert the value from ascii to integer */
3036 ret = kstrtou16(value, 10, &val);
3037 if (ret < 0)
3038 {
3039 /* If the input value is greater than max value of datatype, then also
3040 kstrtou16 fails */
3041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3042 "%s: kstrtou16 failed range [%d - %d]", __func__,
3043 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3044 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3045 ret = -EINVAL;
3046 goto exit;
3047 }
3048
3049 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3050 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3051 {
3052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3053 "scan home time value %d is out of range"
3054 " (Min: %d Max: %d)", val,
3055 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3056 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3057 ret = -EINVAL;
3058 goto exit;
3059 }
3060
3061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3062 "%s: Received Command to change scan home time = %d", __func__, val);
3063
3064 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3065 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3066 }
3067 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3068 {
3069 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3070 char extra[32];
3071 tANI_U8 len = 0;
3072
3073 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003074 len = scnprintf(extra, sizeof(extra), "%s %d",
3075 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003076 if (copy_to_user(priv_data.buf, &extra, len + 1))
3077 {
3078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3079 "%s: failed to copy data to user buffer", __func__);
3080 ret = -EFAULT;
3081 goto exit;
3082 }
3083 }
3084 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3085 {
3086 tANI_U8 *value = command;
3087 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3088
3089 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3090 value = value + 17;
3091 /* Convert the value from ascii to integer */
3092 ret = kstrtou8(value, 10, &val);
3093 if (ret < 0)
3094 {
3095 /* If the input value is greater than max value of datatype, then also
3096 kstrtou8 fails */
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3098 "%s: kstrtou8 failed range [%d - %d]", __func__,
3099 CFG_ROAM_INTRA_BAND_MIN,
3100 CFG_ROAM_INTRA_BAND_MAX);
3101 ret = -EINVAL;
3102 goto exit;
3103 }
3104
3105 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3106 (val > CFG_ROAM_INTRA_BAND_MAX))
3107 {
3108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3109 "intra band mode value %d is out of range"
3110 " (Min: %d Max: %d)", val,
3111 CFG_ROAM_INTRA_BAND_MIN,
3112 CFG_ROAM_INTRA_BAND_MAX);
3113 ret = -EINVAL;
3114 goto exit;
3115 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3117 "%s: Received Command to change intra band = %d", __func__, val);
3118
3119 pHddCtx->cfg_ini->nRoamIntraBand = val;
3120 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3121 }
3122 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3123 {
3124 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3125 char extra[32];
3126 tANI_U8 len = 0;
3127
3128 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003129 len = scnprintf(extra, sizeof(extra), "%s %d",
3130 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003131 if (copy_to_user(priv_data.buf, &extra, len + 1))
3132 {
3133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3134 "%s: failed to copy data to user buffer", __func__);
3135 ret = -EFAULT;
3136 goto exit;
3137 }
3138 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003139 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3140 {
3141 tANI_U8 *value = command;
3142 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3143
3144 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3145 value = value + 15;
3146 /* Convert the value from ascii to integer */
3147 ret = kstrtou8(value, 10, &nProbes);
3148 if (ret < 0)
3149 {
3150 /* If the input value is greater than max value of datatype, then also
3151 kstrtou8 fails */
3152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3153 "%s: kstrtou8 failed range [%d - %d]", __func__,
3154 CFG_ROAM_SCAN_N_PROBES_MIN,
3155 CFG_ROAM_SCAN_N_PROBES_MAX);
3156 ret = -EINVAL;
3157 goto exit;
3158 }
3159
3160 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3161 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3162 {
3163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3164 "NProbes value %d is out of range"
3165 " (Min: %d Max: %d)", nProbes,
3166 CFG_ROAM_SCAN_N_PROBES_MIN,
3167 CFG_ROAM_SCAN_N_PROBES_MAX);
3168 ret = -EINVAL;
3169 goto exit;
3170 }
3171
3172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3173 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3174
3175 pHddCtx->cfg_ini->nProbes = nProbes;
3176 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3177 }
3178 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3179 {
3180 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3181 char extra[32];
3182 tANI_U8 len = 0;
3183
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003184 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003185 if (copy_to_user(priv_data.buf, &extra, len + 1))
3186 {
3187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3188 "%s: failed to copy data to user buffer", __func__);
3189 ret = -EFAULT;
3190 goto exit;
3191 }
3192 }
3193 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3194 {
3195 tANI_U8 *value = command;
3196 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3197
3198 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3199 /* input value is in units of msec */
3200 value = value + 20;
3201 /* Convert the value from ascii to integer */
3202 ret = kstrtou16(value, 10, &homeAwayTime);
3203 if (ret < 0)
3204 {
3205 /* If the input value is greater than max value of datatype, then also
3206 kstrtou8 fails */
3207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3208 "%s: kstrtou8 failed range [%d - %d]", __func__,
3209 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3210 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3211 ret = -EINVAL;
3212 goto exit;
3213 }
3214
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003215 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3216 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3217 {
3218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3219 "homeAwayTime value %d is out of range"
3220 " (Min: %d Max: %d)", homeAwayTime,
3221 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3222 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3223 ret = -EINVAL;
3224 goto exit;
3225 }
3226
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3228 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003229 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3230 {
3231 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3232 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3233 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003234 }
3235 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3236 {
3237 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3238 char extra[32];
3239 tANI_U8 len = 0;
3240
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003241 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003242 if (copy_to_user(priv_data.buf, &extra, len + 1))
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3245 "%s: failed to copy data to user buffer", __func__);
3246 ret = -EFAULT;
3247 goto exit;
3248 }
3249 }
3250 else if (strncmp(command, "REASSOC", 7) == 0)
3251 {
3252 tANI_U8 *value = command;
3253 tANI_U8 channel = 0;
3254 tSirMacAddr targetApBssid;
3255 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003256#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3257 tCsrHandoffRequest handoffInfo;
3258#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003259 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003260 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3261
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003262 /* if not associated, no need to proceed with reassoc */
3263 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3264 {
3265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3266 ret = -EINVAL;
3267 goto exit;
3268 }
3269
3270 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3271 if (eHAL_STATUS_SUCCESS != status)
3272 {
3273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3274 "%s: Failed to parse reassoc command data", __func__);
3275 ret = -EINVAL;
3276 goto exit;
3277 }
3278
3279 /* if the target bssid is same as currently associated AP,
3280 then no need to proceed with reassoc */
3281 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3282 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3283 {
3284 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3285 ret = -EINVAL;
3286 goto exit;
3287 }
3288
3289 /* Check channel number is a valid channel number */
3290 if(VOS_STATUS_SUCCESS !=
3291 wlan_hdd_validate_operation_channel(pAdapter, channel))
3292 {
3293 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003294 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003295 return -EINVAL;
3296 }
3297
3298 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003299#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3300 handoffInfo.channel = channel;
3301 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3302 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3303#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003304 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003305 else if (strncmp(command, "SETWESMODE", 10) == 0)
3306 {
3307 tANI_U8 *value = command;
3308 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3309
3310 /* Move pointer to ahead of SETWESMODE<delimiter> */
3311 value = value + 11;
3312 /* Convert the value from ascii to integer */
3313 ret = kstrtou8(value, 10, &wesMode);
3314 if (ret < 0)
3315 {
3316 /* If the input value is greater than max value of datatype, then also
3317 kstrtou8 fails */
3318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3319 "%s: kstrtou8 failed range [%d - %d]", __func__,
3320 CFG_ENABLE_WES_MODE_NAME_MIN,
3321 CFG_ENABLE_WES_MODE_NAME_MAX);
3322 ret = -EINVAL;
3323 goto exit;
3324 }
3325
3326 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3327 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3328 {
3329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3330 "WES Mode value %d is out of range"
3331 " (Min: %d Max: %d)", wesMode,
3332 CFG_ENABLE_WES_MODE_NAME_MIN,
3333 CFG_ENABLE_WES_MODE_NAME_MAX);
3334 ret = -EINVAL;
3335 goto exit;
3336 }
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3338 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3339
3340 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3341 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3342 }
3343 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3344 {
3345 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3346 char extra[32];
3347 tANI_U8 len = 0;
3348
Arif Hussain826d9412013-11-12 16:44:54 -08003349 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003350 if (copy_to_user(priv_data.buf, &extra, len + 1))
3351 {
3352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3353 "%s: failed to copy data to user buffer", __func__);
3354 ret = -EFAULT;
3355 goto exit;
3356 }
3357 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003358#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003359#ifdef FEATURE_WLAN_LFR
3360 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3361 {
3362 tANI_U8 *value = command;
3363 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3364
3365 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3366 value = value + 12;
3367 /* Convert the value from ascii to integer */
3368 ret = kstrtou8(value, 10, &lfrMode);
3369 if (ret < 0)
3370 {
3371 /* If the input value is greater than max value of datatype, then also
3372 kstrtou8 fails */
3373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3374 "%s: kstrtou8 failed range [%d - %d]", __func__,
3375 CFG_LFR_FEATURE_ENABLED_MIN,
3376 CFG_LFR_FEATURE_ENABLED_MAX);
3377 ret = -EINVAL;
3378 goto exit;
3379 }
3380
3381 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3382 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3383 {
3384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3385 "lfr mode value %d is out of range"
3386 " (Min: %d Max: %d)", lfrMode,
3387 CFG_LFR_FEATURE_ENABLED_MIN,
3388 CFG_LFR_FEATURE_ENABLED_MAX);
3389 ret = -EINVAL;
3390 goto exit;
3391 }
3392
3393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3394 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3395
3396 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3397 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3398 }
3399#endif
3400#ifdef WLAN_FEATURE_VOWIFI_11R
3401 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3402 {
3403 tANI_U8 *value = command;
3404 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3405
3406 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3407 value = value + 18;
3408 /* Convert the value from ascii to integer */
3409 ret = kstrtou8(value, 10, &ft);
3410 if (ret < 0)
3411 {
3412 /* If the input value is greater than max value of datatype, then also
3413 kstrtou8 fails */
3414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3415 "%s: kstrtou8 failed range [%d - %d]", __func__,
3416 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3417 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3418 ret = -EINVAL;
3419 goto exit;
3420 }
3421
3422 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3423 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3424 {
3425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3426 "ft mode value %d is out of range"
3427 " (Min: %d Max: %d)", ft,
3428 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3429 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3430 ret = -EINVAL;
3431 goto exit;
3432 }
3433
3434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3435 "%s: Received Command to change ft mode = %d", __func__, ft);
3436
3437 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3438 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3439 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303440
3441 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3442 {
3443 tANI_U8 *value = command;
3444 tSirMacAddr targetApBssid;
3445 tANI_U8 trigger = 0;
3446 eHalStatus status = eHAL_STATUS_SUCCESS;
3447 hdd_station_ctx_t *pHddStaCtx = NULL;
3448 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3449
3450 /* if not associated, no need to proceed with reassoc */
3451 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3452 {
3453 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3454 ret = -EINVAL;
3455 goto exit;
3456 }
3457
3458 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3459 if (eHAL_STATUS_SUCCESS != status)
3460 {
3461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3462 "%s: Failed to parse reassoc command data", __func__);
3463 ret = -EINVAL;
3464 goto exit;
3465 }
3466
3467 /* if the target bssid is same as currently associated AP,
3468 then no need to proceed with reassoc */
3469 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3470 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3471 {
3472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3473 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3474 __func__);
3475 ret = -EINVAL;
3476 goto exit;
3477 }
3478
3479 /* Proceed with scan/roam */
3480 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3481 &targetApBssid[0],
3482 (tSmeFastRoamTrigger)(trigger));
3483 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003484#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003485#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003486 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3487 {
3488 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003489 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003490
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003491 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003492 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003493 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003494 hdd_is_okc_mode_enabled(pHddCtx) &&
3495 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3496 {
3497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003498 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003499 " hence this operation is not permitted!", __func__);
3500 ret = -EPERM;
3501 goto exit;
3502 }
3503
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003504 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3505 value = value + 11;
3506 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003507 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003508 if (ret < 0)
3509 {
3510 /* If the input value is greater than max value of datatype, then also
3511 kstrtou8 fails */
3512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3513 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003514 CFG_ESE_FEATURE_ENABLED_MIN,
3515 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003516 ret = -EINVAL;
3517 goto exit;
3518 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003519 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3520 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003521 {
3522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003523 "Ese mode value %d is out of range"
3524 " (Min: %d Max: %d)", eseMode,
3525 CFG_ESE_FEATURE_ENABLED_MIN,
3526 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003527 ret = -EINVAL;
3528 goto exit;
3529 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003531 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003532
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003533 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3534 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003535 }
3536#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003537 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3538 {
3539 tANI_U8 *value = command;
3540 tANI_BOOLEAN roamScanControl = 0;
3541
3542 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3543 value = value + 19;
3544 /* Convert the value from ascii to integer */
3545 ret = kstrtou8(value, 10, &roamScanControl);
3546 if (ret < 0)
3547 {
3548 /* If the input value is greater than max value of datatype, then also
3549 kstrtou8 fails */
3550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3551 "%s: kstrtou8 failed ", __func__);
3552 ret = -EINVAL;
3553 goto exit;
3554 }
3555
3556 if (0 != roamScanControl)
3557 {
3558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3559 "roam scan control invalid value = %d",
3560 roamScanControl);
3561 ret = -EINVAL;
3562 goto exit;
3563 }
3564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3565 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3566
3567 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3568 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003569#ifdef FEATURE_WLAN_OKC
3570 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3571 {
3572 tANI_U8 *value = command;
3573 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3574
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003575 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003576 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003577 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003578 hdd_is_okc_mode_enabled(pHddCtx) &&
3579 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3580 {
3581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003582 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003583 " hence this operation is not permitted!", __func__);
3584 ret = -EPERM;
3585 goto exit;
3586 }
3587
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003588 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3589 value = value + 11;
3590 /* Convert the value from ascii to integer */
3591 ret = kstrtou8(value, 10, &okcMode);
3592 if (ret < 0)
3593 {
3594 /* If the input value is greater than max value of datatype, then also
3595 kstrtou8 fails */
3596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3597 "%s: kstrtou8 failed range [%d - %d]", __func__,
3598 CFG_OKC_FEATURE_ENABLED_MIN,
3599 CFG_OKC_FEATURE_ENABLED_MAX);
3600 ret = -EINVAL;
3601 goto exit;
3602 }
3603
3604 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3605 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3606 {
3607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3608 "Okc mode value %d is out of range"
3609 " (Min: %d Max: %d)", okcMode,
3610 CFG_OKC_FEATURE_ENABLED_MIN,
3611 CFG_OKC_FEATURE_ENABLED_MAX);
3612 ret = -EINVAL;
3613 goto exit;
3614 }
3615
3616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3617 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3618
3619 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3620 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003621#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003622 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3623 {
3624 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3625 char extra[32];
3626 tANI_U8 len = 0;
3627
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003628 len = scnprintf(extra, sizeof(extra), "%s %d",
3629 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003630 if (copy_to_user(priv_data.buf, &extra, len + 1))
3631 {
3632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3633 "%s: failed to copy data to user buffer", __func__);
3634 ret = -EFAULT;
3635 goto exit;
3636 }
3637 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303638#ifdef WLAN_FEATURE_PACKET_FILTERING
3639 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3640 {
3641 tANI_U8 filterType = 0;
3642 tANI_U8 *value = command;
3643
3644 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3645 value = value + 22;
3646
3647 /* Convert the value from ascii to integer */
3648 ret = kstrtou8(value, 10, &filterType);
3649 if (ret < 0)
3650 {
3651 /* If the input value is greater than max value of datatype,
3652 * then also kstrtou8 fails
3653 */
3654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3655 "%s: kstrtou8 failed range ", __func__);
3656 ret = -EINVAL;
3657 goto exit;
3658 }
3659
3660 if (filterType != 0 && filterType != 1)
3661 {
3662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3663 "%s: Accepted Values are 0 and 1 ", __func__);
3664 ret = -EINVAL;
3665 goto exit;
3666 }
3667 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3668 pAdapter->sessionId);
3669 }
3670#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303671 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3672 {
Kiet Lamad161252014-07-22 11:23:32 -07003673 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303674 int ret;
3675
Kiet Lamad161252014-07-22 11:23:32 -07003676 dhcpPhase = command + 11;
3677 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303678 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003680 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303681
3682 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003683
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303684 ret = wlan_hdd_scan_abort(pAdapter);
3685 if (ret < 0)
3686 {
3687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3688 FL("failed to abort existing scan %d"), ret);
3689 }
3690
Kiet Lamad161252014-07-22 11:23:32 -07003691 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3692 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303693 }
Kiet Lamad161252014-07-22 11:23:32 -07003694 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303695 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003697 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303698
3699 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003700
3701 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3702 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303703 }
3704 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003705 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3706 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3708 FL("making default scan to ACTIVE"));
3709 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003710 }
3711 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3712 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3714 FL("making default scan to PASSIVE"));
3715 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003716 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303717 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3718 {
3719 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3720 char extra[32];
3721 tANI_U8 len = 0;
3722
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303723 memset(extra, 0, sizeof(extra));
3724 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3725 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303726 {
3727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3728 "%s: failed to copy data to user buffer", __func__);
3729 ret = -EFAULT;
3730 goto exit;
3731 }
3732 ret = len;
3733 }
3734 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3735 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303736 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303737 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003738 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3739 {
3740 tANI_U8 filterType = 0;
3741 tANI_U8 *value;
3742 value = command + 9;
3743
3744 /* Convert the value from ascii to integer */
3745 ret = kstrtou8(value, 10, &filterType);
3746 if (ret < 0)
3747 {
3748 /* If the input value is greater than max value of datatype,
3749 * then also kstrtou8 fails
3750 */
3751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3752 "%s: kstrtou8 failed range ", __func__);
3753 ret = -EINVAL;
3754 goto exit;
3755 }
3756 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3757 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3758 {
3759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3760 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3761 " 2-Sink ", __func__);
3762 ret = -EINVAL;
3763 goto exit;
3764 }
3765 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3766 pHddCtx->drvr_miracast = filterType;
3767 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303768 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003769 }
Leo Chang614d2072013-08-22 14:59:44 -07003770 else if (strncmp(command, "SETMCRATE", 9) == 0)
3771 {
Leo Chang614d2072013-08-22 14:59:44 -07003772 tANI_U8 *value = command;
3773 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003774 tSirRateUpdateInd *rateUpdate;
3775 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003776
3777 /* Only valid for SAP mode */
3778 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3779 {
3780 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3781 "%s: SAP mode is not running", __func__);
3782 ret = -EFAULT;
3783 goto exit;
3784 }
3785
3786 /* Move pointer to ahead of SETMCRATE<delimiter> */
3787 /* input value is in units of hundred kbps */
3788 value = value + 10;
3789 /* Convert the value from ascii to integer, decimal base */
3790 ret = kstrtouint(value, 10, &targetRate);
3791
Leo Chang1f98cbd2013-10-17 15:03:52 -07003792 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3793 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003794 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003795 hddLog(VOS_TRACE_LEVEL_ERROR,
3796 "%s: SETMCRATE indication alloc fail", __func__);
3797 ret = -EFAULT;
3798 goto exit;
3799 }
3800 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3801
3802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3803 "MC Target rate %d", targetRate);
3804 /* Ignore unicast */
3805 rateUpdate->ucastDataRate = -1;
3806 rateUpdate->mcastDataRate24GHz = targetRate;
3807 rateUpdate->mcastDataRate5GHz = targetRate;
3808 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3809 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3810 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3811 if (eHAL_STATUS_SUCCESS != status)
3812 {
3813 hddLog(VOS_TRACE_LEVEL_ERROR,
3814 "%s: SET_MC_RATE failed", __func__);
3815 vos_mem_free(rateUpdate);
3816 ret = -EFAULT;
3817 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003818 }
3819 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303820#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003821 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303822 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003823 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303824 }
3825#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003826#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003827 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3828 {
3829 tANI_U8 *value = command;
3830 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3831 tANI_U8 numChannels = 0;
3832 eHalStatus status = eHAL_STATUS_SUCCESS;
3833
3834 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3835 if (eHAL_STATUS_SUCCESS != status)
3836 {
3837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3838 "%s: Failed to parse channel list information", __func__);
3839 ret = -EINVAL;
3840 goto exit;
3841 }
3842
3843 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3844 {
3845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3846 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3847 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3848 ret = -EINVAL;
3849 goto exit;
3850 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003851 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003852 ChannelList,
3853 numChannels);
3854 if (eHAL_STATUS_SUCCESS != status)
3855 {
3856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3857 "%s: Failed to update channel list information", __func__);
3858 ret = -EINVAL;
3859 goto exit;
3860 }
3861 }
3862 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3863 {
3864 tANI_U8 *value = command;
3865 char extra[128] = {0};
3866 int len = 0;
3867 tANI_U8 tid = 0;
3868 hdd_station_ctx_t *pHddStaCtx = NULL;
3869 tAniTrafStrmMetrics tsmMetrics;
3870 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3871
3872 /* if not associated, return error */
3873 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3874 {
3875 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3876 ret = -EINVAL;
3877 goto exit;
3878 }
3879
3880 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3881 value = value + 12;
3882 /* Convert the value from ascii to integer */
3883 ret = kstrtou8(value, 10, &tid);
3884 if (ret < 0)
3885 {
3886 /* If the input value is greater than max value of datatype, then also
3887 kstrtou8 fails */
3888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3889 "%s: kstrtou8 failed range [%d - %d]", __func__,
3890 TID_MIN_VALUE,
3891 TID_MAX_VALUE);
3892 ret = -EINVAL;
3893 goto exit;
3894 }
3895
3896 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3897 {
3898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3899 "tid value %d is out of range"
3900 " (Min: %d Max: %d)", tid,
3901 TID_MIN_VALUE,
3902 TID_MAX_VALUE);
3903 ret = -EINVAL;
3904 goto exit;
3905 }
3906
3907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3908 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3909
3910 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3911 {
3912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3913 "%s: failed to get tsm stats", __func__);
3914 ret = -EFAULT;
3915 goto exit;
3916 }
3917
3918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3919 "UplinkPktQueueDly(%d)\n"
3920 "UplinkPktQueueDlyHist[0](%d)\n"
3921 "UplinkPktQueueDlyHist[1](%d)\n"
3922 "UplinkPktQueueDlyHist[2](%d)\n"
3923 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303924 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003925 "UplinkPktLoss(%d)\n"
3926 "UplinkPktCount(%d)\n"
3927 "RoamingCount(%d)\n"
3928 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3929 tsmMetrics.UplinkPktQueueDlyHist[0],
3930 tsmMetrics.UplinkPktQueueDlyHist[1],
3931 tsmMetrics.UplinkPktQueueDlyHist[2],
3932 tsmMetrics.UplinkPktQueueDlyHist[3],
3933 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3934 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3935
3936 /* Output TSM stats is of the format
3937 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3938 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003939 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003940 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3941 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3942 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3943 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3944 tsmMetrics.RoamingDly);
3945
3946 if (copy_to_user(priv_data.buf, &extra, len + 1))
3947 {
3948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3949 "%s: failed to copy data to user buffer", __func__);
3950 ret = -EFAULT;
3951 goto exit;
3952 }
3953 }
3954 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3955 {
3956 tANI_U8 *value = command;
3957 tANI_U8 *cckmIe = NULL;
3958 tANI_U8 cckmIeLen = 0;
3959 eHalStatus status = eHAL_STATUS_SUCCESS;
3960
3961 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3962 if (eHAL_STATUS_SUCCESS != status)
3963 {
3964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3965 "%s: Failed to parse cckm ie data", __func__);
3966 ret = -EINVAL;
3967 goto exit;
3968 }
3969
3970 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3971 {
3972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3973 "%s: CCKM Ie input length is more than max[%d]", __func__,
3974 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003975 vos_mem_free(cckmIe);
3976 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003977 ret = -EINVAL;
3978 goto exit;
3979 }
3980 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003981 vos_mem_free(cckmIe);
3982 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003983 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003984 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3985 {
3986 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003987 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003988 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003989
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003990 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003991 if (eHAL_STATUS_SUCCESS != status)
3992 {
3993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003994 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003995 ret = -EINVAL;
3996 goto exit;
3997 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003998 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
3999 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4000 hdd_indicateEseBcnReportNoResults (pAdapter,
4001 eseBcnReq.bcnReq[0].measurementToken,
4002 0x02, //BIT(1) set for measurement done
4003 0); // no BSS
4004 goto exit;
4005 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004006
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004007 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4008 if (eHAL_STATUS_SUCCESS != status)
4009 {
4010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4011 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4012 ret = -EINVAL;
4013 goto exit;
4014 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004015 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004016#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304017 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4018 {
4019 eHalStatus status;
4020 char buf[32], len;
4021 long waitRet;
4022 bcnMissRateContext_t getBcnMissRateCtx;
4023
4024 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4025
4026 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4027 {
4028 hddLog(VOS_TRACE_LEVEL_WARN,
4029 FL("GETBCNMISSRATE: STA is not in connected state"));
4030 ret = -1;
4031 goto exit;
4032 }
4033
4034 init_completion(&(getBcnMissRateCtx.completion));
4035 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4036
4037 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4038 pAdapter->sessionId,
4039 (void *)getBcnMissRateCB,
4040 (void *)(&getBcnMissRateCtx));
4041 if( eHAL_STATUS_SUCCESS != status)
4042 {
4043 hddLog(VOS_TRACE_LEVEL_INFO,
4044 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4045 ret = -EINVAL;
4046 goto exit;
4047 }
4048
4049 waitRet = wait_for_completion_interruptible_timeout
4050 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4051 if(waitRet <= 0)
4052 {
4053 hddLog(VOS_TRACE_LEVEL_ERROR,
4054 FL("failed to wait on bcnMissRateComp %d"), ret);
4055
4056 //Make magic number to zero so that callback is not called.
4057 spin_lock(&hdd_context_lock);
4058 getBcnMissRateCtx.magic = 0x0;
4059 spin_unlock(&hdd_context_lock);
4060 ret = -EINVAL;
4061 goto exit;
4062 }
4063
4064 hddLog(VOS_TRACE_LEVEL_INFO,
4065 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4066
4067 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4068 if (copy_to_user(priv_data.buf, &buf, len + 1))
4069 {
4070 hddLog(VOS_TRACE_LEVEL_ERROR,
4071 "%s: failed to copy data to user buffer", __func__);
4072 ret = -EFAULT;
4073 goto exit;
4074 }
4075 ret = len;
4076 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304077#ifdef FEATURE_WLAN_TDLS
4078 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4079 tANI_U8 *value = command;
4080 int set_value;
4081 /* Move pointer to ahead of TDLSOFFCH*/
4082 value += 26;
4083 sscanf(value, "%d", &set_value);
4084 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4085 "%s: Tdls offchannel offset:%d",
4086 __func__, set_value);
4087 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4088 if (ret < 0)
4089 {
4090 ret = -EINVAL;
4091 goto exit;
4092 }
4093
4094 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4095 tANI_U8 *value = command;
4096 int set_value;
4097 /* Move pointer to ahead of tdlsoffchnmode*/
4098 value += 18;
4099 sscanf(value, "%d", &set_value);
4100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4101 "%s: Tdls offchannel mode:%d",
4102 __func__, set_value);
4103 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4104 if (ret < 0)
4105 {
4106 ret = -EINVAL;
4107 goto exit;
4108 }
4109 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4110 tANI_U8 *value = command;
4111 int set_value;
4112 /* Move pointer to ahead of TDLSOFFCH*/
4113 value += 14;
4114 sscanf(value, "%d", &set_value);
4115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4116 "%s: Tdls offchannel num: %d",
4117 __func__, set_value);
4118 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4119 if (ret < 0)
4120 {
4121 ret = -EINVAL;
4122 goto exit;
4123 }
4124 }
4125#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004126 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304127 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4128 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4129 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004130 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4131 __func__, command);
4132 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004133 }
4134exit:
4135 if (command)
4136 {
4137 kfree(command);
4138 }
4139 return ret;
4140}
4141
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004142#ifdef CONFIG_COMPAT
4143static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4144{
4145 struct {
4146 compat_uptr_t buf;
4147 int used_len;
4148 int total_len;
4149 } compat_priv_data;
4150 hdd_priv_data_t priv_data;
4151 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004152
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004153 /*
4154 * Note that pAdapter and ifr have already been verified by caller,
4155 * and HDD context has also been validated
4156 */
4157 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4158 sizeof(compat_priv_data))) {
4159 ret = -EFAULT;
4160 goto exit;
4161 }
4162 priv_data.buf = compat_ptr(compat_priv_data.buf);
4163 priv_data.used_len = compat_priv_data.used_len;
4164 priv_data.total_len = compat_priv_data.total_len;
4165 ret = hdd_driver_command(pAdapter, &priv_data);
4166 exit:
4167 return ret;
4168}
4169#else /* CONFIG_COMPAT */
4170static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4171{
4172 /* will never be invoked */
4173 return 0;
4174}
4175#endif /* CONFIG_COMPAT */
4176
4177static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4178{
4179 hdd_priv_data_t priv_data;
4180 int ret = 0;
4181
4182 /*
4183 * Note that pAdapter and ifr have already been verified by caller,
4184 * and HDD context has also been validated
4185 */
4186 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4187 ret = -EFAULT;
4188 } else {
4189 ret = hdd_driver_command(pAdapter, &priv_data);
4190 }
4191 return ret;
4192}
4193
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304194int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004195{
4196 hdd_adapter_t *pAdapter;
4197 hdd_context_t *pHddCtx;
4198 int ret;
4199
4200 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4201 if (NULL == pAdapter) {
4202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4203 "%s: HDD adapter context is Null", __func__);
4204 ret = -ENODEV;
4205 goto exit;
4206 }
4207 if (dev != pAdapter->dev) {
4208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4209 "%s: HDD adapter/dev inconsistency", __func__);
4210 ret = -ENODEV;
4211 goto exit;
4212 }
4213
4214 if ((!ifr) || (!ifr->ifr_data)) {
4215 ret = -EINVAL;
4216 goto exit;
4217 }
4218
4219 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4220 ret = wlan_hdd_validate_context(pHddCtx);
4221 if (ret) {
4222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4223 "%s: invalid context", __func__);
4224 ret = -EBUSY;
4225 goto exit;
4226 }
4227
4228 switch (cmd) {
4229 case (SIOCDEVPRIVATE + 1):
4230 if (is_compat_task())
4231 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4232 else
4233 ret = hdd_driver_ioctl(pAdapter, ifr);
4234 break;
4235 default:
4236 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4237 __func__, cmd);
4238 ret = -EINVAL;
4239 break;
4240 }
4241 exit:
4242 return ret;
4243}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004244
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304245int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4246{
4247 int ret;
4248
4249 vos_ssr_protect(__func__);
4250 ret = __hdd_ioctl(dev, ifr, cmd);
4251 vos_ssr_unprotect(__func__);
4252
4253 return ret;
4254}
4255
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004256#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004257/**---------------------------------------------------------------------------
4258
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004259 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004260
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004261 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004262 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4263 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4264 <space>Scan Mode N<space>Meas Duration N
4265 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4266 then take N.
4267 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4268 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4269 This function does not take care of removing duplicate channels from the list
4270
4271 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004272 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004273
4274 \return - 0 for success non-zero for failure
4275
4276 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004277static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4278 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004279{
4280 tANI_U8 *inPtr = pValue;
4281 int tempInt = 0;
4282 int j = 0, i = 0, v = 0;
4283 char buf[32];
4284
4285 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4286 /*no argument after the command*/
4287 if (NULL == inPtr)
4288 {
4289 return -EINVAL;
4290 }
4291 /*no space after the command*/
4292 else if (SPACE_ASCII_VALUE != *inPtr)
4293 {
4294 return -EINVAL;
4295 }
4296
4297 /*removing empty spaces*/
4298 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4299
4300 /*no argument followed by spaces*/
4301 if ('\0' == *inPtr) return -EINVAL;
4302
4303 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004304 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004305 if (1 != v) return -EINVAL;
4306
4307 v = kstrtos32(buf, 10, &tempInt);
4308 if ( v < 0) return -EINVAL;
4309
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004310 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004311
4312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004313 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004314
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004315 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004316 {
4317 for (i = 0; i < 4; i++)
4318 {
4319 /*inPtr pointing to the beginning of first space after number of ie fields*/
4320 inPtr = strpbrk( inPtr, " " );
4321 /*no ie data after the number of ie fields argument*/
4322 if (NULL == inPtr) return -EINVAL;
4323
4324 /*removing empty space*/
4325 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4326
4327 /*no ie data after the number of ie fields argument and spaces*/
4328 if ( '\0' == *inPtr ) return -EINVAL;
4329
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004330 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004331 if (1 != v) return -EINVAL;
4332
4333 v = kstrtos32(buf, 10, &tempInt);
4334 if (v < 0) return -EINVAL;
4335
4336 switch (i)
4337 {
4338 case 0: /* Measurement token */
4339 if (tempInt <= 0)
4340 {
4341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4342 "Invalid Measurement Token(%d)", tempInt);
4343 return -EINVAL;
4344 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004345 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004346 break;
4347
4348 case 1: /* Channel number */
4349 if ((tempInt <= 0) ||
4350 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4351 {
4352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4353 "Invalid Channel Number(%d)", tempInt);
4354 return -EINVAL;
4355 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004356 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004357 break;
4358
4359 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004360 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004361 {
4362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4363 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4364 return -EINVAL;
4365 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004366 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004367 break;
4368
4369 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004370 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4371 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004372 {
4373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4374 "Invalid Measurement Duration(%d)", tempInt);
4375 return -EINVAL;
4376 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004377 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004378 break;
4379 }
4380 }
4381 }
4382
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004383 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004384 {
4385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304386 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004387 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004388 pEseBcnReq->bcnReq[j].measurementToken,
4389 pEseBcnReq->bcnReq[j].channel,
4390 pEseBcnReq->bcnReq[j].scanMode,
4391 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004392 }
4393
4394 return VOS_STATUS_SUCCESS;
4395}
4396
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004397static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4398{
4399 struct statsContext *pStatsContext = NULL;
4400 hdd_adapter_t *pAdapter = NULL;
4401
4402 if (NULL == pContext)
4403 {
4404 hddLog(VOS_TRACE_LEVEL_ERROR,
4405 "%s: Bad param, pContext [%p]",
4406 __func__, pContext);
4407 return;
4408 }
4409
Jeff Johnson72a40512013-12-19 10:14:15 -08004410 /* there is a race condition that exists between this callback
4411 function and the caller since the caller could time out either
4412 before or while this code is executing. we use a spinlock to
4413 serialize these actions */
4414 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004415
4416 pStatsContext = pContext;
4417 pAdapter = pStatsContext->pAdapter;
4418 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4419 {
4420 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004421 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004422 hddLog(VOS_TRACE_LEVEL_WARN,
4423 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4424 __func__, pAdapter, pStatsContext->magic);
4425 return;
4426 }
4427
Jeff Johnson72a40512013-12-19 10:14:15 -08004428 /* context is valid so caller is still waiting */
4429
4430 /* paranoia: invalidate the magic */
4431 pStatsContext->magic = 0;
4432
4433 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004434 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4435 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4436 tsmMetrics.UplinkPktQueueDlyHist,
4437 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4438 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4439 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4440 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4441 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4442 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4443 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4444
Jeff Johnson72a40512013-12-19 10:14:15 -08004445 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004446 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004447
4448 /* serialization is complete */
4449 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004450}
4451
4452
4453
4454static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4455 tAniTrafStrmMetrics* pTsmMetrics)
4456{
4457 hdd_station_ctx_t *pHddStaCtx = NULL;
4458 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004459 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004460 long lrc;
4461 struct statsContext context;
4462 hdd_context_t *pHddCtx = NULL;
4463
4464 if (NULL == pAdapter)
4465 {
4466 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4467 return VOS_STATUS_E_FAULT;
4468 }
4469
4470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4471 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4472
4473 /* we are connected prepare our callback context */
4474 init_completion(&context.completion);
4475 context.pAdapter = pAdapter;
4476 context.magic = STATS_CONTEXT_MAGIC;
4477
4478 /* query tsm stats */
4479 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4480 pHddStaCtx->conn_info.staId[ 0 ],
4481 pHddStaCtx->conn_info.bssId,
4482 &context, pHddCtx->pvosContext, tid);
4483
4484 if (eHAL_STATUS_SUCCESS != hstatus)
4485 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004486 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4487 __func__);
4488 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004489 }
4490 else
4491 {
4492 /* request was sent -- wait for the response */
4493 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4494 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004495 if (lrc <= 0)
4496 {
4497 hddLog(VOS_TRACE_LEVEL_ERROR,
4498 "%s: SME %s while retrieving statistics",
4499 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004500 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004501 }
4502 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004503
Jeff Johnson72a40512013-12-19 10:14:15 -08004504 /* either we never sent a request, we sent a request and received a
4505 response or we sent a request and timed out. if we never sent a
4506 request or if we sent a request and got a response, we want to
4507 clear the magic out of paranoia. if we timed out there is a
4508 race condition such that the callback function could be
4509 executing at the same time we are. of primary concern is if the
4510 callback function had already verified the "magic" but had not
4511 yet set the completion variable when a timeout occurred. we
4512 serialize these activities by invalidating the magic while
4513 holding a shared spinlock which will cause us to block if the
4514 callback is currently executing */
4515 spin_lock(&hdd_context_lock);
4516 context.magic = 0;
4517 spin_unlock(&hdd_context_lock);
4518
4519 if (VOS_STATUS_SUCCESS == vstatus)
4520 {
4521 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4522 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4523 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4524 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4525 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4526 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4527 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4528 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4529 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4530 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4531 }
4532 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004533}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004534#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004535
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004536#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004537void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4538{
4539 eCsrBand band = -1;
4540 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4541 switch (band)
4542 {
4543 case eCSR_BAND_ALL:
4544 *pBand = WLAN_HDD_UI_BAND_AUTO;
4545 break;
4546
4547 case eCSR_BAND_24:
4548 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4549 break;
4550
4551 case eCSR_BAND_5G:
4552 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4553 break;
4554
4555 default:
4556 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4557 *pBand = -1;
4558 break;
4559 }
4560}
4561
4562/**---------------------------------------------------------------------------
4563
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004564 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4565
4566 This function parses the send action frame data passed in the format
4567 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4568
Srinivas Girigowda56076852013-08-20 14:00:50 -07004569 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004570 \param - pTargetApBssid Pointer to target Ap bssid
4571 \param - pChannel Pointer to the Target AP channel
4572 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4573 \param - pBuf Pointer to data
4574 \param - pBufLen Pointer to data length
4575
4576 \return - 0 for success non-zero for failure
4577
4578 --------------------------------------------------------------------------*/
4579VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4580 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4581{
4582 tANI_U8 *inPtr = pValue;
4583 tANI_U8 *dataEnd;
4584 int tempInt;
4585 int j = 0;
4586 int i = 0;
4587 int v = 0;
4588 tANI_U8 tempBuf[32];
4589 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004590 /* 12 hexa decimal digits, 5 ':' and '\0' */
4591 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004592
4593 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4594 /*no argument after the command*/
4595 if (NULL == inPtr)
4596 {
4597 return -EINVAL;
4598 }
4599
4600 /*no space after the command*/
4601 else if (SPACE_ASCII_VALUE != *inPtr)
4602 {
4603 return -EINVAL;
4604 }
4605
4606 /*removing empty spaces*/
4607 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4608
4609 /*no argument followed by spaces*/
4610 if ('\0' == *inPtr)
4611 {
4612 return -EINVAL;
4613 }
4614
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004615 v = sscanf(inPtr, "%17s", macAddress);
4616 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004617 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4619 "Invalid MAC address or All hex inputs are not read (%d)", v);
4620 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004621 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004622
4623 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4624 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4625 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4626 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4627 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4628 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004629
4630 /* point to the next argument */
4631 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4632 /*no argument after the command*/
4633 if (NULL == inPtr) return -EINVAL;
4634
4635 /*removing empty spaces*/
4636 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4637
4638 /*no argument followed by spaces*/
4639 if ('\0' == *inPtr)
4640 {
4641 return -EINVAL;
4642 }
4643
4644 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004645 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004646 if (1 != v) return -EINVAL;
4647
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004648 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304649 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304650 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004651
4652 *pChannel = tempInt;
4653
4654 /* point to the next argument */
4655 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4656 /*no argument after the command*/
4657 if (NULL == inPtr) return -EINVAL;
4658 /*removing empty spaces*/
4659 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4660
4661 /*no argument followed by spaces*/
4662 if ('\0' == *inPtr)
4663 {
4664 return -EINVAL;
4665 }
4666
4667 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004668 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004669 if (1 != v) return -EINVAL;
4670
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004671 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004672 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004673
4674 *pDwellTime = tempInt;
4675
4676 /* point to the next argument */
4677 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4678 /*no argument after the command*/
4679 if (NULL == inPtr) return -EINVAL;
4680 /*removing empty spaces*/
4681 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4682
4683 /*no argument followed by spaces*/
4684 if ('\0' == *inPtr)
4685 {
4686 return -EINVAL;
4687 }
4688
4689 /* find the length of data */
4690 dataEnd = inPtr;
4691 while(('\0' != *dataEnd) )
4692 {
4693 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004694 }
Kiet Lambe150c22013-11-21 16:30:32 +05304695 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004696 if ( *pBufLen <= 0) return -EINVAL;
4697
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004698 /* Allocate the number of bytes based on the number of input characters
4699 whether it is even or odd.
4700 if the number of input characters are even, then we need N/2 byte.
4701 if the number of input characters are odd, then we need do (N+1)/2 to
4702 compensate rounding off.
4703 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4704 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4705 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004706 if (NULL == *pBuf)
4707 {
4708 hddLog(VOS_TRACE_LEVEL_FATAL,
4709 "%s: vos_mem_alloc failed ", __func__);
4710 return -EINVAL;
4711 }
4712
4713 /* the buffer received from the upper layer is character buffer,
4714 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4715 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4716 and f0 in 3rd location */
4717 for (i = 0, j = 0; j < *pBufLen; j += 2)
4718 {
Kiet Lambe150c22013-11-21 16:30:32 +05304719 if( j+1 == *pBufLen)
4720 {
4721 tempByte = hdd_parse_hex(inPtr[j]);
4722 }
4723 else
4724 {
4725 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4726 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004727 (*pBuf)[i++] = tempByte;
4728 }
4729 *pBufLen = i;
4730 return VOS_STATUS_SUCCESS;
4731}
4732
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004733/**---------------------------------------------------------------------------
4734
Srinivas Girigowdade697412013-02-14 16:31:48 -08004735 \brief hdd_parse_channellist() - HDD Parse channel list
4736
4737 This function parses the channel list passed in the format
4738 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004739 if the Number of channels (N) does not match with the actual number of channels passed
4740 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4741 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4742 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4743 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004744
4745 \param - pValue Pointer to input channel list
4746 \param - ChannelList Pointer to local output array to record channel list
4747 \param - pNumChannels Pointer to number of roam scan channels
4748
4749 \return - 0 for success non-zero for failure
4750
4751 --------------------------------------------------------------------------*/
4752VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4753{
4754 tANI_U8 *inPtr = pValue;
4755 int tempInt;
4756 int j = 0;
4757 int v = 0;
4758 char buf[32];
4759
4760 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4761 /*no argument after the command*/
4762 if (NULL == inPtr)
4763 {
4764 return -EINVAL;
4765 }
4766
4767 /*no space after the command*/
4768 else if (SPACE_ASCII_VALUE != *inPtr)
4769 {
4770 return -EINVAL;
4771 }
4772
4773 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004774 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004775
4776 /*no argument followed by spaces*/
4777 if ('\0' == *inPtr)
4778 {
4779 return -EINVAL;
4780 }
4781
4782 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004783 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004784 if (1 != v) return -EINVAL;
4785
Srinivas Girigowdade697412013-02-14 16:31:48 -08004786 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004787 if ((v < 0) ||
4788 (tempInt <= 0) ||
4789 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4790 {
4791 return -EINVAL;
4792 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004793
4794 *pNumChannels = tempInt;
4795
4796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4797 "Number of channels are: %d", *pNumChannels);
4798
4799 for (j = 0; j < (*pNumChannels); j++)
4800 {
4801 /*inPtr pointing to the beginning of first space after number of channels*/
4802 inPtr = strpbrk( inPtr, " " );
4803 /*no channel list after the number of channels argument*/
4804 if (NULL == inPtr)
4805 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004806 if (0 != j)
4807 {
4808 *pNumChannels = j;
4809 return VOS_STATUS_SUCCESS;
4810 }
4811 else
4812 {
4813 return -EINVAL;
4814 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004815 }
4816
4817 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004818 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004819
4820 /*no channel list after the number of channels argument and spaces*/
4821 if ( '\0' == *inPtr )
4822 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004823 if (0 != j)
4824 {
4825 *pNumChannels = j;
4826 return VOS_STATUS_SUCCESS;
4827 }
4828 else
4829 {
4830 return -EINVAL;
4831 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004832 }
4833
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004834 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004835 if (1 != v) return -EINVAL;
4836
Srinivas Girigowdade697412013-02-14 16:31:48 -08004837 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004838 if ((v < 0) ||
4839 (tempInt <= 0) ||
4840 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4841 {
4842 return -EINVAL;
4843 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004844 pChannelList[j] = tempInt;
4845
4846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4847 "Channel %d added to preferred channel list",
4848 pChannelList[j] );
4849 }
4850
Srinivas Girigowdade697412013-02-14 16:31:48 -08004851 return VOS_STATUS_SUCCESS;
4852}
4853
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004854
4855/**---------------------------------------------------------------------------
4856
4857 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4858
4859 This function parses the reasoc command data passed in the format
4860 REASSOC<space><bssid><space><channel>
4861
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004862 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004863 \param - pTargetApBssid Pointer to target Ap bssid
4864 \param - pChannel Pointer to the Target AP channel
4865
4866 \return - 0 for success non-zero for failure
4867
4868 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004869VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4870 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004871{
4872 tANI_U8 *inPtr = pValue;
4873 int tempInt;
4874 int v = 0;
4875 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004876 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004877 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004878
4879 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4880 /*no argument after the command*/
4881 if (NULL == inPtr)
4882 {
4883 return -EINVAL;
4884 }
4885
4886 /*no space after the command*/
4887 else if (SPACE_ASCII_VALUE != *inPtr)
4888 {
4889 return -EINVAL;
4890 }
4891
4892 /*removing empty spaces*/
4893 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4894
4895 /*no argument followed by spaces*/
4896 if ('\0' == *inPtr)
4897 {
4898 return -EINVAL;
4899 }
4900
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004901 v = sscanf(inPtr, "%17s", macAddress);
4902 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004903 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4905 "Invalid MAC address or All hex inputs are not read (%d)", v);
4906 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004907 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004908
4909 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4910 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4911 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4912 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4913 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4914 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004915
4916 /* point to the next argument */
4917 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4918 /*no argument after the command*/
4919 if (NULL == inPtr) return -EINVAL;
4920
4921 /*removing empty spaces*/
4922 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4923
4924 /*no argument followed by spaces*/
4925 if ('\0' == *inPtr)
4926 {
4927 return -EINVAL;
4928 }
4929
4930 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004931 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004932 if (1 != v) return -EINVAL;
4933
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004934 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004935 if ((v < 0) ||
4936 (tempInt <= 0) ||
4937 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4938 {
4939 return -EINVAL;
4940 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004941
4942 *pChannel = tempInt;
4943 return VOS_STATUS_SUCCESS;
4944}
4945
4946#endif
4947
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004948#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004949/**---------------------------------------------------------------------------
4950
4951 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4952
4953 This function parses the SETCCKM IE command
4954 SETCCKMIE<space><ie data>
4955
4956 \param - pValue Pointer to input data
4957 \param - pCckmIe Pointer to output cckm Ie
4958 \param - pCckmIeLen Pointer to output cckm ie length
4959
4960 \return - 0 for success non-zero for failure
4961
4962 --------------------------------------------------------------------------*/
4963VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4964 tANI_U8 *pCckmIeLen)
4965{
4966 tANI_U8 *inPtr = pValue;
4967 tANI_U8 *dataEnd;
4968 int j = 0;
4969 int i = 0;
4970 tANI_U8 tempByte = 0;
4971
4972 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4973 /*no argument after the command*/
4974 if (NULL == inPtr)
4975 {
4976 return -EINVAL;
4977 }
4978
4979 /*no space after the command*/
4980 else if (SPACE_ASCII_VALUE != *inPtr)
4981 {
4982 return -EINVAL;
4983 }
4984
4985 /*removing empty spaces*/
4986 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4987
4988 /*no argument followed by spaces*/
4989 if ('\0' == *inPtr)
4990 {
4991 return -EINVAL;
4992 }
4993
4994 /* find the length of data */
4995 dataEnd = inPtr;
4996 while(('\0' != *dataEnd) )
4997 {
4998 dataEnd++;
4999 ++(*pCckmIeLen);
5000 }
5001 if ( *pCckmIeLen <= 0) return -EINVAL;
5002
5003 /* Allocate the number of bytes based on the number of input characters
5004 whether it is even or odd.
5005 if the number of input characters are even, then we need N/2 byte.
5006 if the number of input characters are odd, then we need do (N+1)/2 to
5007 compensate rounding off.
5008 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5009 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5010 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5011 if (NULL == *pCckmIe)
5012 {
5013 hddLog(VOS_TRACE_LEVEL_FATAL,
5014 "%s: vos_mem_alloc failed ", __func__);
5015 return -EINVAL;
5016 }
5017 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5018 /* the buffer received from the upper layer is character buffer,
5019 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5020 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5021 and f0 in 3rd location */
5022 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5023 {
5024 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5025 (*pCckmIe)[i++] = tempByte;
5026 }
5027 *pCckmIeLen = i;
5028
5029 return VOS_STATUS_SUCCESS;
5030}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005031#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005032
Jeff Johnson295189b2012-06-20 16:38:30 -07005033/**---------------------------------------------------------------------------
5034
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005035 \brief hdd_is_valid_mac_address() - Validate MAC address
5036
5037 This function validates whether the given MAC address is valid or not
5038 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5039 where X is the hexa decimal digit character and separated by ':'
5040 This algorithm works even if MAC address is not separated by ':'
5041
5042 This code checks given input string mac contains exactly 12 hexadecimal digits.
5043 and a separator colon : appears in the input string only after
5044 an even number of hex digits.
5045
5046 \param - pMacAddr pointer to the input MAC address
5047 \return - 1 for valid and 0 for invalid
5048
5049 --------------------------------------------------------------------------*/
5050
5051v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5052{
5053 int xdigit = 0;
5054 int separator = 0;
5055 while (*pMacAddr)
5056 {
5057 if (isxdigit(*pMacAddr))
5058 {
5059 xdigit++;
5060 }
5061 else if (':' == *pMacAddr)
5062 {
5063 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5064 break;
5065
5066 ++separator;
5067 }
5068 else
5069 {
5070 separator = -1;
5071 /* Invalid MAC found */
5072 return 0;
5073 }
5074 ++pMacAddr;
5075 }
5076 return (xdigit == 12 && (separator == 5 || separator == 0));
5077}
5078
5079/**---------------------------------------------------------------------------
5080
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305081 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005082
5083 \param - dev Pointer to net_device structure
5084
5085 \return - 0 for success non-zero for failure
5086
5087 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305088int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005089{
5090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5091 hdd_context_t *pHddCtx;
5092 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5093 VOS_STATUS status;
5094 v_BOOL_t in_standby = TRUE;
5095
5096 if (NULL == pAdapter)
5097 {
5098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305099 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005100 return -ENODEV;
5101 }
5102
5103 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305104 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5105 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 if (NULL == pHddCtx)
5107 {
5108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005109 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 return -ENODEV;
5111 }
5112
5113 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5114 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5115 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005116 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5117 {
5118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305119 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005120 in_standby = FALSE;
5121 break;
5122 }
5123 else
5124 {
5125 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5126 pAdapterNode = pNext;
5127 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005128 }
5129
5130 if (TRUE == in_standby)
5131 {
5132 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5133 {
5134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5135 "wlan out of power save", __func__);
5136 return -EINVAL;
5137 }
5138 }
5139
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005140 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005141 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5142 {
5143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005144 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 /* Enable TX queues only when we are connected */
5146 netif_tx_start_all_queues(dev);
5147 }
5148
5149 return 0;
5150}
5151
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305152/**---------------------------------------------------------------------------
5153
5154 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5155
5156 This is called in response to ifconfig up
5157
5158 \param - dev Pointer to net_device structure
5159
5160 \return - 0 for success non-zero for failure
5161
5162 --------------------------------------------------------------------------*/
5163int hdd_open(struct net_device *dev)
5164{
5165 int ret;
5166
5167 vos_ssr_protect(__func__);
5168 ret = __hdd_open(dev);
5169 vos_ssr_unprotect(__func__);
5170
5171 return ret;
5172}
5173
Jeff Johnson295189b2012-06-20 16:38:30 -07005174int hdd_mon_open (struct net_device *dev)
5175{
5176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5177
5178 if(pAdapter == NULL) {
5179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005180 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005181 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005182 }
5183
5184 netif_start_queue(dev);
5185
5186 return 0;
5187}
5188/**---------------------------------------------------------------------------
5189
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305190 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005191
5192 \param - dev Pointer to net_device structure
5193
5194 \return - 0 for success non-zero for failure
5195
5196 --------------------------------------------------------------------------*/
5197
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305198int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005199{
5200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5201 hdd_context_t *pHddCtx;
5202 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5203 VOS_STATUS status;
5204 v_BOOL_t enter_standby = TRUE;
5205
5206 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005207 if (NULL == pAdapter)
5208 {
5209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305210 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 return -ENODEV;
5212 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305213 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5214 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005215 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5216 if (NULL == pHddCtx)
5217 {
5218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005219 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 return -ENODEV;
5221 }
5222
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305223 /* Nothing to be done if the interface is not opened */
5224 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5225 {
5226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5227 "%s: NETDEV Interface is not OPENED", __func__);
5228 return -ENODEV;
5229 }
5230
5231 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005232 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305234
5235 /* Disable TX on the interface, after this hard_start_xmit() will not
5236 * be called on that interface
5237 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005238 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305239
5240 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 netif_carrier_off(pAdapter->dev);
5242
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305243 /* The interface is marked as down for outside world (aka kernel)
5244 * But the driver is pretty much alive inside. The driver needs to
5245 * tear down the existing connection on the netdev (session)
5246 * cleanup the data pipes and wait until the control plane is stabilized
5247 * for this interface. The call also needs to wait until the above
5248 * mentioned actions are completed before returning to the caller.
5249 * Notice that the hdd_stop_adapter is requested not to close the session
5250 * That is intentional to be able to scan if it is a STA/P2P interface
5251 */
5252 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005253
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305254 /* DeInit the adapter. This ensures datapath cleanup as well */
5255 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005256 /* SoftAP ifaces should never go in power save mode
5257 making sure same here. */
5258 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5259 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 )
5262 {
5263 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5265 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005266 EXIT();
5267 return 0;
5268 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305269 /* Find if any iface is up. If any iface is up then can't put device to
5270 * sleep/power save mode
5271 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005272 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5273 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5274 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005275 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5276 {
5277 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305278 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005279 enter_standby = FALSE;
5280 break;
5281 }
5282 else
5283 {
5284 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5285 pAdapterNode = pNext;
5286 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005287 }
5288
5289 if (TRUE == enter_standby)
5290 {
5291 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5292 "entering standby", __func__);
5293 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5294 {
5295 /*log and return success*/
5296 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5297 "wlan in power save", __func__);
5298 }
5299 }
5300
5301 EXIT();
5302 return 0;
5303}
5304
5305/**---------------------------------------------------------------------------
5306
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305307 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005308
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305309 This is called in response to ifconfig down
5310
5311 \param - dev Pointer to net_device structure
5312
5313 \return - 0 for success non-zero for failure
5314-----------------------------------------------------------------------------*/
5315int hdd_stop (struct net_device *dev)
5316{
5317 int ret;
5318
5319 vos_ssr_protect(__func__);
5320 ret = __hdd_stop(dev);
5321 vos_ssr_unprotect(__func__);
5322
5323 return ret;
5324}
5325
5326/**---------------------------------------------------------------------------
5327
5328 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005329
5330 \param - dev Pointer to net_device structure
5331
5332 \return - void
5333
5334 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305335static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005336{
5337 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5338
5339 ENTER();
5340
5341 do
5342 {
5343 if (NULL == pAdapter)
5344 {
5345 hddLog(VOS_TRACE_LEVEL_FATAL,
5346 "%s: NULL pAdapter", __func__);
5347 break;
5348 }
5349
5350 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5351 {
5352 hddLog(VOS_TRACE_LEVEL_FATAL,
5353 "%s: Invalid magic", __func__);
5354 break;
5355 }
5356
5357 if (NULL == pAdapter->pHddCtx)
5358 {
5359 hddLog(VOS_TRACE_LEVEL_FATAL,
5360 "%s: NULL pHddCtx", __func__);
5361 break;
5362 }
5363
5364 if (dev != pAdapter->dev)
5365 {
5366 hddLog(VOS_TRACE_LEVEL_FATAL,
5367 "%s: Invalid device reference", __func__);
5368 /* we haven't validated all cases so let this go for now */
5369 }
5370
5371 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5372
5373 /* after uninit our adapter structure will no longer be valid */
5374 pAdapter->dev = NULL;
5375 pAdapter->magic = 0;
5376 } while (0);
5377
5378 EXIT();
5379}
5380
5381/**---------------------------------------------------------------------------
5382
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305383 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5384
5385 This is called during the netdev unregister to uninitialize all data
5386associated with the device
5387
5388 \param - dev Pointer to net_device structure
5389
5390 \return - void
5391
5392 --------------------------------------------------------------------------*/
5393static void hdd_uninit (struct net_device *dev)
5394{
5395 vos_ssr_protect(__func__);
5396 __hdd_uninit(dev);
5397 vos_ssr_unprotect(__func__);
5398}
5399
5400/**---------------------------------------------------------------------------
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 \brief hdd_release_firmware() -
5403
5404 This function calls the release firmware API to free the firmware buffer.
5405
5406 \param - pFileName Pointer to the File Name.
5407 pCtx - Pointer to the adapter .
5408
5409
5410 \return - 0 for success, non zero for failure
5411
5412 --------------------------------------------------------------------------*/
5413
5414VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5415{
5416 VOS_STATUS status = VOS_STATUS_SUCCESS;
5417 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5418 ENTER();
5419
5420
5421 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5422
5423 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5424
5425 if(pHddCtx->fw) {
5426 release_firmware(pHddCtx->fw);
5427 pHddCtx->fw = NULL;
5428 }
5429 else
5430 status = VOS_STATUS_E_FAILURE;
5431 }
5432 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5433 if(pHddCtx->nv) {
5434 release_firmware(pHddCtx->nv);
5435 pHddCtx->nv = NULL;
5436 }
5437 else
5438 status = VOS_STATUS_E_FAILURE;
5439
5440 }
5441
5442 EXIT();
5443 return status;
5444}
5445
5446/**---------------------------------------------------------------------------
5447
5448 \brief hdd_request_firmware() -
5449
5450 This function reads the firmware file using the request firmware
5451 API and returns the the firmware data and the firmware file size.
5452
5453 \param - pfileName - Pointer to the file name.
5454 - pCtx - Pointer to the adapter .
5455 - ppfw_data - Pointer to the pointer of the firmware data.
5456 - pSize - Pointer to the file size.
5457
5458 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5459
5460 --------------------------------------------------------------------------*/
5461
5462
5463VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5464{
5465 int status;
5466 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5467 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5468 ENTER();
5469
5470 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5471
5472 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5473
5474 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5476 __func__, pfileName);
5477 retval = VOS_STATUS_E_FAILURE;
5478 }
5479
5480 else {
5481 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5482 *pSize = pHddCtx->fw->size;
5483 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5484 __func__, *pSize);
5485 }
5486 }
5487 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5488
5489 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5490
5491 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5492 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5493 __func__, pfileName);
5494 retval = VOS_STATUS_E_FAILURE;
5495 }
5496
5497 else {
5498 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5499 *pSize = pHddCtx->nv->size;
5500 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5501 __func__, *pSize);
5502 }
5503 }
5504
5505 EXIT();
5506 return retval;
5507}
5508/**---------------------------------------------------------------------------
5509 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5510
5511 This is the function invoked by SME to inform the result of a full power
5512 request issued by HDD
5513
5514 \param - callbackcontext - Pointer to cookie
5515 status - result of request
5516
5517 \return - None
5518
5519--------------------------------------------------------------------------*/
5520void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5521{
5522 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5523
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005524 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 if(&pHddCtx->full_pwr_comp_var)
5526 {
5527 complete(&pHddCtx->full_pwr_comp_var);
5528 }
5529}
5530
5531/**---------------------------------------------------------------------------
5532
5533 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5534
5535 This is the function invoked by SME to inform the result of BMPS
5536 request issued by HDD
5537
5538 \param - callbackcontext - Pointer to cookie
5539 status - result of request
5540
5541 \return - None
5542
5543--------------------------------------------------------------------------*/
5544void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5545{
5546
5547 struct completion *completion_var = (struct completion*) callbackContext;
5548
Arif Hussain6d2a3322013-11-17 19:50:10 -08005549 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 if(completion_var != NULL)
5551 {
5552 complete(completion_var);
5553 }
5554}
5555
5556/**---------------------------------------------------------------------------
5557
5558 \brief hdd_get_cfg_file_size() -
5559
5560 This function reads the configuration file using the request firmware
5561 API and returns the configuration file size.
5562
5563 \param - pCtx - Pointer to the adapter .
5564 - pFileName - Pointer to the file name.
5565 - pBufSize - Pointer to the buffer size.
5566
5567 \return - 0 for success, non zero for failure
5568
5569 --------------------------------------------------------------------------*/
5570
5571VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5572{
5573 int status;
5574 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5575
5576 ENTER();
5577
5578 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5579
5580 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5581 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5582 status = VOS_STATUS_E_FAILURE;
5583 }
5584 else {
5585 *pBufSize = pHddCtx->fw->size;
5586 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5587 release_firmware(pHddCtx->fw);
5588 pHddCtx->fw = NULL;
5589 }
5590
5591 EXIT();
5592 return VOS_STATUS_SUCCESS;
5593}
5594
5595/**---------------------------------------------------------------------------
5596
5597 \brief hdd_read_cfg_file() -
5598
5599 This function reads the configuration file using the request firmware
5600 API and returns the cfg data and the buffer size of the configuration file.
5601
5602 \param - pCtx - Pointer to the adapter .
5603 - pFileName - Pointer to the file name.
5604 - pBuffer - Pointer to the data buffer.
5605 - pBufSize - Pointer to the buffer size.
5606
5607 \return - 0 for success, non zero for failure
5608
5609 --------------------------------------------------------------------------*/
5610
5611VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5612 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5613{
5614 int status;
5615 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5616
5617 ENTER();
5618
5619 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5620
5621 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5622 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5623 return VOS_STATUS_E_FAILURE;
5624 }
5625 else {
5626 if(*pBufSize != pHddCtx->fw->size) {
5627 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5628 "file size", __func__);
5629 release_firmware(pHddCtx->fw);
5630 pHddCtx->fw = NULL;
5631 return VOS_STATUS_E_FAILURE;
5632 }
5633 else {
5634 if(pBuffer) {
5635 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5636 }
5637 release_firmware(pHddCtx->fw);
5638 pHddCtx->fw = NULL;
5639 }
5640 }
5641
5642 EXIT();
5643
5644 return VOS_STATUS_SUCCESS;
5645}
5646
5647/**---------------------------------------------------------------------------
5648
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305649 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005650
5651 This function sets the user specified mac address using
5652 the command ifconfig wlanX hw ether <mac adress>.
5653
5654 \param - dev - Pointer to the net device.
5655 - addr - Pointer to the sockaddr.
5656 \return - 0 for success, non zero for failure
5657
5658 --------------------------------------------------------------------------*/
5659
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305660static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005661{
5662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5663 struct sockaddr *psta_mac_addr = addr;
5664 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5665
5666 ENTER();
5667
5668 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5670
5671 EXIT();
5672 return halStatus;
5673}
5674
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305675/**---------------------------------------------------------------------------
5676
5677 \brief hdd_set_mac_address() -
5678
5679 Wrapper function to protect __hdd_set_mac_address() function from ssr
5680
5681 \param - dev - Pointer to the net device.
5682 - addr - Pointer to the sockaddr.
5683 \return - 0 for success, non zero for failure
5684
5685 --------------------------------------------------------------------------*/
5686static int hdd_set_mac_address(struct net_device *dev, void *addr)
5687{
5688 int ret;
5689
5690 vos_ssr_protect(__func__);
5691 ret = __hdd_set_mac_address(dev, addr);
5692 vos_ssr_unprotect(__func__);
5693
5694 return ret;
5695}
5696
Jeff Johnson295189b2012-06-20 16:38:30 -07005697tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5698{
5699 int i;
5700 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5701 {
Abhishek Singheb183782014-02-06 13:37:21 +05305702 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 break;
5704 }
5705
5706 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5707 return NULL;
5708
5709 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5710 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5711}
5712
5713void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5714{
5715 int i;
5716 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5717 {
5718 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5719 {
5720 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5721 break;
5722 }
5723 }
5724 return;
5725}
5726
5727#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5728 static struct net_device_ops wlan_drv_ops = {
5729 .ndo_open = hdd_open,
5730 .ndo_stop = hdd_stop,
5731 .ndo_uninit = hdd_uninit,
5732 .ndo_start_xmit = hdd_hard_start_xmit,
5733 .ndo_tx_timeout = hdd_tx_timeout,
5734 .ndo_get_stats = hdd_stats,
5735 .ndo_do_ioctl = hdd_ioctl,
5736 .ndo_set_mac_address = hdd_set_mac_address,
5737 .ndo_select_queue = hdd_select_queue,
5738#ifdef WLAN_FEATURE_PACKET_FILTERING
5739#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5740 .ndo_set_rx_mode = hdd_set_multicast_list,
5741#else
5742 .ndo_set_multicast_list = hdd_set_multicast_list,
5743#endif //LINUX_VERSION_CODE
5744#endif
5745 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005746 static struct net_device_ops wlan_mon_drv_ops = {
5747 .ndo_open = hdd_mon_open,
5748 .ndo_stop = hdd_stop,
5749 .ndo_uninit = hdd_uninit,
5750 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5751 .ndo_tx_timeout = hdd_tx_timeout,
5752 .ndo_get_stats = hdd_stats,
5753 .ndo_do_ioctl = hdd_ioctl,
5754 .ndo_set_mac_address = hdd_set_mac_address,
5755 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005756
5757#endif
5758
5759void hdd_set_station_ops( struct net_device *pWlanDev )
5760{
5761#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005762 pWlanDev->netdev_ops = &wlan_drv_ops;
5763#else
5764 pWlanDev->open = hdd_open;
5765 pWlanDev->stop = hdd_stop;
5766 pWlanDev->uninit = hdd_uninit;
5767 pWlanDev->hard_start_xmit = NULL;
5768 pWlanDev->tx_timeout = hdd_tx_timeout;
5769 pWlanDev->get_stats = hdd_stats;
5770 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 pWlanDev->set_mac_address = hdd_set_mac_address;
5772#endif
5773}
5774
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005775static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005776{
5777 struct net_device *pWlanDev = NULL;
5778 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005779 /*
5780 * cfg80211 initialization and registration....
5781 */
5782 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5783
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 if(pWlanDev != NULL)
5785 {
5786
5787 //Save the pointer to the net_device in the HDD adapter
5788 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5789
Jeff Johnson295189b2012-06-20 16:38:30 -07005790 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5791
5792 pAdapter->dev = pWlanDev;
5793 pAdapter->pHddCtx = pHddCtx;
5794 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305795 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005796
5797 init_completion(&pAdapter->session_open_comp_var);
5798 init_completion(&pAdapter->session_close_comp_var);
5799 init_completion(&pAdapter->disconnect_comp_var);
5800 init_completion(&pAdapter->linkup_event_var);
5801 init_completion(&pAdapter->cancel_rem_on_chan_var);
5802 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305803 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005804#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5805 init_completion(&pAdapter->offchannel_tx_event);
5806#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005807 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005808#ifdef FEATURE_WLAN_TDLS
5809 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005810 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005811 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305812 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005813#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 init_completion(&pHddCtx->mc_sus_event_var);
5815 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305816 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005817 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005818 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005819
Rajeev79dbe4c2013-10-05 11:03:42 +05305820#ifdef FEATURE_WLAN_BATCH_SCAN
5821 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5822 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5823 pAdapter->pBatchScanRsp = NULL;
5824 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005825 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005826 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305827 mutex_init(&pAdapter->hdd_batch_scan_lock);
5828#endif
5829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 pAdapter->isLinkUpSvcNeeded = FALSE;
5831 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5832 //Init the net_device structure
5833 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5834
5835 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5836 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5837 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5838 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5839
5840 hdd_set_station_ops( pAdapter->dev );
5841
5842 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5844 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5845 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005846 /* set pWlanDev's parent to underlying device */
5847 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005848
5849 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005850 }
5851
5852 return pAdapter;
5853}
5854
5855VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5856{
5857 struct net_device *pWlanDev = pAdapter->dev;
5858 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5859 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5860 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5861
5862 if( rtnl_lock_held )
5863 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005864 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5866 {
5867 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5868 return VOS_STATUS_E_FAILURE;
5869 }
5870 }
5871 if (register_netdevice(pWlanDev))
5872 {
5873 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5874 return VOS_STATUS_E_FAILURE;
5875 }
5876 }
5877 else
5878 {
5879 if(register_netdev(pWlanDev))
5880 {
5881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5882 return VOS_STATUS_E_FAILURE;
5883 }
5884 }
5885 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5886
5887 return VOS_STATUS_SUCCESS;
5888}
5889
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005890static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005891{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005892 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005893
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005894 if (NULL == pAdapter)
5895 {
5896 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5897 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005899
5900 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5901 {
5902 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5903 return eHAL_STATUS_NOT_INITIALIZED;
5904 }
5905
5906 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5907
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005908#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005909 /* need to make sure all of our scheduled work has completed.
5910 * This callback is called from MC thread context, so it is safe to
5911 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005912 *
5913 * Even though this is called from MC thread context, if there is a faulty
5914 * work item in the system, that can hang this call forever. So flushing
5915 * this global work queue is not safe; and now we make sure that
5916 * individual work queues are stopped correctly. But the cancel work queue
5917 * is a GPL only API, so the proprietary version of the driver would still
5918 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005919 */
5920 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005921#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005922
5923 /* We can be blocked while waiting for scheduled work to be
5924 * flushed, and the adapter structure can potentially be freed, in
5925 * which case the magic will have been reset. So make sure the
5926 * magic is still good, and hence the adapter structure is still
5927 * valid, before signaling completion */
5928 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5929 {
5930 complete(&pAdapter->session_close_comp_var);
5931 }
5932
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 return eHAL_STATUS_SUCCESS;
5934}
5935
5936VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5937{
5938 struct net_device *pWlanDev = pAdapter->dev;
5939 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5940 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5941 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5942 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305943 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005944
5945 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005946 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 //Open a SME session for future operation
5948 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005949 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5951 {
5952 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005953 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 halStatus, halStatus );
5955 status = VOS_STATUS_E_FAILURE;
5956 goto error_sme_open;
5957 }
5958
5959 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305960 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 &pAdapter->session_open_comp_var,
5962 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305963 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005964 {
5965 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305966 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 status = VOS_STATUS_E_FAILURE;
5968 goto error_sme_open;
5969 }
5970
5971 // Register wireless extensions
5972 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5973 {
5974 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005975 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 halStatus, halStatus );
5977 status = VOS_STATUS_E_FAILURE;
5978 goto error_register_wext;
5979 }
5980 //Safe to register the hard_start_xmit function again
5981#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5982 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5983#else
5984 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5985#endif
5986
5987 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305988 hddLog(VOS_TRACE_LEVEL_INFO,
5989 "%s: Set HDD connState to eConnectionState_NotConnected",
5990 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5992
5993 //Set the default operation channel
5994 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5995
5996 /* Make the default Auth Type as OPEN*/
5997 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5998
5999 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6000 {
6001 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006002 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 status, status );
6004 goto error_init_txrx;
6005 }
6006
6007 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6008
6009 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6010 {
6011 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006012 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 status, status );
6014 goto error_wmm_init;
6015 }
6016
6017 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6018
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006019#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306020 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006021 {
6022 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306023 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006024 goto error_tdls_init;
6025 }
6026 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6027#endif
6028
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 return VOS_STATUS_SUCCESS;
6030
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006031#ifdef FEATURE_WLAN_TDLS
6032error_tdls_init:
6033 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6034 hdd_wmm_adapter_close(pAdapter);
6035#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006036error_wmm_init:
6037 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6038 hdd_deinit_tx_rx(pAdapter);
6039error_init_txrx:
6040 hdd_UnregisterWext(pWlanDev);
6041error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006042 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 {
6044 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006045 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006047 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306049 unsigned long rc;
6050
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306052 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006054 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306055 if (rc <= 0)
6056 hddLog(VOS_TRACE_LEVEL_ERROR,
6057 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006058 }
6059}
6060error_sme_open:
6061 return status;
6062}
6063
Jeff Johnson295189b2012-06-20 16:38:30 -07006064void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6065{
6066 hdd_cfg80211_state_t *cfgState;
6067
6068 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6069
6070 if( NULL != cfgState->buf )
6071 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306072 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006073 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6074 rc = wait_for_completion_interruptible_timeout(
6075 &pAdapter->tx_action_cnf_event,
6076 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306077 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006078 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306080 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6081 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 }
6083 }
6084 return;
6085}
Jeff Johnson295189b2012-06-20 16:38:30 -07006086
6087void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6088{
6089 ENTER();
6090 switch ( pAdapter->device_mode )
6091 {
6092 case WLAN_HDD_INFRA_STATION:
6093 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006094 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006095 {
6096 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6097 {
6098 hdd_deinit_tx_rx( pAdapter );
6099 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6100 }
6101
6102 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6103 {
6104 hdd_wmm_adapter_close( pAdapter );
6105 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6106 }
6107
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006109#ifdef FEATURE_WLAN_TDLS
6110 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6111 {
6112 wlan_hdd_tdls_exit(pAdapter);
6113 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6114 }
6115#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006116
6117 break;
6118 }
6119
6120 case WLAN_HDD_SOFTAP:
6121 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306123
6124 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6125 {
6126 hdd_wmm_adapter_close( pAdapter );
6127 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6128 }
6129
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006131
6132 hdd_unregister_hostapd(pAdapter);
6133 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006134 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 break;
6136 }
6137
6138 case WLAN_HDD_MONITOR:
6139 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6142 {
6143 hdd_deinit_tx_rx( pAdapter );
6144 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6145 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006146 if(NULL != pAdapterforTx)
6147 {
6148 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6149 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006150 break;
6151 }
6152
6153
6154 default:
6155 break;
6156 }
6157
6158 EXIT();
6159}
6160
6161void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6162{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006163 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306164
6165 ENTER();
6166 if (NULL == pAdapter)
6167 {
6168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6169 "%s: HDD adapter is Null", __func__);
6170 return;
6171 }
6172
6173 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006174
Rajeev79dbe4c2013-10-05 11:03:42 +05306175#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306176 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6177 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006178 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306179 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6180 )
6181 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006182 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306183 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006184 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6185 {
6186 hdd_deinit_batch_scan(pAdapter);
6187 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306188 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006189 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306190#endif
6191
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6193 if( rtnl_held )
6194 {
6195 unregister_netdevice(pWlanDev);
6196 }
6197 else
6198 {
6199 unregister_netdev(pWlanDev);
6200 }
6201 // note that the pAdapter is no longer valid at this point
6202 // since the memory has been reclaimed
6203 }
6204
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306205 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006206}
6207
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006208void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6209{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306210 VOS_STATUS status;
6211 hdd_adapter_t *pAdapter = NULL;
6212 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006213
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306214 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006215
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306216 /*loop through all adapters.*/
6217 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006218 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306219 pAdapter = pAdapterNode->pAdapter;
6220 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6221 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006222
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306223 { // we skip this registration for modes other than STA and P2P client modes.
6224 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6225 pAdapterNode = pNext;
6226 continue;
6227 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006228
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306229 //Apply Dynamic DTIM For P2P
6230 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6231 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6232 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6233 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6234 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6235 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6236 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6237 (eConnectionState_Associated ==
6238 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6239 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6240 {
6241 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006242
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306243 powerRequest.uIgnoreDTIM = 1;
6244 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6245
6246 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6247 {
6248 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6249 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6250 }
6251 else
6252 {
6253 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6254 }
6255
6256 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6257 * specified during Enter/Exit BMPS when LCD off*/
6258 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6259 NULL, eANI_BOOLEAN_FALSE);
6260 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6261 NULL, eANI_BOOLEAN_FALSE);
6262
6263 /* switch to the DTIM specified in cfg.ini */
6264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6265 "Switch to DTIM %d", powerRequest.uListenInterval);
6266 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6267 break;
6268
6269 }
6270
6271 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6272 pAdapterNode = pNext;
6273 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006274}
6275
6276void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6277{
6278 /*Switch back to DTIM 1*/
6279 tSirSetPowerParamsReq powerRequest = { 0 };
6280
6281 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6282 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006283 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006284
6285 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6286 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6287 NULL, eANI_BOOLEAN_FALSE);
6288 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6289 NULL, eANI_BOOLEAN_FALSE);
6290
6291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6292 "Switch to DTIM%d",powerRequest.uListenInterval);
6293 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6294
6295}
6296
Jeff Johnson295189b2012-06-20 16:38:30 -07006297VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6298{
6299 VOS_STATUS status = VOS_STATUS_SUCCESS;
6300
6301 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6302 {
6303 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6304 }
6305
6306 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6307 {
6308 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6309 }
6310
6311 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6312 {
6313 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6314 }
6315
6316 return status;
6317}
6318
6319VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6320{
6321 hdd_adapter_t *pAdapter = NULL;
6322 eHalStatus halStatus;
6323 VOS_STATUS status = VOS_STATUS_E_INVAL;
6324 v_BOOL_t disableBmps = FALSE;
6325 v_BOOL_t disableImps = FALSE;
6326
6327 switch(session_type)
6328 {
6329 case WLAN_HDD_INFRA_STATION:
6330 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 case WLAN_HDD_P2P_CLIENT:
6332 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 //Exit BMPS -> Is Sta/P2P Client is already connected
6334 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6335 if((NULL != pAdapter)&&
6336 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6337 {
6338 disableBmps = TRUE;
6339 }
6340
6341 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6342 if((NULL != pAdapter)&&
6343 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6344 {
6345 disableBmps = TRUE;
6346 }
6347
6348 //Exit both Bmps and Imps incase of Go/SAP Mode
6349 if((WLAN_HDD_SOFTAP == session_type) ||
6350 (WLAN_HDD_P2P_GO == session_type))
6351 {
6352 disableBmps = TRUE;
6353 disableImps = TRUE;
6354 }
6355
6356 if(TRUE == disableImps)
6357 {
6358 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6359 {
6360 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6361 }
6362 }
6363
6364 if(TRUE == disableBmps)
6365 {
6366 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6367 {
6368 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6369
6370 if(eHAL_STATUS_SUCCESS != halStatus)
6371 {
6372 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006373 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006374 VOS_ASSERT(0);
6375 return status;
6376 }
6377 }
6378
6379 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6380 {
6381 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6382
6383 if(eHAL_STATUS_SUCCESS != halStatus)
6384 {
6385 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006386 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006387 VOS_ASSERT(0);
6388 return status;
6389 }
6390 }
6391 }
6392
6393 if((TRUE == disableBmps) ||
6394 (TRUE == disableImps))
6395 {
6396 /* Now, get the chip into Full Power now */
6397 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6398 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6399 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6400
6401 if(halStatus != eHAL_STATUS_SUCCESS)
6402 {
6403 if(halStatus == eHAL_STATUS_PMC_PENDING)
6404 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306405 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006406 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306407 ret = wait_for_completion_interruptible_timeout(
6408 &pHddCtx->full_pwr_comp_var,
6409 msecs_to_jiffies(1000));
6410 if (ret <= 0)
6411 {
6412 hddLog(VOS_TRACE_LEVEL_ERROR,
6413 "%s: wait on full_pwr_comp_var failed %ld",
6414 __func__, ret);
6415 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006416 }
6417 else
6418 {
6419 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006420 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006421 VOS_ASSERT(0);
6422 return status;
6423 }
6424 }
6425
6426 status = VOS_STATUS_SUCCESS;
6427 }
6428
6429 break;
6430 }
6431 return status;
6432}
6433
6434hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006435 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 tANI_U8 rtnl_held )
6437{
6438 hdd_adapter_t *pAdapter = NULL;
6439 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6440 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6441 VOS_STATUS exitbmpsStatus;
6442
Arif Hussain6d2a3322013-11-17 19:50:10 -08006443 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006444
Nirav Shah436658f2014-02-28 17:05:45 +05306445 if(macAddr == NULL)
6446 {
6447 /* Not received valid macAddr */
6448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6449 "%s:Unable to add virtual intf: Not able to get"
6450 "valid mac address",__func__);
6451 return NULL;
6452 }
6453
Jeff Johnson295189b2012-06-20 16:38:30 -07006454 //Disable BMPS incase of Concurrency
6455 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6456
6457 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6458 {
6459 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306460 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006461 VOS_ASSERT(0);
6462 return NULL;
6463 }
6464
6465 switch(session_type)
6466 {
6467 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006468 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006469 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006470 {
6471 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6472
6473 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306474 {
6475 hddLog(VOS_TRACE_LEVEL_FATAL,
6476 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006477 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006479
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306480#ifdef FEATURE_WLAN_TDLS
6481 /* A Mutex Lock is introduced while changing/initializing the mode to
6482 * protect the concurrent access for the Adapters by TDLS module.
6483 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306484 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306485#endif
6486
Jeff Johnsone7245742012-09-05 17:12:55 -07006487 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6488 NL80211_IFTYPE_P2P_CLIENT:
6489 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006490
Jeff Johnson295189b2012-06-20 16:38:30 -07006491 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306492#ifdef FEATURE_WLAN_TDLS
6493 mutex_unlock(&pHddCtx->tdls_lock);
6494#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306495
6496 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006497 if( VOS_STATUS_SUCCESS != status )
6498 goto err_free_netdev;
6499
6500 status = hdd_register_interface( pAdapter, rtnl_held );
6501 if( VOS_STATUS_SUCCESS != status )
6502 {
6503 hdd_deinit_adapter(pHddCtx, pAdapter);
6504 goto err_free_netdev;
6505 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306506
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306507 // Workqueue which gets scheduled in IPv4 notification callback.
6508 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6509
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306510#ifdef WLAN_NS_OFFLOAD
6511 // Workqueue which gets scheduled in IPv6 notification callback.
6512 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6513#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006514 //Stop the Interface TX queue.
6515 netif_tx_disable(pAdapter->dev);
6516 //netif_tx_disable(pWlanDev);
6517 netif_carrier_off(pAdapter->dev);
6518
6519 break;
6520 }
6521
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006523 case WLAN_HDD_SOFTAP:
6524 {
6525 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6526 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306527 {
6528 hddLog(VOS_TRACE_LEVEL_FATAL,
6529 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006530 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306531 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6534 NL80211_IFTYPE_AP:
6535 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006536 pAdapter->device_mode = session_type;
6537
6538 status = hdd_init_ap_mode(pAdapter);
6539 if( VOS_STATUS_SUCCESS != status )
6540 goto err_free_netdev;
6541
6542 status = hdd_register_hostapd( pAdapter, rtnl_held );
6543 if( VOS_STATUS_SUCCESS != status )
6544 {
6545 hdd_deinit_adapter(pHddCtx, pAdapter);
6546 goto err_free_netdev;
6547 }
6548
6549 netif_tx_disable(pAdapter->dev);
6550 netif_carrier_off(pAdapter->dev);
6551
6552 hdd_set_conparam( 1 );
6553 break;
6554 }
6555 case WLAN_HDD_MONITOR:
6556 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6558 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306559 {
6560 hddLog(VOS_TRACE_LEVEL_FATAL,
6561 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306563 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006564
6565 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6566 pAdapter->device_mode = session_type;
6567 status = hdd_register_interface( pAdapter, rtnl_held );
6568#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6569 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6570#else
6571 pAdapter->dev->open = hdd_mon_open;
6572 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6573#endif
6574 hdd_init_tx_rx( pAdapter );
6575 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6576 //Set adapter to be used for data tx. It will use either GO or softap.
6577 pAdapter->sessionCtx.monitor.pAdapterForTx =
6578 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006579 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6580 {
6581 pAdapter->sessionCtx.monitor.pAdapterForTx =
6582 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6583 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006584 /* This workqueue will be used to transmit management packet over
6585 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006586 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6587 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6588 return NULL;
6589 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006590
Jeff Johnson295189b2012-06-20 16:38:30 -07006591 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6592 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 }
6594 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006595 case WLAN_HDD_FTM:
6596 {
6597 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6598
6599 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306600 {
6601 hddLog(VOS_TRACE_LEVEL_FATAL,
6602 FL("failed to allocate adapter for session %d"), session_type);
6603 return NULL;
6604 }
6605
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6607 * message while loading driver in FTM mode. */
6608 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6609 pAdapter->device_mode = session_type;
6610 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306611
6612 hdd_init_tx_rx( pAdapter );
6613
6614 //Stop the Interface TX queue.
6615 netif_tx_disable(pAdapter->dev);
6616 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006617 }
6618 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 default:
6620 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6622 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006623 VOS_ASSERT(0);
6624 return NULL;
6625 }
6626 }
6627
Jeff Johnson295189b2012-06-20 16:38:30 -07006628 if( VOS_STATUS_SUCCESS == status )
6629 {
6630 //Add it to the hdd's session list.
6631 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6632 if( NULL == pHddAdapterNode )
6633 {
6634 status = VOS_STATUS_E_NOMEM;
6635 }
6636 else
6637 {
6638 pHddAdapterNode->pAdapter = pAdapter;
6639 status = hdd_add_adapter_back ( pHddCtx,
6640 pHddAdapterNode );
6641 }
6642 }
6643
6644 if( VOS_STATUS_SUCCESS != status )
6645 {
6646 if( NULL != pAdapter )
6647 {
6648 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6649 pAdapter = NULL;
6650 }
6651 if( NULL != pHddAdapterNode )
6652 {
6653 vos_mem_free( pHddAdapterNode );
6654 }
6655
6656 goto resume_bmps;
6657 }
6658
6659 if(VOS_STATUS_SUCCESS == status)
6660 {
6661 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6662
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006663 //Initialize the WoWL service
6664 if(!hdd_init_wowl(pAdapter))
6665 {
6666 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6667 goto err_free_netdev;
6668 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006669 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006670 return pAdapter;
6671
6672err_free_netdev:
6673 free_netdev(pAdapter->dev);
6674 wlan_hdd_release_intf_addr( pHddCtx,
6675 pAdapter->macAddressCurrent.bytes );
6676
6677resume_bmps:
6678 //If bmps disabled enable it
6679 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6680 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306681 if (pHddCtx->hdd_wlan_suspended)
6682 {
6683 hdd_set_pwrparams(pHddCtx);
6684 }
6685 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006686 }
6687 return NULL;
6688}
6689
6690VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6691 tANI_U8 rtnl_held )
6692{
6693 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6694 VOS_STATUS status;
6695
6696 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6697 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306698 {
6699 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6700 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006701 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006703
6704 while ( pCurrent->pAdapter != pAdapter )
6705 {
6706 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6707 if( VOS_STATUS_SUCCESS != status )
6708 break;
6709
6710 pCurrent = pNext;
6711 }
6712 pAdapterNode = pCurrent;
6713 if( VOS_STATUS_SUCCESS == status )
6714 {
6715 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6716 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306717
6718#ifdef FEATURE_WLAN_TDLS
6719
6720 /* A Mutex Lock is introduced while changing/initializing the mode to
6721 * protect the concurrent access for the Adapters by TDLS module.
6722 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306723 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306724#endif
6725
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 hdd_remove_adapter( pHddCtx, pAdapterNode );
6727 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006728 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006729
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306730#ifdef FEATURE_WLAN_TDLS
6731 mutex_unlock(&pHddCtx->tdls_lock);
6732#endif
6733
Jeff Johnson295189b2012-06-20 16:38:30 -07006734
6735 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306736 if ((!vos_concurrent_open_sessions_running()) &&
6737 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6738 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006739 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306740 if (pHddCtx->hdd_wlan_suspended)
6741 {
6742 hdd_set_pwrparams(pHddCtx);
6743 }
6744 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006745 }
6746
6747 return VOS_STATUS_SUCCESS;
6748 }
6749
6750 return VOS_STATUS_E_FAILURE;
6751}
6752
6753VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6754{
6755 hdd_adapter_list_node_t *pHddAdapterNode;
6756 VOS_STATUS status;
6757
6758 ENTER();
6759
6760 do
6761 {
6762 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6763 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6764 {
6765 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6766 vos_mem_free( pHddAdapterNode );
6767 }
6768 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6769
6770 EXIT();
6771
6772 return VOS_STATUS_SUCCESS;
6773}
6774
6775void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6776{
6777 v_U8_t addIE[1] = {0};
6778
6779 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6780 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6781 eANI_BOOLEAN_FALSE) )
6782 {
6783 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006784 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 }
6786
6787 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6788 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6789 eANI_BOOLEAN_FALSE) )
6790 {
6791 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006792 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006793 }
6794
6795 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6796 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6797 eANI_BOOLEAN_FALSE) )
6798 {
6799 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006800 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006801 }
6802}
6803
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306804VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6805 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006806{
6807 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6808 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6809 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306810 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306811 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006812
6813 ENTER();
6814
6815 switch(pAdapter->device_mode)
6816 {
6817 case WLAN_HDD_INFRA_STATION:
6818 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006819 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306820 {
6821 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6822 if( hdd_connIsConnected(pstation) ||
6823 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006824 {
6825 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6826 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6827 pAdapter->sessionId,
6828 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6829 else
6830 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6831 pAdapter->sessionId,
6832 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6833 //success implies disconnect command got queued up successfully
6834 if(halStatus == eHAL_STATUS_SUCCESS)
6835 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306836 ret = wait_for_completion_interruptible_timeout(
6837 &pAdapter->disconnect_comp_var,
6838 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6839 if (ret <= 0)
6840 {
6841 hddLog(VOS_TRACE_LEVEL_ERROR,
6842 "%s: wait on disconnect_comp_var failed %ld",
6843 __func__, ret);
6844 }
6845 }
6846 else
6847 {
6848 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6849 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006850 }
6851 memset(&wrqu, '\0', sizeof(wrqu));
6852 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6853 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6854 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6855 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306856 else if(pstation->conn_info.connState ==
6857 eConnectionState_Disconnecting)
6858 {
6859 ret = wait_for_completion_interruptible_timeout(
6860 &pAdapter->disconnect_comp_var,
6861 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6862 if (ret <= 0)
6863 {
6864 hddLog(VOS_TRACE_LEVEL_ERROR,
6865 FL("wait on disconnect_comp_var failed %ld"), ret);
6866 }
6867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006868 else
6869 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306870 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6871 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006872 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306873 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6874 {
6875 while (pAdapter->is_roc_inprogress)
6876 {
6877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6878 "%s: ROC in progress for session %d!!!",
6879 __func__, pAdapter->sessionId);
6880 // waiting for ROC to expire
6881 msleep(500);
6882 /* In GO present case , if retry exceeds 3,
6883 it means something went wrong. */
6884 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6885 {
6886 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6887 "%s: ROC completion is not received.!!!", __func__);
6888 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6889 pAdapter->sessionId);
6890 wait_for_completion_interruptible_timeout(
6891 &pAdapter->cancel_rem_on_chan_var,
6892 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6893 break;
6894 }
6895 }
6896 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306897#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306898#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306899 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6900#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306901 if (pAdapter->ipv6_notifier_registered)
6902 {
6903 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6904 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6905 pAdapter->ipv6_notifier_registered = false;
6906 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306907#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306908 if (pAdapter->ipv4_notifier_registered)
6909 {
6910 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6911 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6912 pAdapter->ipv4_notifier_registered = false;
6913 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306914#ifdef WLAN_OPEN_SOURCE
6915 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6916#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306917 /* It is possible that the caller of this function does not
6918 * wish to close the session
6919 */
6920 if (VOS_TRUE == bCloseSession &&
6921 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006922 {
6923 INIT_COMPLETION(pAdapter->session_close_comp_var);
6924 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306925 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6926 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306928 unsigned long ret;
6929
Jeff Johnson295189b2012-06-20 16:38:30 -07006930 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306931 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306932 &pAdapter->session_close_comp_var,
6933 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306934 if ( 0 >= ret)
6935 {
6936 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306937 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006939 }
6940 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306941 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006942 break;
6943
6944 case WLAN_HDD_SOFTAP:
6945 case WLAN_HDD_P2P_GO:
6946 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306947 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6948 while (pAdapter->is_roc_inprogress) {
6949 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6950 "%s: ROC in progress for session %d!!!",
6951 __func__, pAdapter->sessionId);
6952 msleep(500);
6953 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6955 "%s: ROC completion is not received.!!!", __func__);
6956 WLANSAP_CancelRemainOnChannel(
6957 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6958 wait_for_completion_interruptible_timeout(
6959 &pAdapter->cancel_rem_on_chan_var,
6960 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6961 break;
6962 }
6963 }
6964 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006965 mutex_lock(&pHddCtx->sap_lock);
6966 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6967 {
6968 VOS_STATUS status;
6969 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6970
6971 //Stop Bss.
6972 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6973 if (VOS_IS_STATUS_SUCCESS(status))
6974 {
6975 hdd_hostapd_state_t *pHostapdState =
6976 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6977
6978 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6979
6980 if (!VOS_IS_STATUS_SUCCESS(status))
6981 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306982 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6983 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 }
6985 }
6986 else
6987 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006988 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006989 }
6990 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306991 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006992
6993 if (eHAL_STATUS_FAILURE ==
6994 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6995 0, NULL, eANI_BOOLEAN_FALSE))
6996 {
6997 hddLog(LOGE,
6998 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006999 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007000 }
7001
7002 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7003 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7004 eANI_BOOLEAN_FALSE) )
7005 {
7006 hddLog(LOGE,
7007 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7008 }
7009
7010 // Reset WNI_CFG_PROBE_RSP Flags
7011 wlan_hdd_reset_prob_rspies(pAdapter);
7012 kfree(pAdapter->sessionCtx.ap.beacon);
7013 pAdapter->sessionCtx.ap.beacon = NULL;
7014 }
7015 mutex_unlock(&pHddCtx->sap_lock);
7016 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007017
Jeff Johnson295189b2012-06-20 16:38:30 -07007018 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007019#ifdef WLAN_OPEN_SOURCE
7020 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007023
Jeff Johnson295189b2012-06-20 16:38:30 -07007024 default:
7025 break;
7026 }
7027
7028 EXIT();
7029 return VOS_STATUS_SUCCESS;
7030}
7031
7032VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7033{
7034 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7035 VOS_STATUS status;
7036 hdd_adapter_t *pAdapter;
7037
7038 ENTER();
7039
7040 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7041
7042 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7043 {
7044 pAdapter = pAdapterNode->pAdapter;
7045 netif_tx_disable(pAdapter->dev);
7046 netif_carrier_off(pAdapter->dev);
7047
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307048 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007049
7050 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7051 pAdapterNode = pNext;
7052 }
7053
7054 EXIT();
7055
7056 return VOS_STATUS_SUCCESS;
7057}
7058
Rajeev Kumarf999e582014-01-09 17:33:29 -08007059
7060#ifdef FEATURE_WLAN_BATCH_SCAN
7061/**---------------------------------------------------------------------------
7062
7063 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7064 structures
7065
7066 \param - pAdapter Pointer to HDD adapter
7067
7068 \return - None
7069
7070 --------------------------------------------------------------------------*/
7071void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7072{
7073 tHddBatchScanRsp *pNode;
7074 tHddBatchScanRsp *pPrev;
7075
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307076 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007077 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307078 hddLog(VOS_TRACE_LEVEL_ERROR,
7079 "%s: Adapter context is Null", __func__);
7080 return;
7081 }
7082
7083 pNode = pAdapter->pBatchScanRsp;
7084 while (pNode)
7085 {
7086 pPrev = pNode;
7087 pNode = pNode->pNext;
7088 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007089 }
7090
7091 pAdapter->pBatchScanRsp = NULL;
7092 pAdapter->numScanList = 0;
7093 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7094 pAdapter->prev_batch_id = 0;
7095
7096 return;
7097}
7098#endif
7099
7100
Jeff Johnson295189b2012-06-20 16:38:30 -07007101VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7102{
7103 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7104 VOS_STATUS status;
7105 hdd_adapter_t *pAdapter;
7106
7107 ENTER();
7108
7109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7110
7111 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7112 {
7113 pAdapter = pAdapterNode->pAdapter;
7114 netif_tx_disable(pAdapter->dev);
7115 netif_carrier_off(pAdapter->dev);
7116
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007117 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7118
Jeff Johnson295189b2012-06-20 16:38:30 -07007119 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307120
7121 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7122
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307123 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7124 {
7125 hdd_wmm_adapter_close( pAdapter );
7126 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7127 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007128
Rajeev Kumarf999e582014-01-09 17:33:29 -08007129#ifdef FEATURE_WLAN_BATCH_SCAN
7130 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7131 {
7132 hdd_deinit_batch_scan(pAdapter);
7133 }
7134#endif
7135
Jeff Johnson295189b2012-06-20 16:38:30 -07007136 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7137 pAdapterNode = pNext;
7138 }
7139
7140 EXIT();
7141
7142 return VOS_STATUS_SUCCESS;
7143}
7144
7145VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7146{
7147 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7148 VOS_STATUS status;
7149 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307150 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007151
7152 ENTER();
7153
7154 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7155
7156 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7157 {
7158 pAdapter = pAdapterNode->pAdapter;
7159
Kumar Anand82c009f2014-05-29 00:29:42 -07007160 hdd_wmm_init( pAdapter );
7161
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 switch(pAdapter->device_mode)
7163 {
7164 case WLAN_HDD_INFRA_STATION:
7165 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007166 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307167
7168 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7169
Jeff Johnson295189b2012-06-20 16:38:30 -07007170 hdd_init_station_mode(pAdapter);
7171 /* Open the gates for HDD to receive Wext commands */
7172 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007173 pHddCtx->scan_info.mScanPending = FALSE;
7174 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007175
7176 //Trigger the initial scan
7177 hdd_wlan_initial_scan(pAdapter);
7178
7179 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307180 if (eConnectionState_Associated == connState ||
7181 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007182 {
7183 union iwreq_data wrqu;
7184 memset(&wrqu, '\0', sizeof(wrqu));
7185 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7186 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7187 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007188 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007189
Jeff Johnson295189b2012-06-20 16:38:30 -07007190 /* indicate disconnected event to nl80211 */
7191 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7192 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307194 else if (eConnectionState_Connecting == connState)
7195 {
7196 /*
7197 * Indicate connect failure to supplicant if we were in the
7198 * process of connecting
7199 */
7200 cfg80211_connect_result(pAdapter->dev, NULL,
7201 NULL, 0, NULL, 0,
7202 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7203 GFP_KERNEL);
7204 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007205 break;
7206
7207 case WLAN_HDD_SOFTAP:
7208 /* softAP can handle SSR */
7209 break;
7210
7211 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007212 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007214 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007215 break;
7216
7217 case WLAN_HDD_MONITOR:
7218 /* monitor interface start */
7219 break;
7220 default:
7221 break;
7222 }
7223
7224 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7225 pAdapterNode = pNext;
7226 }
7227
7228 EXIT();
7229
7230 return VOS_STATUS_SUCCESS;
7231}
7232
7233VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7234{
7235 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7236 hdd_adapter_t *pAdapter;
7237 VOS_STATUS status;
7238 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307239 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007240
7241 ENTER();
7242
7243 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7244
7245 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7246 {
7247 pAdapter = pAdapterNode->pAdapter;
7248
7249 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7250 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7251 {
7252 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7253 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7254
Abhishek Singhf4669da2014-05-26 15:07:49 +05307255 hddLog(VOS_TRACE_LEVEL_INFO,
7256 "%s: Set HDD connState to eConnectionState_NotConnected",
7257 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007258 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7259 init_completion(&pAdapter->disconnect_comp_var);
7260 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7261 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7262
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307263 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007264 &pAdapter->disconnect_comp_var,
7265 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307266 if (0 >= ret)
7267 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7268 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007269
7270 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7271 pHddCtx->isAmpAllowed = VOS_FALSE;
7272 sme_RoamConnect(pHddCtx->hHal,
7273 pAdapter->sessionId, &(pWextState->roamProfile),
7274 &roamId);
7275 }
7276
7277 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7278 pAdapterNode = pNext;
7279 }
7280
7281 EXIT();
7282
7283 return VOS_STATUS_SUCCESS;
7284}
7285
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007286void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7287{
7288 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7289 VOS_STATUS status;
7290 hdd_adapter_t *pAdapter;
7291 hdd_station_ctx_t *pHddStaCtx;
7292 hdd_ap_ctx_t *pHddApCtx;
7293 hdd_hostapd_state_t * pHostapdState;
7294 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7295 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7296 const char *p2pMode = "DEV";
7297 const char *ccMode = "Standalone";
7298 int n;
7299
7300 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7301 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7302 {
7303 pAdapter = pAdapterNode->pAdapter;
7304 switch (pAdapter->device_mode) {
7305 case WLAN_HDD_INFRA_STATION:
7306 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7307 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7308 staChannel = pHddStaCtx->conn_info.operationChannel;
7309 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7310 }
7311 break;
7312 case WLAN_HDD_P2P_CLIENT:
7313 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7314 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7315 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7316 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7317 p2pMode = "CLI";
7318 }
7319 break;
7320 case WLAN_HDD_P2P_GO:
7321 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7322 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7323 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7324 p2pChannel = pHddApCtx->operatingChannel;
7325 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7326 }
7327 p2pMode = "GO";
7328 break;
7329 case WLAN_HDD_SOFTAP:
7330 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7331 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7332 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7333 apChannel = pHddApCtx->operatingChannel;
7334 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7335 }
7336 break;
7337 default:
7338 break;
7339 }
7340 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7341 pAdapterNode = pNext;
7342 }
7343 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7344 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7345 }
7346 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7347 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7348 if (p2pChannel > 0) {
7349 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7350 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7351 }
7352 if (apChannel > 0) {
7353 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7354 apChannel, MAC_ADDR_ARRAY(apBssid));
7355 }
7356
7357 if (p2pChannel > 0 && apChannel > 0) {
7358 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7359 }
7360}
7361
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007362bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007363{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007364 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007365}
7366
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007367/* Once SSR is disabled then it cannot be set. */
7368void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007369{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007370 if (HDD_SSR_DISABLED == isSsrRequired)
7371 return;
7372
Jeff Johnson295189b2012-06-20 16:38:30 -07007373 isSsrRequired = value;
7374}
7375
7376VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7377 hdd_adapter_list_node_t** ppAdapterNode)
7378{
7379 VOS_STATUS status;
7380 spin_lock(&pHddCtx->hddAdapters.lock);
7381 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7382 (hdd_list_node_t**) ppAdapterNode );
7383 spin_unlock(&pHddCtx->hddAdapters.lock);
7384 return status;
7385}
7386
7387VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7388 hdd_adapter_list_node_t* pAdapterNode,
7389 hdd_adapter_list_node_t** pNextAdapterNode)
7390{
7391 VOS_STATUS status;
7392 spin_lock(&pHddCtx->hddAdapters.lock);
7393 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7394 (hdd_list_node_t*) pAdapterNode,
7395 (hdd_list_node_t**)pNextAdapterNode );
7396
7397 spin_unlock(&pHddCtx->hddAdapters.lock);
7398 return status;
7399}
7400
7401VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7402 hdd_adapter_list_node_t* pAdapterNode)
7403{
7404 VOS_STATUS status;
7405 spin_lock(&pHddCtx->hddAdapters.lock);
7406 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7407 &pAdapterNode->node );
7408 spin_unlock(&pHddCtx->hddAdapters.lock);
7409 return status;
7410}
7411
7412VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7413 hdd_adapter_list_node_t** ppAdapterNode)
7414{
7415 VOS_STATUS status;
7416 spin_lock(&pHddCtx->hddAdapters.lock);
7417 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7418 (hdd_list_node_t**) ppAdapterNode );
7419 spin_unlock(&pHddCtx->hddAdapters.lock);
7420 return status;
7421}
7422
7423VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7424 hdd_adapter_list_node_t* pAdapterNode)
7425{
7426 VOS_STATUS status;
7427 spin_lock(&pHddCtx->hddAdapters.lock);
7428 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7429 (hdd_list_node_t*) pAdapterNode );
7430 spin_unlock(&pHddCtx->hddAdapters.lock);
7431 return status;
7432}
7433
7434VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7435 hdd_adapter_list_node_t* pAdapterNode)
7436{
7437 VOS_STATUS status;
7438 spin_lock(&pHddCtx->hddAdapters.lock);
7439 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7440 (hdd_list_node_t*) pAdapterNode );
7441 spin_unlock(&pHddCtx->hddAdapters.lock);
7442 return status;
7443}
7444
7445hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7446 tSirMacAddr macAddr )
7447{
7448 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7449 hdd_adapter_t *pAdapter;
7450 VOS_STATUS status;
7451
7452 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7453
7454 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7455 {
7456 pAdapter = pAdapterNode->pAdapter;
7457
7458 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7459 macAddr, sizeof(tSirMacAddr) ) )
7460 {
7461 return pAdapter;
7462 }
7463 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7464 pAdapterNode = pNext;
7465 }
7466
7467 return NULL;
7468
7469}
7470
7471hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7472{
7473 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7474 hdd_adapter_t *pAdapter;
7475 VOS_STATUS status;
7476
7477 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7478
7479 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7480 {
7481 pAdapter = pAdapterNode->pAdapter;
7482
7483 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7484 IFNAMSIZ ) )
7485 {
7486 return pAdapter;
7487 }
7488 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7489 pAdapterNode = pNext;
7490 }
7491
7492 return NULL;
7493
7494}
7495
7496hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7497{
7498 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7499 hdd_adapter_t *pAdapter;
7500 VOS_STATUS status;
7501
7502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7503
7504 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7505 {
7506 pAdapter = pAdapterNode->pAdapter;
7507
7508 if( pAdapter && (mode == pAdapter->device_mode) )
7509 {
7510 return pAdapter;
7511 }
7512 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7513 pAdapterNode = pNext;
7514 }
7515
7516 return NULL;
7517
7518}
7519
7520//Remove this function later
7521hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7522{
7523 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7524 hdd_adapter_t *pAdapter;
7525 VOS_STATUS status;
7526
7527 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7528
7529 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7530 {
7531 pAdapter = pAdapterNode->pAdapter;
7532
7533 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7534 {
7535 return pAdapter;
7536 }
7537
7538 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7539 pAdapterNode = pNext;
7540 }
7541
7542 return NULL;
7543
7544}
7545
Jeff Johnson295189b2012-06-20 16:38:30 -07007546/**---------------------------------------------------------------------------
7547
7548 \brief hdd_set_monitor_tx_adapter() -
7549
7550 This API initializes the adapter to be used while transmitting on monitor
7551 adapter.
7552
7553 \param - pHddCtx - Pointer to the HDD context.
7554 pAdapter - Adapter that will used for TX. This can be NULL.
7555 \return - None.
7556 --------------------------------------------------------------------------*/
7557void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7558{
7559 hdd_adapter_t *pMonAdapter;
7560
7561 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7562
7563 if( NULL != pMonAdapter )
7564 {
7565 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7566 }
7567}
Jeff Johnson295189b2012-06-20 16:38:30 -07007568/**---------------------------------------------------------------------------
7569
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307570 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007571
7572 This API returns the operating channel of the requested device mode
7573
7574 \param - pHddCtx - Pointer to the HDD context.
7575 - mode - Device mode for which operating channel is required
7576 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7577 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7578 \return - channel number. "0" id the requested device is not found OR it is not connected.
7579 --------------------------------------------------------------------------*/
7580v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7581{
7582 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7583 VOS_STATUS status;
7584 hdd_adapter_t *pAdapter;
7585 v_U8_t operatingChannel = 0;
7586
7587 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7588
7589 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7590 {
7591 pAdapter = pAdapterNode->pAdapter;
7592
7593 if( mode == pAdapter->device_mode )
7594 {
7595 switch(pAdapter->device_mode)
7596 {
7597 case WLAN_HDD_INFRA_STATION:
7598 case WLAN_HDD_P2P_CLIENT:
7599 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7600 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7601 break;
7602 case WLAN_HDD_SOFTAP:
7603 case WLAN_HDD_P2P_GO:
7604 /*softap connection info */
7605 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7606 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7607 break;
7608 default:
7609 break;
7610 }
7611
7612 break; //Found the device of interest. break the loop
7613 }
7614
7615 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7616 pAdapterNode = pNext;
7617 }
7618 return operatingChannel;
7619}
7620
7621#ifdef WLAN_FEATURE_PACKET_FILTERING
7622/**---------------------------------------------------------------------------
7623
7624 \brief hdd_set_multicast_list() -
7625
7626 This used to set the multicast address list.
7627
7628 \param - dev - Pointer to the WLAN device.
7629 - skb - Pointer to OS packet (sk_buff).
7630 \return - success/fail
7631
7632 --------------------------------------------------------------------------*/
7633static void hdd_set_multicast_list(struct net_device *dev)
7634{
7635 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007636 int mc_count;
7637 int i = 0;
7638 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307639
7640 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007641 {
7642 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307643 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007644 return;
7645 }
7646
7647 if (dev->flags & IFF_ALLMULTI)
7648 {
7649 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007650 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307651 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007652 }
7653 else
7654 {
7655 mc_count = netdev_mc_count(dev);
7656 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007657 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007658 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7659 {
7660 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007661 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307662 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007663 return;
7664 }
7665
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307666 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007667
7668 netdev_for_each_mc_addr(ha, dev) {
7669 if (i == mc_count)
7670 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307671 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7672 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007673 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007674 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307675 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 i++;
7677 }
7678 }
7679 return;
7680}
7681#endif
7682
7683/**---------------------------------------------------------------------------
7684
7685 \brief hdd_select_queue() -
7686
7687 This function is registered with the Linux OS for network
7688 core to decide which queue to use first.
7689
7690 \param - dev - Pointer to the WLAN device.
7691 - skb - Pointer to OS packet (sk_buff).
7692 \return - ac, Queue Index/access category corresponding to UP in IP header
7693
7694 --------------------------------------------------------------------------*/
7695v_U16_t hdd_select_queue(struct net_device *dev,
7696 struct sk_buff *skb)
7697{
7698 return hdd_wmm_select_queue(dev, skb);
7699}
7700
7701
7702/**---------------------------------------------------------------------------
7703
7704 \brief hdd_wlan_initial_scan() -
7705
7706 This function triggers the initial scan
7707
7708 \param - pAdapter - Pointer to the HDD adapter.
7709
7710 --------------------------------------------------------------------------*/
7711void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7712{
7713 tCsrScanRequest scanReq;
7714 tCsrChannelInfo channelInfo;
7715 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007716 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007717 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7718
7719 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7720 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7721 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7722
7723 if(sme_Is11dSupported(pHddCtx->hHal))
7724 {
7725 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7726 if ( HAL_STATUS_SUCCESS( halStatus ) )
7727 {
7728 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7729 if( !scanReq.ChannelInfo.ChannelList )
7730 {
7731 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7732 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007733 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007734 return;
7735 }
7736 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7737 channelInfo.numOfChannels);
7738 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7739 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007740 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007741 }
7742
7743 scanReq.scanType = eSIR_PASSIVE_SCAN;
7744 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7745 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7746 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7747 }
7748 else
7749 {
7750 scanReq.scanType = eSIR_ACTIVE_SCAN;
7751 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7752 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7753 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7754 }
7755
7756 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7757 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7758 {
7759 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7760 __func__, halStatus );
7761 }
7762
7763 if(sme_Is11dSupported(pHddCtx->hHal))
7764 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7765}
7766
Jeff Johnson295189b2012-06-20 16:38:30 -07007767/**---------------------------------------------------------------------------
7768
7769 \brief hdd_full_power_callback() - HDD full power callback function
7770
7771 This is the function invoked by SME to inform the result of a full power
7772 request issued by HDD
7773
7774 \param - callbackcontext - Pointer to cookie
7775 \param - status - result of request
7776
7777 \return - None
7778
7779 --------------------------------------------------------------------------*/
7780static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7781{
Jeff Johnson72a40512013-12-19 10:14:15 -08007782 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007783
7784 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307785 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007786
7787 if (NULL == callbackContext)
7788 {
7789 hddLog(VOS_TRACE_LEVEL_ERROR,
7790 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007791 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007792 return;
7793 }
7794
Jeff Johnson72a40512013-12-19 10:14:15 -08007795 /* there is a race condition that exists between this callback
7796 function and the caller since the caller could time out either
7797 before or while this code is executing. we use a spinlock to
7798 serialize these actions */
7799 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007800
7801 if (POWER_CONTEXT_MAGIC != pContext->magic)
7802 {
7803 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007804 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007805 hddLog(VOS_TRACE_LEVEL_WARN,
7806 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007807 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007808 return;
7809 }
7810
Jeff Johnson72a40512013-12-19 10:14:15 -08007811 /* context is valid so caller is still waiting */
7812
7813 /* paranoia: invalidate the magic */
7814 pContext->magic = 0;
7815
7816 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007817 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007818
7819 /* serialization is complete */
7820 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007821}
7822
7823/**---------------------------------------------------------------------------
7824
7825 \brief hdd_wlan_exit() - HDD WLAN exit function
7826
7827 This is the driver exit point (invoked during rmmod)
7828
7829 \param - pHddCtx - Pointer to the HDD Context
7830
7831 \return - None
7832
7833 --------------------------------------------------------------------------*/
7834void hdd_wlan_exit(hdd_context_t *pHddCtx)
7835{
7836 eHalStatus halStatus;
7837 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7838 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307839 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007840 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007841 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007842 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307843 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007844
7845 ENTER();
7846
Jeff Johnson88ba7742013-02-27 14:36:02 -08007847 if (VOS_FTM_MODE != hdd_get_conparam())
7848 {
7849 // Unloading, restart logic is no more required.
7850 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007851
c_hpothu5ab05e92014-06-13 17:34:05 +05307852 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7853 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007854 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307855 pAdapter = pAdapterNode->pAdapter;
7856 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007857 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307858 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7859 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7860 {
7861 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7862 hdd_UnregisterWext(pAdapter->dev);
7863 }
7864 // Cancel any outstanding scan requests. We are about to close all
7865 // of our adapters, but an adapter structure is what SME passes back
7866 // to our callback function. Hence if there are any outstanding scan
7867 // requests then there is a race condition between when the adapter
7868 // is closed and when the callback is invoked.We try to resolve that
7869 // race condition here by canceling any outstanding scans before we
7870 // close the adapters.
7871 // Note that the scans may be cancelled in an asynchronous manner,
7872 // so ideally there needs to be some kind of synchronization. Rather
7873 // than introduce a new synchronization here, we will utilize the
7874 // fact that we are about to Request Full Power, and since that is
7875 // synchronized, the expectation is that by the time Request Full
7876 // Power has completed all scans will be cancelled.
7877 if (pHddCtx->scan_info.mScanPending)
7878 {
7879 hddLog(VOS_TRACE_LEVEL_INFO,
7880 FL("abort scan mode: %d sessionId: %d"),
7881 pAdapter->device_mode,
7882 pAdapter->sessionId);
7883 hdd_abort_mac_scan(pHddCtx,
7884 pAdapter->sessionId,
7885 eCSR_SCAN_ABORT_DEFAULT);
7886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007887 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307888 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7889 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007890 }
7891 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307892 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007893 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307894 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007895 wlan_hdd_ftm_close(pHddCtx);
7896 goto free_hdd_ctx;
7897 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307898
Jeff Johnson295189b2012-06-20 16:38:30 -07007899 /* DeRegister with platform driver as client for Suspend/Resume */
7900 vosStatus = hddDeregisterPmOps(pHddCtx);
7901 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7902 {
7903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7904 VOS_ASSERT(0);
7905 }
7906
7907 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7908 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7909 {
7910 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7911 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007912
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007913 //Stop the traffic monitor timer
7914 if ( VOS_TIMER_STATE_RUNNING ==
7915 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7916 {
7917 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7918 }
7919
7920 // Destroy the traffic monitor timer
7921 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7922 &pHddCtx->tx_rx_trafficTmr)))
7923 {
7924 hddLog(VOS_TRACE_LEVEL_ERROR,
7925 "%s: Cannot deallocate Traffic monitor timer", __func__);
7926 }
7927
Jeff Johnson295189b2012-06-20 16:38:30 -07007928 //Disable IMPS/BMPS as we do not want the device to enter any power
7929 //save mode during shutdown
7930 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7931 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7932 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7933
7934 //Ensure that device is in full power as we will touch H/W during vos_Stop
7935 init_completion(&powerContext.completion);
7936 powerContext.magic = POWER_CONTEXT_MAGIC;
7937
7938 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7939 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7940
7941 if (eHAL_STATUS_SUCCESS != halStatus)
7942 {
7943 if (eHAL_STATUS_PMC_PENDING == halStatus)
7944 {
7945 /* request was sent -- wait for the response */
7946 lrc = wait_for_completion_interruptible_timeout(
7947 &powerContext.completion,
7948 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007949 if (lrc <= 0)
7950 {
7951 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007952 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007953 }
7954 }
7955 else
7956 {
7957 hddLog(VOS_TRACE_LEVEL_ERROR,
7958 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007959 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007960 /* continue -- need to clean up as much as possible */
7961 }
7962 }
7963
Jeff Johnson72a40512013-12-19 10:14:15 -08007964 /* either we never sent a request, we sent a request and received a
7965 response or we sent a request and timed out. if we never sent a
7966 request or if we sent a request and got a response, we want to
7967 clear the magic out of paranoia. if we timed out there is a
7968 race condition such that the callback function could be
7969 executing at the same time we are. of primary concern is if the
7970 callback function had already verified the "magic" but had not
7971 yet set the completion variable when a timeout occurred. we
7972 serialize these activities by invalidating the magic while
7973 holding a shared spinlock which will cause us to block if the
7974 callback is currently executing */
7975 spin_lock(&hdd_context_lock);
7976 powerContext.magic = 0;
7977 spin_unlock(&hdd_context_lock);
7978
Yue Ma0d4891e2013-08-06 17:01:45 -07007979 hdd_debugfs_exit(pHddCtx);
7980
Jeff Johnson295189b2012-06-20 16:38:30 -07007981 // Unregister the Net Device Notifier
7982 unregister_netdevice_notifier(&hdd_netdev_notifier);
7983
Jeff Johnson295189b2012-06-20 16:38:30 -07007984 hdd_stop_all_adapters( pHddCtx );
7985
Jeff Johnson295189b2012-06-20 16:38:30 -07007986#ifdef WLAN_BTAMP_FEATURE
7987 vosStatus = WLANBAP_Stop(pVosContext);
7988 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7989 {
7990 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7991 "%s: Failed to stop BAP",__func__);
7992 }
7993#endif //WLAN_BTAMP_FEATURE
7994
7995 //Stop all the modules
7996 vosStatus = vos_stop( pVosContext );
7997 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7998 {
7999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8000 "%s: Failed to stop VOSS",__func__);
8001 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8002 }
8003
Jeff Johnson295189b2012-06-20 16:38:30 -07008004 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008006
8007 //Close the scheduler before calling vos_close to make sure no thread is
8008 // scheduled after the each module close is called i.e after all the data
8009 // structures are freed.
8010 vosStatus = vos_sched_close( pVosContext );
8011 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8012 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8013 "%s: Failed to close VOSS Scheduler",__func__);
8014 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8015 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008016#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008017#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8018 /* Destroy the wake lock */
8019 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8020#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008021 /* Destroy the wake lock */
8022 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008023#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008024
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308025#ifdef CONFIG_ENABLE_LINUX_REG
8026 vosStatus = vos_nv_close();
8027 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8028 {
8029 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8030 "%s: Failed to close NV", __func__);
8031 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8032 }
8033#endif
8034
Jeff Johnson295189b2012-06-20 16:38:30 -07008035 //Close VOSS
8036 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8037 vos_close(pVosContext);
8038
Jeff Johnson295189b2012-06-20 16:38:30 -07008039 //Close Watchdog
8040 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8041 vos_watchdog_close(pVosContext);
8042
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308043 //Clean up HDD Nlink Service
8044 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308045
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308046#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308047 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308048 {
8049 wlan_logging_sock_deactivate_svc();
8050 }
8051#endif
8052
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308053#ifdef WLAN_KD_READY_NOTIFIER
8054 nl_srv_exit(pHddCtx->ptt_pid);
8055#else
8056 nl_srv_exit();
8057#endif /* WLAN_KD_READY_NOTIFIER */
8058
8059
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 hdd_close_all_adapters( pHddCtx );
8061
Jeff Johnson295189b2012-06-20 16:38:30 -07008062 /* free the power on lock from platform driver */
8063 if (free_riva_power_on_lock("wlan"))
8064 {
8065 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8066 __func__);
8067 }
8068
Jeff Johnson88ba7742013-02-27 14:36:02 -08008069free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308070
8071 //Free up dynamically allocated members inside HDD Adapter
8072 if (pHddCtx->cfg_ini)
8073 {
8074 kfree(pHddCtx->cfg_ini);
8075 pHddCtx->cfg_ini= NULL;
8076 }
8077
Leo Changf04ddad2013-09-18 13:46:38 -07008078 /* FTM mode, WIPHY did not registered
8079 If un-register here, system crash will happen */
8080 if (VOS_FTM_MODE != hdd_get_conparam())
8081 {
8082 wiphy_unregister(wiphy) ;
8083 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008084 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008085 if (hdd_is_ssr_required())
8086 {
8087 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008088 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008089 msleep(5000);
8090 }
8091 hdd_set_ssr_required (VOS_FALSE);
8092}
8093
8094
8095/**---------------------------------------------------------------------------
8096
8097 \brief hdd_update_config_from_nv() - Function to update the contents of
8098 the running configuration with parameters taken from NV storage
8099
8100 \param - pHddCtx - Pointer to the HDD global context
8101
8102 \return - VOS_STATUS_SUCCESS if successful
8103
8104 --------------------------------------------------------------------------*/
8105static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8106{
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 v_BOOL_t itemIsValid = VOS_FALSE;
8108 VOS_STATUS status;
8109 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8110 v_U8_t macLoop;
8111
8112 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8113 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8114 if(status != VOS_STATUS_SUCCESS)
8115 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008116 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 return VOS_STATUS_E_FAILURE;
8118 }
8119
8120 if (itemIsValid == VOS_TRUE)
8121 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008122 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8124 VOS_MAX_CONCURRENCY_PERSONA);
8125 if(status != VOS_STATUS_SUCCESS)
8126 {
8127 /* Get MAC from NV fail, not update CFG info
8128 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008129 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008130 return VOS_STATUS_E_FAILURE;
8131 }
8132
8133 /* If first MAC is not valid, treat all others are not valid
8134 * Then all MACs will be got from ini file */
8135 if(vos_is_macaddr_zero(&macFromNV[0]))
8136 {
8137 /* MAC address in NV file is not configured yet */
8138 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8139 return VOS_STATUS_E_INVAL;
8140 }
8141
8142 /* Get MAC address from NV, update CFG info */
8143 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8144 {
8145 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8146 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308147 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 /* This MAC is not valid, skip it
8149 * This MAC will be got from ini file */
8150 }
8151 else
8152 {
8153 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8154 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8155 VOS_MAC_ADDR_SIZE);
8156 }
8157 }
8158 }
8159 else
8160 {
8161 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8162 return VOS_STATUS_E_FAILURE;
8163 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008164
Jeff Johnson295189b2012-06-20 16:38:30 -07008165
8166 return VOS_STATUS_SUCCESS;
8167}
8168
8169/**---------------------------------------------------------------------------
8170
8171 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8172
8173 \param - pAdapter - Pointer to the HDD
8174
8175 \return - None
8176
8177 --------------------------------------------------------------------------*/
8178VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8179{
8180 eHalStatus halStatus;
8181 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308182 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008183
Jeff Johnson295189b2012-06-20 16:38:30 -07008184
8185 // Send ready indication to the HDD. This will kick off the MAC
8186 // into a 'running' state and should kick off an initial scan.
8187 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8188 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8189 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308190 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008191 "code %08d [x%08x]",__func__, halStatus, halStatus );
8192 return VOS_STATUS_E_FAILURE;
8193 }
8194
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308195 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008196 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8197 // And RIVA will crash
8198 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8199 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308200 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8201 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8202
8203
Jeff Johnson295189b2012-06-20 16:38:30 -07008204 return VOS_STATUS_SUCCESS;
8205}
8206
Jeff Johnson295189b2012-06-20 16:38:30 -07008207/* wake lock APIs for HDD */
8208void hdd_prevent_suspend(void)
8209{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008210#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008211 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008212#else
8213 wcnss_prevent_suspend();
8214#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008215}
8216
8217void hdd_allow_suspend(void)
8218{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008219#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008220 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008221#else
8222 wcnss_allow_suspend();
8223#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008224}
8225
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308226void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008227{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008228#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008229 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008230#else
8231 /* Do nothing as there is no API in wcnss for timeout*/
8232#endif
8233}
8234
Jeff Johnson295189b2012-06-20 16:38:30 -07008235/**---------------------------------------------------------------------------
8236
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008237 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8238 information between Host and Riva
8239
8240 This function gets reported version of FW
8241 It also finds the version of Riva headers used to compile the host
8242 It compares the above two and prints a warning if they are different
8243 It gets the SW and HW version string
8244 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8245 indicating the features they support through a bitmap
8246
8247 \param - pHddCtx - Pointer to HDD context
8248
8249 \return - void
8250
8251 --------------------------------------------------------------------------*/
8252
8253void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8254{
8255
8256 tSirVersionType versionCompiled;
8257 tSirVersionType versionReported;
8258 tSirVersionString versionString;
8259 tANI_U8 fwFeatCapsMsgSupported = 0;
8260 VOS_STATUS vstatus;
8261
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008262 memset(&versionCompiled, 0, sizeof(versionCompiled));
8263 memset(&versionReported, 0, sizeof(versionReported));
8264
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008265 /* retrieve and display WCNSS version information */
8266 do {
8267
8268 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8269 &versionCompiled);
8270 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8271 {
8272 hddLog(VOS_TRACE_LEVEL_FATAL,
8273 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008274 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008275 break;
8276 }
8277
8278 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8279 &versionReported);
8280 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8281 {
8282 hddLog(VOS_TRACE_LEVEL_FATAL,
8283 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008284 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008285 break;
8286 }
8287
8288 if ((versionCompiled.major != versionReported.major) ||
8289 (versionCompiled.minor != versionReported.minor) ||
8290 (versionCompiled.version != versionReported.version) ||
8291 (versionCompiled.revision != versionReported.revision))
8292 {
8293 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8294 "Host expected %u.%u.%u.%u\n",
8295 WLAN_MODULE_NAME,
8296 (int)versionReported.major,
8297 (int)versionReported.minor,
8298 (int)versionReported.version,
8299 (int)versionReported.revision,
8300 (int)versionCompiled.major,
8301 (int)versionCompiled.minor,
8302 (int)versionCompiled.version,
8303 (int)versionCompiled.revision);
8304 }
8305 else
8306 {
8307 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8308 WLAN_MODULE_NAME,
8309 (int)versionReported.major,
8310 (int)versionReported.minor,
8311 (int)versionReported.version,
8312 (int)versionReported.revision);
8313 }
8314
8315 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8316 versionString,
8317 sizeof(versionString));
8318 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8319 {
8320 hddLog(VOS_TRACE_LEVEL_FATAL,
8321 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008322 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008323 break;
8324 }
8325
8326 pr_info("%s: WCNSS software version %s\n",
8327 WLAN_MODULE_NAME, versionString);
8328
8329 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8330 versionString,
8331 sizeof(versionString));
8332 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8333 {
8334 hddLog(VOS_TRACE_LEVEL_FATAL,
8335 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008336 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008337 break;
8338 }
8339
8340 pr_info("%s: WCNSS hardware version %s\n",
8341 WLAN_MODULE_NAME, versionString);
8342
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008343 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8344 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008345 send the message only if it the riva is 1.1
8346 minor numbers for different riva branches:
8347 0 -> (1.0)Mainline Build
8348 1 -> (1.1)Mainline Build
8349 2->(1.04) Stability Build
8350 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008351 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008352 ((versionReported.minor>=1) && (versionReported.version>=1)))
8353 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8354 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008355
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008356 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008357 {
8358#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8359 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8360 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8361#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008362 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8363 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8364 {
8365 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8366 }
8367
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008368 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008369 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008370
8371 } while (0);
8372
8373}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308374void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8375{
8376 struct sk_buff *skb;
8377 struct nlmsghdr *nlh;
8378 tAniMsgHdr *ani_hdr;
8379
8380 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8381
8382 if(skb == NULL) {
8383 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8384 "%s: alloc_skb failed", __func__);
8385 return;
8386 }
8387
8388 nlh = (struct nlmsghdr *)skb->data;
8389 nlh->nlmsg_pid = 0; /* from kernel */
8390 nlh->nlmsg_flags = 0;
8391 nlh->nlmsg_seq = 0;
8392 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8393
8394 ani_hdr = NLMSG_DATA(nlh);
8395 ani_hdr->type = type;
8396
8397 switch(type) {
8398 case WLAN_SVC_SAP_RESTART_IND:
8399 ani_hdr->length = 0;
8400 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8401 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8402 break;
8403 default:
8404 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8405 "Attempt to send unknown nlink message %d", type);
8406 kfree_skb(skb);
8407 return;
8408 }
8409
8410 nl_srv_bcast(skb);
8411
8412 return;
8413}
8414
8415
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008416
8417/**---------------------------------------------------------------------------
8418
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308419 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8420
8421 \param - pHddCtx - Pointer to the hdd context
8422
8423 \return - true if hardware supports 5GHz
8424
8425 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308426boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308427{
8428 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8429 * then hardware support 5Ghz.
8430 */
8431 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8432 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308433 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308434 return true;
8435 }
8436 else
8437 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308438 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308439 __func__);
8440 return false;
8441 }
8442}
8443
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308444/**---------------------------------------------------------------------------
8445
8446 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8447 generate function
8448
8449 This is generate the random mac address for WLAN interface
8450
8451 \param - pHddCtx - Pointer to HDD context
8452 idx - Start interface index to get auto
8453 generated mac addr.
8454 mac_addr - Mac address
8455
8456 \return - 0 for success, < 0 for failure
8457
8458 --------------------------------------------------------------------------*/
8459
8460static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8461 int idx, v_MACADDR_t mac_addr)
8462{
8463 int i;
8464 unsigned int serialno;
8465 serialno = wcnss_get_serial_number();
8466
8467 if (0 != serialno)
8468 {
8469 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8470 bytes of the serial number that can be used to generate
8471 the other 3 bytes of the MAC address. Mask off all but
8472 the lower 3 bytes (this will also make sure we don't
8473 overflow in the next step) */
8474 serialno &= 0x00FFFFFF;
8475
8476 /* we need a unique address for each session */
8477 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8478
8479 /* autogen other Mac addresses */
8480 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8481 {
8482 /* start with the entire default address */
8483 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8484 /* then replace the lower 3 bytes */
8485 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8486 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8487 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8488
8489 serialno++;
8490 hddLog(VOS_TRACE_LEVEL_ERROR,
8491 "%s: Derived Mac Addr: "
8492 MAC_ADDRESS_STR, __func__,
8493 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8494 }
8495
8496 }
8497 else
8498 {
8499 hddLog(LOGE, FL("Failed to Get Serial NO"));
8500 return -1;
8501 }
8502 return 0;
8503}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308504
8505/**---------------------------------------------------------------------------
8506
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308507 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8508 completed to flush out the scan results
8509
8510 11d scan is done during driver load and is a passive scan on all
8511 channels supported by the device, 11d scans may find some APs on
8512 frequencies which are forbidden to be used in the regulatory domain
8513 the device is operating in. If these APs are notified to the supplicant
8514 it may try to connect to these APs, thus flush out all the scan results
8515 which are present in SME after 11d scan is done.
8516
8517 \return - eHalStatus
8518
8519 --------------------------------------------------------------------------*/
8520static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8521 tANI_U32 scanId, eCsrScanStatus status)
8522{
8523 ENTER();
8524
8525 sme_ScanFlushResult(halHandle, 0);
8526
8527 EXIT();
8528
8529 return eHAL_STATUS_SUCCESS;
8530}
8531
8532/**---------------------------------------------------------------------------
8533
Jeff Johnson295189b2012-06-20 16:38:30 -07008534 \brief hdd_wlan_startup() - HDD init function
8535
8536 This is the driver startup code executed once a WLAN device has been detected
8537
8538 \param - dev - Pointer to the underlying device
8539
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008540 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008541
8542 --------------------------------------------------------------------------*/
8543
8544int hdd_wlan_startup(struct device *dev )
8545{
8546 VOS_STATUS status;
8547 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008548 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008549 hdd_context_t *pHddCtx = NULL;
8550 v_CONTEXT_t pVosContext= NULL;
8551#ifdef WLAN_BTAMP_FEATURE
8552 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8553 WLANBAP_ConfigType btAmpConfig;
8554 hdd_config_t *pConfig;
8555#endif
8556 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008557 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308558 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008559
8560 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008561 /*
8562 * cfg80211: wiphy allocation
8563 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308564 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008565
8566 if(wiphy == NULL)
8567 {
8568 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008569 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008570 }
8571
8572 pHddCtx = wiphy_priv(wiphy);
8573
Jeff Johnson295189b2012-06-20 16:38:30 -07008574 //Initialize the adapter context to zeros.
8575 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8576
Jeff Johnson295189b2012-06-20 16:38:30 -07008577 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008578 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308579 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008580
8581 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8582
8583 /*Get vos context here bcoz vos_open requires it*/
8584 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8585
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008586 if(pVosContext == NULL)
8587 {
8588 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8589 goto err_free_hdd_context;
8590 }
8591
Jeff Johnson295189b2012-06-20 16:38:30 -07008592 //Save the Global VOSS context in adapter context for future.
8593 pHddCtx->pvosContext = pVosContext;
8594
8595 //Save the adapter context in global context for future.
8596 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8597
Jeff Johnson295189b2012-06-20 16:38:30 -07008598 pHddCtx->parent_dev = dev;
8599
8600 init_completion(&pHddCtx->full_pwr_comp_var);
8601 init_completion(&pHddCtx->standby_comp_var);
8602 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008603 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008604 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308605 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308606 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008607
8608#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008609 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008610#else
8611 init_completion(&pHddCtx->driver_crda_req);
8612#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008613
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308614 spin_lock_init(&pHddCtx->schedScan_lock);
8615
Jeff Johnson295189b2012-06-20 16:38:30 -07008616 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8617
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308618#ifdef FEATURE_WLAN_TDLS
8619 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8620 * invoked by other instances also) to protect the concurrent
8621 * access for the Adapters by TDLS module.
8622 */
8623 mutex_init(&pHddCtx->tdls_lock);
8624#endif
Agarwal Ashish1f422872014-07-22 00:11:55 +05308625 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308626
Agarwal Ashish1f422872014-07-22 00:11:55 +05308627 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008628 // Load all config first as TL config is needed during vos_open
8629 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8630 if(pHddCtx->cfg_ini == NULL)
8631 {
8632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8633 goto err_free_hdd_context;
8634 }
8635
8636 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8637
8638 // Read and parse the qcom_cfg.ini file
8639 status = hdd_parse_config_ini( pHddCtx );
8640 if ( VOS_STATUS_SUCCESS != status )
8641 {
8642 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8643 __func__, WLAN_INI_FILE);
8644 goto err_config;
8645 }
Arif Hussaind5218912013-12-05 01:10:55 -08008646#ifdef MEMORY_DEBUG
8647 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8648 vos_mem_init();
8649
8650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8651 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8652#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008653
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308654 /* INI has been read, initialise the configuredMcastBcastFilter with
8655 * INI value as this will serve as the default value
8656 */
8657 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8658 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8659 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308660
8661 if (false == hdd_is_5g_supported(pHddCtx))
8662 {
8663 //5Ghz is not supported.
8664 if (1 != pHddCtx->cfg_ini->nBandCapability)
8665 {
8666 hddLog(VOS_TRACE_LEVEL_INFO,
8667 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8668 pHddCtx->cfg_ini->nBandCapability = 1;
8669 }
8670 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308671
8672 /* If SNR Monitoring is enabled, FW has to parse all beacons
8673 * for calcaluting and storing the average SNR, so set Nth beacon
8674 * filter to 1 to enable FW to parse all the beaocons
8675 */
8676 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8677 {
8678 /* The log level is deliberately set to WARN as overriding
8679 * nthBeaconFilter to 1 will increase power cosumption and this
8680 * might just prove helpful to detect the power issue.
8681 */
8682 hddLog(VOS_TRACE_LEVEL_WARN,
8683 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8684 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008686 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308687 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008688 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008689 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008690 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008691 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8692 {
8693 hddLog(VOS_TRACE_LEVEL_FATAL,
8694 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8695 goto err_config;
8696 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008697 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008698
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008699 // Update VOS trace levels based upon the cfg.ini
8700 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8701 pHddCtx->cfg_ini->vosTraceEnableBAP);
8702 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8703 pHddCtx->cfg_ini->vosTraceEnableTL);
8704 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8705 pHddCtx->cfg_ini->vosTraceEnableWDI);
8706 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8707 pHddCtx->cfg_ini->vosTraceEnableHDD);
8708 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8709 pHddCtx->cfg_ini->vosTraceEnableSME);
8710 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8711 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308712 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8713 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008714 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8715 pHddCtx->cfg_ini->vosTraceEnableWDA);
8716 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8717 pHddCtx->cfg_ini->vosTraceEnableSYS);
8718 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8719 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008720 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8721 pHddCtx->cfg_ini->vosTraceEnableSAP);
8722 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8723 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008724
Jeff Johnson295189b2012-06-20 16:38:30 -07008725 // Update WDI trace levels based upon the cfg.ini
8726 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8727 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8728 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8729 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8730 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8731 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8732 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8733 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008734
Jeff Johnson88ba7742013-02-27 14:36:02 -08008735 if (VOS_FTM_MODE == hdd_get_conparam())
8736 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008737 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8738 {
8739 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8740 goto err_free_hdd_context;
8741 }
8742 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308743
8744 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008745 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008746 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008747
Jeff Johnson88ba7742013-02-27 14:36:02 -08008748 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008749 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8750 {
8751 status = vos_watchdog_open(pVosContext,
8752 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8753
8754 if(!VOS_IS_STATUS_SUCCESS( status ))
8755 {
8756 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308757 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008758 }
8759 }
8760
8761 pHddCtx->isLogpInProgress = FALSE;
8762 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8763
Amar Singhala49cbc52013-10-08 18:37:44 -07008764#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008765 /* initialize the NV module. This is required so that
8766 we can initialize the channel information in wiphy
8767 from the NV.bin data. The channel information in
8768 wiphy needs to be initialized before wiphy registration */
8769
8770 status = vos_nv_open();
8771 if (!VOS_IS_STATUS_SUCCESS(status))
8772 {
8773 /* NV module cannot be initialized */
8774 hddLog( VOS_TRACE_LEVEL_FATAL,
8775 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05308776 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07008777 }
8778
8779 status = vos_init_wiphy_from_nv_bin();
8780 if (!VOS_IS_STATUS_SUCCESS(status))
8781 {
8782 /* NV module cannot be initialized */
8783 hddLog( VOS_TRACE_LEVEL_FATAL,
8784 "%s: vos_init_wiphy failed", __func__);
8785 goto err_vos_nv_close;
8786 }
8787
Amar Singhala49cbc52013-10-08 18:37:44 -07008788#endif
8789
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308790 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 if ( !VOS_IS_STATUS_SUCCESS( status ))
8792 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008793 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308794 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008795 }
8796
Jeff Johnson295189b2012-06-20 16:38:30 -07008797 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8798
8799 if ( NULL == pHddCtx->hHal )
8800 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008801 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008802 goto err_vosclose;
8803 }
8804
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008805 status = vos_preStart( pHddCtx->pvosContext );
8806 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8807 {
8808 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308809 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008810 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008811
Arif Hussaineaf68602013-12-30 23:10:44 -08008812 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8813 {
8814 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8815 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8816 __func__, enable_dfs_chan_scan);
8817 }
8818 if (0 == enable_11d || 1 == enable_11d)
8819 {
8820 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8821 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8822 __func__, enable_11d);
8823 }
8824
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008825 /* Note that the vos_preStart() sequence triggers the cfg download.
8826 The cfg download must occur before we update the SME config
8827 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008828 status = hdd_set_sme_config( pHddCtx );
8829
8830 if ( VOS_STATUS_SUCCESS != status )
8831 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008832 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308833 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008835
Jeff Johnson295189b2012-06-20 16:38:30 -07008836 /* In the integrated architecture we update the configuration from
8837 the INI file and from NV before vOSS has been started so that
8838 the final contents are available to send down to the cCPU */
8839
8840 // Apply the cfg.ini to cfg.dat
8841 if (FALSE == hdd_update_config_dat(pHddCtx))
8842 {
8843 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308844 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008845 }
8846
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308847 // Get mac addr from platform driver
8848 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8849
8850 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008851 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308852 /* Store the mac addr for first interface */
8853 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8854
8855 hddLog(VOS_TRACE_LEVEL_ERROR,
8856 "%s: WLAN Mac Addr: "
8857 MAC_ADDRESS_STR, __func__,
8858 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8859
8860 /* Here, passing Arg2 as 1 because we do not want to change the
8861 last 3 bytes (means non OUI bytes) of first interface mac
8862 addr.
8863 */
8864 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8865 {
8866 hddLog(VOS_TRACE_LEVEL_ERROR,
8867 "%s: Failed to generate wlan interface mac addr "
8868 "using MAC from ini file ", __func__);
8869 }
8870 }
8871 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8872 {
8873 // Apply the NV to cfg.dat
8874 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008875#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8876 /* There was not a valid set of MAC Addresses in NV. See if the
8877 default addresses were modified by the cfg.ini settings. If so,
8878 we'll use them, but if not, we'll autogenerate a set of MAC
8879 addresses based upon the device serial number */
8880
8881 static const v_MACADDR_t default_address =
8882 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008883
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308884 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8885 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008886 {
8887 /* cfg.ini has the default address, invoke autogen logic */
8888
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308889 /* Here, passing Arg2 as 0 because we want to change the
8890 last 3 bytes (means non OUI bytes) of all the interfaces
8891 mac addr.
8892 */
8893 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8894 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008895 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308896 hddLog(VOS_TRACE_LEVEL_ERROR,
8897 "%s: Failed to generate wlan interface mac addr "
8898 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8899 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008900 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008901 }
8902 else
8903#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8904 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008905 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008906 "%s: Invalid MAC address in NV, using MAC from ini file "
8907 MAC_ADDRESS_STR, __func__,
8908 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8909 }
8910 }
8911 {
8912 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308913
8914 /* Set the MAC Address Currently this is used by HAL to
8915 * add self sta. Remove this once self sta is added as
8916 * part of session open.
8917 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008918 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8919 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8920 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308921
Jeff Johnson295189b2012-06-20 16:38:30 -07008922 if (!HAL_STATUS_SUCCESS( halStatus ))
8923 {
8924 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8925 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308926 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008927 }
8928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008929
8930 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8931 Note: Firmware image will be read and downloaded inside vos_start API */
8932 status = vos_start( pHddCtx->pvosContext );
8933 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8934 {
8935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308936 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008937 }
8938
Leo Chang6cec3e22014-01-21 15:33:49 -08008939#ifdef FEATURE_WLAN_CH_AVOID
8940 /* Plug in avoid channel notification callback
8941 * This should happen before ADD_SELF_STA
8942 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308943
8944 /* check the Channel Avoidance is enabled */
8945 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8946 {
8947 sme_AddChAvoidCallback(pHddCtx->hHal,
8948 hdd_hostapd_ch_avoid_cb);
8949 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008950#endif /* FEATURE_WLAN_CH_AVOID */
8951
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008952 /* Exchange capability info between Host and FW and also get versioning info from FW */
8953 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008954
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308955#ifdef CONFIG_ENABLE_LINUX_REG
8956 status = wlan_hdd_init_channels(pHddCtx);
8957 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8958 {
8959 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8960 __func__);
8961 goto err_vosstop;
8962 }
8963#endif
8964
Jeff Johnson295189b2012-06-20 16:38:30 -07008965 status = hdd_post_voss_start_config( pHddCtx );
8966 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8967 {
8968 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8969 __func__);
8970 goto err_vosstop;
8971 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008972
8973#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308974 wlan_hdd_cfg80211_update_reg_info( wiphy );
8975
8976 /* registration of wiphy dev with cfg80211 */
8977 if (0 > wlan_hdd_cfg80211_register(wiphy))
8978 {
8979 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8980 goto err_vosstop;
8981 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008982#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008983
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308984#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308985 /* registration of wiphy dev with cfg80211 */
8986 if (0 > wlan_hdd_cfg80211_register(wiphy))
8987 {
8988 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8989 goto err_vosstop;
8990 }
8991
Agarwal Ashish6db9d532014-09-30 18:19:10 +05308992 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308993 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8994 {
8995 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8996 __func__);
8997 goto err_unregister_wiphy;
8998 }
8999#endif
9000
Jeff Johnson295189b2012-06-20 16:38:30 -07009001 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9002 {
9003 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9004 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9005 }
9006 else
9007 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009008 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9009 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9010 if (pAdapter != NULL)
9011 {
kaidde69982014-06-18 13:23:21 +08009012 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009013 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309014 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9015 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9016 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009017
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309018 /* Generate the P2P Device Address. This consists of the device's
9019 * primary MAC address with the locally administered bit set.
9020 */
9021 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009022 }
9023 else
9024 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309025 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9026 if (p2p_dev_addr != NULL)
9027 {
9028 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9029 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9030 }
9031 else
9032 {
9033 hddLog(VOS_TRACE_LEVEL_FATAL,
9034 "%s: Failed to allocate mac_address for p2p_device",
9035 __func__);
9036 goto err_close_adapter;
9037 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009039
9040 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9041 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9042 if ( NULL == pP2pAdapter )
9043 {
9044 hddLog(VOS_TRACE_LEVEL_FATAL,
9045 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009046 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009047 goto err_close_adapter;
9048 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009049 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009050 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009051
9052 if( pAdapter == NULL )
9053 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009054 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9055 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009056 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009057
Arif Hussain66559122013-11-21 10:11:40 -08009058 if (country_code)
9059 {
9060 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009061 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009062 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9063#ifndef CONFIG_ENABLE_LINUX_REG
9064 hdd_checkandupdate_phymode(pAdapter, country_code);
9065#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009066 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9067 (void *)(tSmeChangeCountryCallback)
9068 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009069 country_code,
9070 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309071 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009072 if (eHAL_STATUS_SUCCESS == ret)
9073 {
Arif Hussaincb607082013-12-20 11:57:42 -08009074 ret = wait_for_completion_interruptible_timeout(
9075 &pAdapter->change_country_code,
9076 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9077
9078 if (0 >= ret)
9079 {
9080 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9081 "%s: SME while setting country code timed out", __func__);
9082 }
Arif Hussain66559122013-11-21 10:11:40 -08009083 }
9084 else
9085 {
Arif Hussaincb607082013-12-20 11:57:42 -08009086 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9087 "%s: SME Change Country code from module param fail ret=%d",
9088 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009089 }
9090 }
9091
Jeff Johnson295189b2012-06-20 16:38:30 -07009092#ifdef WLAN_BTAMP_FEATURE
9093 vStatus = WLANBAP_Open(pVosContext);
9094 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9095 {
9096 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9097 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009098 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009099 }
9100
9101 vStatus = BSL_Init(pVosContext);
9102 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9103 {
9104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9105 "%s: Failed to Init BSL",__func__);
9106 goto err_bap_close;
9107 }
9108 vStatus = WLANBAP_Start(pVosContext);
9109 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9110 {
9111 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9112 "%s: Failed to start TL",__func__);
9113 goto err_bap_close;
9114 }
9115
9116 pConfig = pHddCtx->cfg_ini;
9117 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9118 status = WLANBAP_SetConfig(&btAmpConfig);
9119
9120#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009121
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009122#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9123 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9124 {
9125 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9126 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9127 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9128 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9129 }
9130#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009131
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309132 wlan_hdd_tdls_init(pHddCtx);
9133
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309134 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9135
Jeff Johnson295189b2012-06-20 16:38:30 -07009136 /* Register with platform driver as client for Suspend/Resume */
9137 status = hddRegisterPmOps(pHddCtx);
9138 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9139 {
9140 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9141#ifdef WLAN_BTAMP_FEATURE
9142 goto err_bap_stop;
9143#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009144 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009145#endif //WLAN_BTAMP_FEATURE
9146 }
9147
Yue Ma0d4891e2013-08-06 17:01:45 -07009148 /* Open debugfs interface */
9149 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9150 {
9151 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9152 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009153 }
9154
Jeff Johnson295189b2012-06-20 16:38:30 -07009155 /* Register TM level change handler function to the platform */
9156 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9157 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9158 {
9159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9160 goto err_unregister_pmops;
9161 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009162
9163 /* register for riva power on lock to platform driver */
9164 if (req_riva_power_on_lock("wlan"))
9165 {
9166 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9167 __func__);
9168 goto err_unregister_pmops;
9169 }
9170
Jeff Johnson295189b2012-06-20 16:38:30 -07009171 // register net device notifier for device change notification
9172 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9173
9174 if(ret < 0)
9175 {
9176 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9177 goto err_free_power_on_lock;
9178 }
9179
9180 //Initialize the nlink service
9181 if(nl_srv_init() != 0)
9182 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309183 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009184 goto err_reg_netdev;
9185 }
9186
Leo Chang4ce1cc52013-10-21 18:27:15 -07009187#ifdef WLAN_KD_READY_NOTIFIER
9188 pHddCtx->kd_nl_init = 1;
9189#endif /* WLAN_KD_READY_NOTIFIER */
9190
Jeff Johnson295189b2012-06-20 16:38:30 -07009191 //Initialize the BTC service
9192 if(btc_activate_service(pHddCtx) != 0)
9193 {
9194 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9195 goto err_nl_srv;
9196 }
9197
9198#ifdef PTT_SOCK_SVC_ENABLE
9199 //Initialize the PTT service
9200 if(ptt_sock_activate_svc(pHddCtx) != 0)
9201 {
9202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9203 goto err_nl_srv;
9204 }
9205#endif
9206
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309207#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9208 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9209 {
9210 if(wlan_logging_sock_activate_svc(
9211 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9212 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9213 {
9214 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9215 " failed", __func__);
9216 goto err_nl_srv;
9217 }
9218 }
9219#endif
9220
Jeff Johnson295189b2012-06-20 16:38:30 -07009221 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009222 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009223 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009224 /* Action frame registered in one adapter which will
9225 * applicable to all interfaces
9226 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309227 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009228 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009229
9230 mutex_init(&pHddCtx->sap_lock);
9231
Jeff Johnson295189b2012-06-20 16:38:30 -07009232
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009233#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009234#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9235 /* Initialize the wake lcok */
9236 wake_lock_init(&pHddCtx->rx_wake_lock,
9237 WAKE_LOCK_SUSPEND,
9238 "qcom_rx_wakelock");
9239#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009240 /* Initialize the wake lcok */
9241 wake_lock_init(&pHddCtx->sap_wake_lock,
9242 WAKE_LOCK_SUSPEND,
9243 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009244#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009245
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009246 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9247 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009248
Katya Nigam5c306ea2014-06-19 15:39:54 +05309249 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009250 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9251 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309252
9253#ifdef FEATURE_WLAN_SCAN_PNO
9254 /*SME must send channel update configuration to RIVA*/
9255 sme_UpdateChannelConfig(pHddCtx->hHal);
9256#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309257 /* Send the update default channel list to the FW*/
9258 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309259#ifndef CONFIG_ENABLE_LINUX_REG
9260 /*updating wiphy so that regulatory user hints can be processed*/
9261 if (wiphy)
9262 {
9263 regulatory_hint(wiphy, "00");
9264 }
9265#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009266 // Initialize the restart logic
9267 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309268
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009269 //Register the traffic monitor timer now
9270 if ( pHddCtx->cfg_ini->dynSplitscan)
9271 {
9272 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9273 VOS_TIMER_TYPE_SW,
9274 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9275 (void *)pHddCtx);
9276 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309277#ifdef WLAN_FEATURE_EXTSCAN
9278 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9279 wlan_hdd_cfg80211_extscan_callback,
9280 pHddCtx);
9281#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009282 goto success;
9283
9284err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009285#ifdef WLAN_KD_READY_NOTIFIER
9286 nl_srv_exit(pHddCtx->ptt_pid);
9287#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009288 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009289#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009290err_reg_netdev:
9291 unregister_netdevice_notifier(&hdd_netdev_notifier);
9292
9293err_free_power_on_lock:
9294 free_riva_power_on_lock("wlan");
9295
9296err_unregister_pmops:
9297 hddDevTmUnregisterNotifyCallback(pHddCtx);
9298 hddDeregisterPmOps(pHddCtx);
9299
Yue Ma0d4891e2013-08-06 17:01:45 -07009300 hdd_debugfs_exit(pHddCtx);
9301
Jeff Johnson295189b2012-06-20 16:38:30 -07009302#ifdef WLAN_BTAMP_FEATURE
9303err_bap_stop:
9304 WLANBAP_Stop(pVosContext);
9305#endif
9306
9307#ifdef WLAN_BTAMP_FEATURE
9308err_bap_close:
9309 WLANBAP_Close(pVosContext);
9310#endif
9311
Jeff Johnson295189b2012-06-20 16:38:30 -07009312err_close_adapter:
9313 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309314#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309315err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309316#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309317 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009318err_vosstop:
9319 vos_stop(pVosContext);
9320
Amar Singhala49cbc52013-10-08 18:37:44 -07009321err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009322 status = vos_sched_close( pVosContext );
9323 if (!VOS_IS_STATUS_SUCCESS(status)) {
9324 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9325 "%s: Failed to close VOSS Scheduler", __func__);
9326 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9327 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009328 vos_close(pVosContext );
9329
Amar Singhal0a402232013-10-11 20:57:16 -07009330err_vos_nv_close:
9331
c_hpothue6a36282014-03-19 12:27:38 +05309332#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009333 vos_nv_close();
9334
c_hpothu70f8d812014-03-22 22:59:23 +05309335#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009336
9337err_wdclose:
9338 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9339 vos_watchdog_close(pVosContext);
9340
Jeff Johnson295189b2012-06-20 16:38:30 -07009341err_config:
9342 kfree(pHddCtx->cfg_ini);
9343 pHddCtx->cfg_ini= NULL;
9344
9345err_free_hdd_context:
9346 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009347 wiphy_free(wiphy) ;
9348 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009349 VOS_BUG(1);
9350
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009351 if (hdd_is_ssr_required())
9352 {
9353 /* WDI timeout had happened during load, so SSR is needed here */
9354 subsystem_restart("wcnss");
9355 msleep(5000);
9356 }
9357 hdd_set_ssr_required (VOS_FALSE);
9358
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009359 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009360
9361success:
9362 EXIT();
9363 return 0;
9364}
9365
9366/**---------------------------------------------------------------------------
9367
Jeff Johnson32d95a32012-09-10 13:15:23 -07009368 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009369
Jeff Johnson32d95a32012-09-10 13:15:23 -07009370 This is the driver entry point - called in different timeline depending
9371 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009372
9373 \param - None
9374
9375 \return - 0 for success, non zero for failure
9376
9377 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009378static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009379{
9380 VOS_STATUS status;
9381 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009382 struct device *dev = NULL;
9383 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009384#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9385 int max_retries = 0;
9386#endif
Anand N Sunkad337f2fd2014-10-10 22:37:38 +05309387#ifdef HAVE_CBC_DONE
9388 int max_cbc_retries = 0;
9389#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009390
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309391#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9392 wlan_logging_sock_init_svc();
9393#endif
9394
Jeff Johnson295189b2012-06-20 16:38:30 -07009395 ENTER();
9396
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009397#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009398 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009399#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009400
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309401 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009402 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9403 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9404
Jeff Johnson295189b2012-06-20 16:38:30 -07009405#ifdef ANI_BUS_TYPE_PCI
9406
9407 dev = wcnss_wlan_get_device();
9408
9409#endif // ANI_BUS_TYPE_PCI
9410
9411#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009412
9413#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9414 /* wait until WCNSS driver downloads NV */
9415 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9416 msleep(1000);
9417 }
Anand N Sunkad337f2fd2014-10-10 22:37:38 +05309418
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009419 if (max_retries >= 5) {
9420 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309421#ifdef WLAN_OPEN_SOURCE
9422 wake_lock_destroy(&wlan_wake_lock);
9423#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309424
9425#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9426 wlan_logging_sock_deinit_svc();
9427#endif
9428
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009429 return -ENODEV;
9430 }
9431#endif
9432
Anand N Sunkad337f2fd2014-10-10 22:37:38 +05309433#ifdef HAVE_CBC_DONE
9434 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
9435 msleep(1000);
9436 }
9437 if (max_cbc_retries >= 10) {
9438 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
9439 }
9440#endif
9441
Jeff Johnson295189b2012-06-20 16:38:30 -07009442 dev = wcnss_wlan_get_device();
9443#endif // ANI_BUS_TYPE_PLATFORM
9444
9445
9446 do {
9447 if (NULL == dev) {
9448 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9449 ret_status = -1;
9450 break;
9451 }
9452
Jeff Johnson295189b2012-06-20 16:38:30 -07009453#ifdef TIMER_MANAGER
9454 vos_timer_manager_init();
9455#endif
9456
9457 /* Preopen VOSS so that it is ready to start at least SAL */
9458 status = vos_preOpen(&pVosContext);
9459
9460 if (!VOS_IS_STATUS_SUCCESS(status))
9461 {
9462 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9463 ret_status = -1;
9464 break;
9465 }
9466
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009467#ifndef MODULE
9468 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9469 */
9470 hdd_set_conparam((v_UINT_t)con_mode);
9471#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009472
9473 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009474 if (hdd_wlan_startup(dev))
9475 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009476 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009477 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009478 vos_preClose( &pVosContext );
9479 ret_status = -1;
9480 break;
9481 }
9482
Jeff Johnson295189b2012-06-20 16:38:30 -07009483 } while (0);
9484
9485 if (0 != ret_status)
9486 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009487#ifdef TIMER_MANAGER
9488 vos_timer_exit();
9489#endif
9490#ifdef MEMORY_DEBUG
9491 vos_mem_exit();
9492#endif
9493
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009494#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009495 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009496#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309497
9498#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9499 wlan_logging_sock_deinit_svc();
9500#endif
9501
Jeff Johnson295189b2012-06-20 16:38:30 -07009502 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9503 }
9504 else
9505 {
9506 //Send WLAN UP indication to Nlink Service
9507 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9508
9509 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009510 }
9511
9512 EXIT();
9513
9514 return ret_status;
9515}
9516
Jeff Johnson32d95a32012-09-10 13:15:23 -07009517/**---------------------------------------------------------------------------
9518
9519 \brief hdd_module_init() - Init Function
9520
9521 This is the driver entry point (invoked when module is loaded using insmod)
9522
9523 \param - None
9524
9525 \return - 0 for success, non zero for failure
9526
9527 --------------------------------------------------------------------------*/
9528#ifdef MODULE
9529static int __init hdd_module_init ( void)
9530{
9531 return hdd_driver_init();
9532}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009533#else /* #ifdef MODULE */
9534static int __init hdd_module_init ( void)
9535{
9536 /* Driver initialization is delayed to fwpath_changed_handler */
9537 return 0;
9538}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009539#endif /* #ifdef MODULE */
9540
Jeff Johnson295189b2012-06-20 16:38:30 -07009541
9542/**---------------------------------------------------------------------------
9543
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009544 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009545
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009546 This is the driver exit point (invoked when module is unloaded using rmmod
9547 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009548
9549 \param - None
9550
9551 \return - None
9552
9553 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009554static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009555{
9556 hdd_context_t *pHddCtx = NULL;
9557 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309558 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309559 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009560
9561 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9562
9563 //Get the global vos context
9564 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9565
9566 if(!pVosContext)
9567 {
9568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9569 goto done;
9570 }
9571
9572 //Get the HDD context.
9573 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9574
9575 if(!pHddCtx)
9576 {
9577 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9578 }
9579 else
9580 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309581 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9582
9583 if (pHddCtx->isLogpInProgress)
9584 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309586 "%s:SSR in Progress; block rmmod !!!", __func__);
9587 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9588 msecs_to_jiffies(30000));
9589 if(!rc)
9590 {
9591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9592 "%s:SSR timedout, fatal error", __func__);
9593 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009594 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309595 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009596
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309597 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309598 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009599 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309600 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009601
Agarwal Ashish8db39882014-07-30 21:56:07 +05309602 /* Driver Need to send country code 00 in below condition
9603 * 1) If gCountryCodePriority is set to 1; and last country
9604 * code set is through 11d. This needs to be done in case
9605 * when NV country code is 00.
9606 * This Needs to be done as when kernel store last country
9607 * code and if stored country code is not through 11d,
9608 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9609 * in next load/unload as soon as we get any country through
9610 * 11d. In sme_HandleChangeCountryCodeByUser
9611 * pMsg->countryCode will be last countryCode and
9612 * pMac->scan.countryCode11d will be country through 11d so
9613 * due to mismatch driver will disable 11d.
9614 *
9615 * 2) When NV country Code is non-zero ;
9616 * There are chances that kernel last country and default
9617 * country can be same. In this case if Driver doesn't pass 00 to
9618 * kernel, at the time of driver loading next timer, driver will not
9619 * call any hint to kernel as country is same. This can add 3 sec
9620 * delay in driver loading.
9621 */
9622
9623 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309624 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Agarwal Ashish8db39882014-07-30 21:56:07 +05309625 sme_Is11dSupported(pHddCtx->hHal)) || (vos_is_nv_country_non_zero() ))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309626 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309627 hddLog(VOS_TRACE_LEVEL_INFO,
9628 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309629 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9630 }
9631
Jeff Johnson295189b2012-06-20 16:38:30 -07009632 //Do all the cleanup before deregistering the driver
9633 hdd_wlan_exit(pHddCtx);
9634 }
9635
Jeff Johnson295189b2012-06-20 16:38:30 -07009636 vos_preClose( &pVosContext );
9637
9638#ifdef TIMER_MANAGER
9639 vos_timer_exit();
9640#endif
9641#ifdef MEMORY_DEBUG
9642 vos_mem_exit();
9643#endif
9644
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309645#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9646 wlan_logging_sock_deinit_svc();
9647#endif
9648
Jeff Johnson295189b2012-06-20 16:38:30 -07009649done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009650#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009651 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009652#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309653
Jeff Johnson295189b2012-06-20 16:38:30 -07009654 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9655}
9656
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009657/**---------------------------------------------------------------------------
9658
9659 \brief hdd_module_exit() - Exit function
9660
9661 This is the driver exit point (invoked when module is unloaded using rmmod)
9662
9663 \param - None
9664
9665 \return - None
9666
9667 --------------------------------------------------------------------------*/
9668static void __exit hdd_module_exit(void)
9669{
9670 hdd_driver_exit();
9671}
9672
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009673#ifdef MODULE
9674static int fwpath_changed_handler(const char *kmessage,
9675 struct kernel_param *kp)
9676{
Jeff Johnson76052702013-04-16 13:55:05 -07009677 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009678}
9679
9680static int con_mode_handler(const char *kmessage,
9681 struct kernel_param *kp)
9682{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009683 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009684}
9685#else /* #ifdef MODULE */
9686/**---------------------------------------------------------------------------
9687
Jeff Johnson76052702013-04-16 13:55:05 -07009688 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009689
Jeff Johnson76052702013-04-16 13:55:05 -07009690 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009691 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009692 - invoked when module parameter fwpath is modified from userspace to signal
9693 initializing the WLAN driver or when con_mode is modified from userspace
9694 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009695
9696 \return - 0 for success, non zero for failure
9697
9698 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009699static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009700{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009701 int ret_status;
9702
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009703 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009704 ret_status = hdd_driver_init();
9705 wlan_hdd_inited = ret_status ? 0 : 1;
9706 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009707 }
9708
9709 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009710
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009711 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009712
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009713 ret_status = hdd_driver_init();
9714 wlan_hdd_inited = ret_status ? 0 : 1;
9715 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009716}
9717
Jeff Johnson295189b2012-06-20 16:38:30 -07009718/**---------------------------------------------------------------------------
9719
Jeff Johnson76052702013-04-16 13:55:05 -07009720 \brief fwpath_changed_handler() - Handler Function
9721
9722 Handle changes to the fwpath parameter
9723
9724 \return - 0 for success, non zero for failure
9725
9726 --------------------------------------------------------------------------*/
9727static int fwpath_changed_handler(const char *kmessage,
9728 struct kernel_param *kp)
9729{
9730 int ret;
9731
9732 ret = param_set_copystring(kmessage, kp);
9733 if (0 == ret)
9734 ret = kickstart_driver();
9735 return ret;
9736}
9737
9738/**---------------------------------------------------------------------------
9739
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009740 \brief con_mode_handler() -
9741
9742 Handler function for module param con_mode when it is changed by userspace
9743 Dynamically linked - do nothing
9744 Statically linked - exit and init driver, as in rmmod and insmod
9745
Jeff Johnson76052702013-04-16 13:55:05 -07009746 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009747
Jeff Johnson76052702013-04-16 13:55:05 -07009748 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009749
9750 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009751static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009752{
Jeff Johnson76052702013-04-16 13:55:05 -07009753 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009754
Jeff Johnson76052702013-04-16 13:55:05 -07009755 ret = param_set_int(kmessage, kp);
9756 if (0 == ret)
9757 ret = kickstart_driver();
9758 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009759}
9760#endif /* #ifdef MODULE */
9761
9762/**---------------------------------------------------------------------------
9763
Jeff Johnson295189b2012-06-20 16:38:30 -07009764 \brief hdd_get_conparam() -
9765
9766 This is the driver exit point (invoked when module is unloaded using rmmod)
9767
9768 \param - None
9769
9770 \return - tVOS_CON_MODE
9771
9772 --------------------------------------------------------------------------*/
9773tVOS_CON_MODE hdd_get_conparam ( void )
9774{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009775#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009776 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009777#else
9778 return (tVOS_CON_MODE)curr_con_mode;
9779#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009780}
9781void hdd_set_conparam ( v_UINT_t newParam )
9782{
9783 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009784#ifndef MODULE
9785 curr_con_mode = con_mode;
9786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009787}
9788/**---------------------------------------------------------------------------
9789
9790 \brief hdd_softap_sta_deauth() - function
9791
9792 This to take counter measure to handle deauth req from HDD
9793
9794 \param - pAdapter - Pointer to the HDD
9795
9796 \param - enable - boolean value
9797
9798 \return - None
9799
9800 --------------------------------------------------------------------------*/
9801
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009802VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009803{
Jeff Johnson295189b2012-06-20 16:38:30 -07009804 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009805 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009806
9807 ENTER();
9808
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009809 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9810 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009811
9812 //Ignore request to deauth bcmc station
9813 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009814 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009815
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009816 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009817
9818 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009819 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009820}
9821
9822/**---------------------------------------------------------------------------
9823
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309824 \brief hdd_del_all_sta() - function
9825
9826 This function removes all the stations associated on stopping AP/P2P GO.
9827
9828 \param - pAdapter - Pointer to the HDD
9829
9830 \return - None
9831
9832 --------------------------------------------------------------------------*/
9833
9834int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9835{
9836 v_U16_t i;
9837 VOS_STATUS vos_status;
9838
9839 ENTER();
9840
9841 hddLog(VOS_TRACE_LEVEL_INFO,
9842 "%s: Delete all STAs associated.",__func__);
9843 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9844 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9845 )
9846 {
9847 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9848 {
9849 if ((pAdapter->aStaInfo[i].isUsed) &&
9850 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9851 {
9852 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
9853 hddLog(VOS_TRACE_LEVEL_ERROR,
9854 "%s: Delete STA with staid = %d and MAC::"
9855 MAC_ADDRESS_STR,
9856 __func__, i, MAC_ADDR_ARRAY(macAddr));
9857 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
9858 if (VOS_IS_STATUS_SUCCESS(vos_status))
9859 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9860 }
9861 }
9862 }
9863
9864 EXIT();
9865 return 0;
9866}
9867
9868/**---------------------------------------------------------------------------
9869
Jeff Johnson295189b2012-06-20 16:38:30 -07009870 \brief hdd_softap_sta_disassoc() - function
9871
9872 This to take counter measure to handle deauth req from HDD
9873
9874 \param - pAdapter - Pointer to the HDD
9875
9876 \param - enable - boolean value
9877
9878 \return - None
9879
9880 --------------------------------------------------------------------------*/
9881
9882void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9883{
9884 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9885
9886 ENTER();
9887
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309888 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009889
9890 //Ignore request to disassoc bcmc station
9891 if( pDestMacAddress[0] & 0x1 )
9892 return;
9893
9894 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9895}
9896
9897void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9898{
9899 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9900
9901 ENTER();
9902
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309903 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009904
9905 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9906}
9907
Jeff Johnson295189b2012-06-20 16:38:30 -07009908/**---------------------------------------------------------------------------
9909 *
9910 * \brief hdd_get__concurrency_mode() -
9911 *
9912 *
9913 * \param - None
9914 *
9915 * \return - CONCURRENCY MODE
9916 *
9917 * --------------------------------------------------------------------------*/
9918tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9919{
9920 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9921 hdd_context_t *pHddCtx;
9922
9923 if (NULL != pVosContext)
9924 {
9925 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9926 if (NULL != pHddCtx)
9927 {
9928 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9929 }
9930 }
9931
9932 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009933 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009934 return VOS_STA;
9935}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309936v_BOOL_t
9937wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9938{
9939 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009940
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309941 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9942 if (pAdapter == NULL)
9943 {
9944 hddLog(VOS_TRACE_LEVEL_INFO,
9945 FL("GO doesn't exist"));
9946 return TRUE;
9947 }
9948 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9949 {
9950 hddLog(VOS_TRACE_LEVEL_INFO,
9951 FL("GO started"));
9952 return TRUE;
9953 }
9954 else
9955 /* wait till GO changes its interface to p2p device */
9956 hddLog(VOS_TRACE_LEVEL_INFO,
9957 FL("Del_bss called, avoid apps suspend"));
9958 return FALSE;
9959
9960}
Jeff Johnson295189b2012-06-20 16:38:30 -07009961/* Decide whether to allow/not the apps power collapse.
9962 * Allow apps power collapse if we are in connected state.
9963 * if not, allow only if we are in IMPS */
9964v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9965{
9966 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009967 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009968 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009969 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9970 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9971 hdd_adapter_t *pAdapter = NULL;
9972 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009973 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009974
Jeff Johnson295189b2012-06-20 16:38:30 -07009975 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9976 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009977
Yathish9f22e662012-12-10 14:21:35 -08009978 concurrent_state = hdd_get_concurrency_mode();
9979
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309980 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
9981 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
9982 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -08009983#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309984
Yathish9f22e662012-12-10 14:21:35 -08009985 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309986 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -08009987 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9988 return TRUE;
9989#endif
9990
Jeff Johnson295189b2012-06-20 16:38:30 -07009991 /*loop through all adapters. TBD fix for Concurrency */
9992 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9993 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9994 {
9995 pAdapter = pAdapterNode->pAdapter;
9996 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9997 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9998 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009999 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010000 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010001 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010002 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10003 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010004 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010005 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010006 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10007 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010008 return FALSE;
10009 }
10010 }
10011 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10012 pAdapterNode = pNext;
10013 }
10014 return TRUE;
10015}
10016
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010017/* Decides whether to send suspend notification to Riva
10018 * if any adapter is in BMPS; then it is required */
10019v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10020{
10021 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10022 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10023
10024 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10025 {
10026 return TRUE;
10027 }
10028 return FALSE;
10029}
10030
Jeff Johnson295189b2012-06-20 16:38:30 -070010031void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10032{
10033 switch(mode)
10034 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010035 case VOS_STA_MODE:
10036 case VOS_P2P_CLIENT_MODE:
10037 case VOS_P2P_GO_MODE:
10038 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010039 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010040 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010041 break;
10042 default:
10043 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010044 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010045 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10046 "Number of open sessions for mode %d = %d"),
10047 pHddCtx->concurrency_mode, mode,
10048 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010049}
10050
10051
10052void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10053{
10054 switch(mode)
10055 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010056 case VOS_STA_MODE:
10057 case VOS_P2P_CLIENT_MODE:
10058 case VOS_P2P_GO_MODE:
10059 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010060 pHddCtx->no_of_open_sessions[mode]--;
10061 if (!(pHddCtx->no_of_open_sessions[mode]))
10062 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010063 break;
10064 default:
10065 break;
10066 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010067 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10068 "Number of open sessions for mode %d = %d"),
10069 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10070
10071}
10072/**---------------------------------------------------------------------------
10073 *
10074 * \brief wlan_hdd_incr_active_session()
10075 *
10076 * This function increments the number of active sessions
10077 * maintained per device mode
10078 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10079 * Incase of SAP/P2P GO upon bss start it is incremented
10080 *
10081 * \param pHddCtx - HDD Context
10082 * \param mode - device mode
10083 *
10084 * \return - None
10085 *
10086 * --------------------------------------------------------------------------*/
10087void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10088{
10089 switch (mode) {
10090 case VOS_STA_MODE:
10091 case VOS_P2P_CLIENT_MODE:
10092 case VOS_P2P_GO_MODE:
10093 case VOS_STA_SAP_MODE:
10094 pHddCtx->no_of_active_sessions[mode]++;
10095 break;
10096 default:
10097 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10098 break;
10099 }
10100 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10101 mode,
10102 pHddCtx->no_of_active_sessions[mode]);
10103}
10104
10105/**---------------------------------------------------------------------------
10106 *
10107 * \brief wlan_hdd_decr_active_session()
10108 *
10109 * This function decrements the number of active sessions
10110 * maintained per device mode
10111 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10112 * Incase of SAP/P2P GO upon bss stop it is decremented
10113 *
10114 * \param pHddCtx - HDD Context
10115 * \param mode - device mode
10116 *
10117 * \return - None
10118 *
10119 * --------------------------------------------------------------------------*/
10120void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10121{
10122 switch (mode) {
10123 case VOS_STA_MODE:
10124 case VOS_P2P_CLIENT_MODE:
10125 case VOS_P2P_GO_MODE:
10126 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010127 if (pHddCtx->no_of_active_sessions[mode] > 0)
10128 pHddCtx->no_of_active_sessions[mode]--;
10129 else
10130 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10131 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010132 break;
10133 default:
10134 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10135 break;
10136 }
10137 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10138 mode,
10139 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010140}
10141
Jeff Johnsone7245742012-09-05 17:12:55 -070010142/**---------------------------------------------------------------------------
10143 *
10144 * \brief wlan_hdd_restart_init
10145 *
10146 * This function initalizes restart timer/flag. An internal function.
10147 *
10148 * \param - pHddCtx
10149 *
10150 * \return - None
10151 *
10152 * --------------------------------------------------------------------------*/
10153
10154static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10155{
10156 /* Initialize */
10157 pHddCtx->hdd_restart_retries = 0;
10158 atomic_set(&pHddCtx->isRestartInProgress, 0);
10159 vos_timer_init(&pHddCtx->hdd_restart_timer,
10160 VOS_TIMER_TYPE_SW,
10161 wlan_hdd_restart_timer_cb,
10162 pHddCtx);
10163}
10164/**---------------------------------------------------------------------------
10165 *
10166 * \brief wlan_hdd_restart_deinit
10167 *
10168 * This function cleans up the resources used. An internal function.
10169 *
10170 * \param - pHddCtx
10171 *
10172 * \return - None
10173 *
10174 * --------------------------------------------------------------------------*/
10175
10176static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10177{
10178
10179 VOS_STATUS vos_status;
10180 /* Block any further calls */
10181 atomic_set(&pHddCtx->isRestartInProgress, 1);
10182 /* Cleanup */
10183 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10184 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010185 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010186 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10187 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010188 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010189
10190}
10191
10192/**---------------------------------------------------------------------------
10193 *
10194 * \brief wlan_hdd_framework_restart
10195 *
10196 * This function uses a cfg80211 API to start a framework initiated WLAN
10197 * driver module unload/load.
10198 *
10199 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10200 *
10201 *
10202 * \param - pHddCtx
10203 *
10204 * \return - VOS_STATUS_SUCCESS: Success
10205 * VOS_STATUS_E_EMPTY: Adapter is Empty
10206 * VOS_STATUS_E_NOMEM: No memory
10207
10208 * --------------------------------------------------------------------------*/
10209
10210static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10211{
10212 VOS_STATUS status = VOS_STATUS_SUCCESS;
10213 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010214 int len = (sizeof (struct ieee80211_mgmt));
10215 struct ieee80211_mgmt *mgmt = NULL;
10216
10217 /* Prepare the DEAUTH managment frame with reason code */
10218 mgmt = kzalloc(len, GFP_KERNEL);
10219 if(mgmt == NULL)
10220 {
10221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10222 "%s: memory allocation failed (%d bytes)", __func__, len);
10223 return VOS_STATUS_E_NOMEM;
10224 }
10225 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010226
10227 /* Iterate over all adapters/devices */
10228 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10229 do
10230 {
10231 if( (status == VOS_STATUS_SUCCESS) &&
10232 pAdapterNode &&
10233 pAdapterNode->pAdapter)
10234 {
10235 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10236 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10237 pAdapterNode->pAdapter->dev->name,
10238 pAdapterNode->pAdapter->device_mode,
10239 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010240 /*
10241 * CFG80211 event to restart the driver
10242 *
10243 * 'cfg80211_send_unprot_deauth' sends a
10244 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10245 * of SME(Linux Kernel) state machine.
10246 *
10247 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10248 * the driver.
10249 *
10250 */
10251
10252 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010253 }
10254 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10255 pAdapterNode = pNext;
10256 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10257
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010258
10259 /* Free the allocated management frame */
10260 kfree(mgmt);
10261
Jeff Johnsone7245742012-09-05 17:12:55 -070010262 /* Retry until we unload or reach max count */
10263 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10264 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10265
10266 return status;
10267
10268}
10269/**---------------------------------------------------------------------------
10270 *
10271 * \brief wlan_hdd_restart_timer_cb
10272 *
10273 * Restart timer callback. An internal function.
10274 *
10275 * \param - User data:
10276 *
10277 * \return - None
10278 *
10279 * --------------------------------------------------------------------------*/
10280
10281void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10282{
10283 hdd_context_t *pHddCtx = usrDataForCallback;
10284 wlan_hdd_framework_restart(pHddCtx);
10285 return;
10286
10287}
10288
10289
10290/**---------------------------------------------------------------------------
10291 *
10292 * \brief wlan_hdd_restart_driver
10293 *
10294 * This function sends an event to supplicant to restart the WLAN driver.
10295 *
10296 * This function is called from vos_wlanRestart.
10297 *
10298 * \param - pHddCtx
10299 *
10300 * \return - VOS_STATUS_SUCCESS: Success
10301 * VOS_STATUS_E_EMPTY: Adapter is Empty
10302 * VOS_STATUS_E_ALREADY: Request already in progress
10303
10304 * --------------------------------------------------------------------------*/
10305VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10306{
10307 VOS_STATUS status = VOS_STATUS_SUCCESS;
10308
10309 /* A tight check to make sure reentrancy */
10310 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10311 {
Mihir Shetefd528652014-06-23 19:07:50 +053010312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010313 "%s: WLAN restart is already in progress", __func__);
10314
10315 return VOS_STATUS_E_ALREADY;
10316 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010317 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010318#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010319 wcnss_reset_intr();
10320#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010321
Jeff Johnsone7245742012-09-05 17:12:55 -070010322 return status;
10323}
10324
Mihir Shetee1093ba2014-01-21 20:13:32 +053010325/**---------------------------------------------------------------------------
10326 *
10327 * \brief wlan_hdd_init_channels
10328 *
10329 * This function is used to initialize the channel list in CSR
10330 *
10331 * This function is called from hdd_wlan_startup
10332 *
10333 * \param - pHddCtx: HDD context
10334 *
10335 * \return - VOS_STATUS_SUCCESS: Success
10336 * VOS_STATUS_E_FAULT: Failure reported by SME
10337
10338 * --------------------------------------------------------------------------*/
10339static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10340{
10341 eHalStatus status;
10342
10343 status = sme_InitChannels(pHddCtx->hHal);
10344 if (HAL_STATUS_SUCCESS(status))
10345 {
10346 return VOS_STATUS_SUCCESS;
10347 }
10348 else
10349 {
10350 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10351 __func__, status);
10352 return VOS_STATUS_E_FAULT;
10353 }
10354}
10355
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010356VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010357{
10358 eHalStatus status;
10359
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010360 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010361 if (HAL_STATUS_SUCCESS(status))
10362 {
10363 return VOS_STATUS_SUCCESS;
10364 }
10365 else
10366 {
10367 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10368 __func__, status);
10369 return VOS_STATUS_E_FAULT;
10370 }
10371}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010372/*
10373 * API to find if there is any STA or P2P-Client is connected
10374 */
10375VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10376{
10377 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10378}
Jeff Johnsone7245742012-09-05 17:12:55 -070010379
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010380int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10381{
10382 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10383 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010384 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010385
10386 pScanInfo = &pHddCtx->scan_info;
10387 if (pScanInfo->mScanPending)
10388 {
10389 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10390 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10391 eCSR_SCAN_ABORT_DEFAULT);
10392
10393 status = wait_for_completion_interruptible_timeout(
10394 &pScanInfo->abortscan_event_var,
10395 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010396 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010397 {
10398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010399 "%s: Timeout or Interrupt occurred while waiting for abort"
10400 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010401 return -ETIMEDOUT;
10402 }
10403 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010404 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010405}
10406
Jeff Johnson295189b2012-06-20 16:38:30 -070010407//Register the module init/exit functions
10408module_init(hdd_module_init);
10409module_exit(hdd_module_exit);
10410
10411MODULE_LICENSE("Dual BSD/GPL");
10412MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10413MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10414
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010415module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10416 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010417
Jeff Johnson76052702013-04-16 13:55:05 -070010418module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010419 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010420
10421module_param(enable_dfs_chan_scan, int,
10422 S_IRUSR | S_IRGRP | S_IROTH);
10423
10424module_param(enable_11d, int,
10425 S_IRUSR | S_IRGRP | S_IROTH);
10426
10427module_param(country_code, charp,
10428 S_IRUSR | S_IRGRP | S_IROTH);