blob: b5858b6545d93b13460e9283eed5ba1f241fc9cb [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;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302127 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2128 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002129 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302130 int status;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002131 /*
2132 * Note that valid pointers are provided by caller
2133 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002134
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002135 /* copy to local struct to avoid numerous changes to legacy code */
2136 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002137
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002138 if (priv_data.total_len <= 0 ||
2139 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002140 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002141 hddLog(VOS_TRACE_LEVEL_WARN,
2142 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2143 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002144 ret = -EINVAL;
2145 goto exit;
2146 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05302147 status = wlan_hdd_validate_context(pHddCtx);
2148 if (0 != status)
2149 {
2150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2151 "%s: HDD context is not valid", __func__);
2152 return status;
2153 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002154 /* Allocate +1 for '\0' */
2155 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002156 if (!command)
2157 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002158 hddLog(VOS_TRACE_LEVEL_ERROR,
2159 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002160 ret = -ENOMEM;
2161 goto exit;
2162 }
2163
2164 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2165 {
2166 ret = -EFAULT;
2167 goto exit;
2168 }
2169
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002170 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002171 command[priv_data.total_len] = '\0';
2172
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002173 /* at one time the following block of code was conditional. braces
2174 * have been retained to avoid re-indenting the legacy code
2175 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002176 {
2177 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2178
2179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002180 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002181
2182 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2183 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302184 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2185 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2186 pAdapter->sessionId, (unsigned)
2187 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2188 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2189 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2190 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2192 sizeof(tSirMacAddr)))
2193 {
2194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002195 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 ret = -EFAULT;
2197 }
2198 }
Amar Singhal0974e402013-02-12 14:27:46 -08002199 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 {
Amar Singhal0974e402013-02-12 14:27:46 -08002201 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002202
Jeff Johnson295189b2012-06-20 16:38:30 -07002203 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002204
2205 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002206 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002208 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002209 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002210 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302211 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302212 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002213 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002214 }
Kiet Lamf040f472013-11-20 21:15:23 +05302215 else if(strncmp(command, "SETWMMPS", 8) == 0)
2216 {
2217 tANI_U8 *ptr = command;
2218 ret = hdd_wmmps_helper(pAdapter, ptr);
2219 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002220 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2221 {
2222 char *country_code;
2223
2224 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002225
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002226 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002227 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002228#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302229 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002230#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002231 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2232 (void *)(tSmeChangeCountryCallback)
2233 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302234 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002235 if (eHAL_STATUS_SUCCESS == ret)
2236 {
2237 ret = wait_for_completion_interruptible_timeout(
2238 &pAdapter->change_country_code,
2239 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2240 if (0 >= ret)
2241 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002242 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302243 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002244 }
2245 }
2246 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002247 {
2248 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002249 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002250 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002251 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002252
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002253 }
2254 /*
2255 command should be a string having format
2256 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2257 */
Amar Singhal0974e402013-02-12 14:27:46 -08002258 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002259 {
Amar Singhal0974e402013-02-12 14:27:46 -08002260 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002261
2262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002263 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002264
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002265 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002266 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002267 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2268 {
2269 int suspend = 0;
2270 tANI_U8 *ptr = (tANI_U8*)command + 15;
2271
2272 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302273 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2274 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2275 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002276 hdd_set_wlan_suspend_mode(suspend);
2277 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002278#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2279 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2280 {
2281 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002282 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002283 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2284 eHalStatus status = eHAL_STATUS_SUCCESS;
2285
2286 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2287 value = value + 15;
2288
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002289 /* Convert the value from ascii to integer */
2290 ret = kstrtos8(value, 10, &rssi);
2291 if (ret < 0)
2292 {
2293 /* If the input value is greater than max value of datatype, then also
2294 kstrtou8 fails */
2295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2296 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002297 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002298 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2299 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2300 ret = -EINVAL;
2301 goto exit;
2302 }
2303
Srinivas Girigowdade697412013-02-14 16:31:48 -08002304 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002305
Srinivas Girigowdade697412013-02-14 16:31:48 -08002306 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2307 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2308 {
2309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2310 "Neighbor lookup threshold value %d is out of range"
2311 " (Min: %d Max: %d)", lookUpThreshold,
2312 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2313 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2314 ret = -EINVAL;
2315 goto exit;
2316 }
2317
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302318 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2319 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2320 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2322 "%s: Received Command to Set Roam trigger"
2323 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2324
2325 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2326 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2327 if (eHAL_STATUS_SUCCESS != status)
2328 {
2329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2330 "%s: Failed to set roam trigger, try again", __func__);
2331 ret = -EPERM;
2332 goto exit;
2333 }
2334
2335 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302336 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2338 }
2339 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2340 {
2341 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2342 int rssi = (-1) * lookUpThreshold;
2343 char extra[32];
2344 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302345 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2346 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2347 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002348 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002349 if (copy_to_user(priv_data.buf, &extra, len + 1))
2350 {
2351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2352 "%s: failed to copy data to user buffer", __func__);
2353 ret = -EFAULT;
2354 goto exit;
2355 }
2356 }
2357 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2358 {
2359 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002360 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002361 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002362
Srinivas Girigowdade697412013-02-14 16:31:48 -08002363 /* input refresh period is in terms of seconds */
2364 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2365 value = value + 18;
2366 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002367 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368 if (ret < 0)
2369 {
2370 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002371 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002373 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002374 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002375 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2376 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 ret = -EINVAL;
2378 goto exit;
2379 }
2380
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002381 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2382 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002383 {
2384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002385 "Roam scan period value %d is out of range"
2386 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002387 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2388 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002389 ret = -EINVAL;
2390 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302391 }
2392 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2393 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2394 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002395 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002396
2397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2398 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002399 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002400
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002401 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2402 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002403 }
2404 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2405 {
2406 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2407 char extra[32];
2408 tANI_U8 len = 0;
2409
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302410 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2411 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2412 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002413 len = scnprintf(extra, sizeof(extra), "%s %d",
2414 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002415 /* Returned value is in units of seconds */
2416 if (copy_to_user(priv_data.buf, &extra, len + 1))
2417 {
2418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2419 "%s: failed to copy data to user buffer", __func__);
2420 ret = -EFAULT;
2421 goto exit;
2422 }
2423 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002424 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2425 {
2426 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002429
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002430 /* input refresh period is in terms of seconds */
2431 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2432 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002433
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002435 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 if (ret < 0)
2437 {
2438 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002439 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002441 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002442 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002443 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2444 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2445 ret = -EINVAL;
2446 goto exit;
2447 }
2448
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002449 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2450 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2451 {
2452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2453 "Neighbor scan results refresh period value %d is out of range"
2454 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2455 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2456 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2457 ret = -EINVAL;
2458 goto exit;
2459 }
2460 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2461
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2463 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002464 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002465
2466 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2467 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2468 }
2469 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2470 {
2471 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2472 char extra[32];
2473 tANI_U8 len = 0;
2474
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002475 len = scnprintf(extra, sizeof(extra), "%s %d",
2476 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002477 /* Returned value is in units of seconds */
2478 if (copy_to_user(priv_data.buf, &extra, len + 1))
2479 {
2480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2481 "%s: failed to copy data to user buffer", __func__);
2482 ret = -EFAULT;
2483 goto exit;
2484 }
2485 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002486#ifdef FEATURE_WLAN_LFR
2487 /* SETROAMMODE */
2488 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2489 {
2490 tANI_U8 *value = command;
2491 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2492
2493 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2494 value = value + SIZE_OF_SETROAMMODE + 1;
2495
2496 /* Convert the value from ascii to integer */
2497 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2498 if (ret < 0)
2499 {
2500 /* If the input value is greater than max value of datatype, then also
2501 kstrtou8 fails */
2502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2503 "%s: kstrtou8 failed range [%d - %d]", __func__,
2504 CFG_LFR_FEATURE_ENABLED_MIN,
2505 CFG_LFR_FEATURE_ENABLED_MAX);
2506 ret = -EINVAL;
2507 goto exit;
2508 }
2509 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2510 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "Roam Mode value %d is out of range"
2514 " (Min: %d Max: %d)", roamMode,
2515 CFG_LFR_FEATURE_ENABLED_MIN,
2516 CFG_LFR_FEATURE_ENABLED_MAX);
2517 ret = -EINVAL;
2518 goto exit;
2519 }
2520
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2522 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2523 /*
2524 * Note that
2525 * SETROAMMODE 0 is to enable LFR while
2526 * SETROAMMODE 1 is to disable LFR, but
2527 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2528 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2529 */
2530 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2531 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2532 else
2533 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2534
2535 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2536 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2537 }
2538 /* GETROAMMODE */
2539 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2540 {
2541 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2542 char extra[32];
2543 tANI_U8 len = 0;
2544
2545 /*
2546 * roamMode value shall be inverted because the sementics is different.
2547 */
2548 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2549 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2550 else
2551 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2552
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002553 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002554 if (copy_to_user(priv_data.buf, &extra, len + 1))
2555 {
2556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2557 "%s: failed to copy data to user buffer", __func__);
2558 ret = -EFAULT;
2559 goto exit;
2560 }
2561 }
2562#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002563#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002564#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002565 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2566 {
2567 tANI_U8 *value = command;
2568 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2569
2570 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2571 value = value + 13;
2572 /* Convert the value from ascii to integer */
2573 ret = kstrtou8(value, 10, &roamRssiDiff);
2574 if (ret < 0)
2575 {
2576 /* If the input value is greater than max value of datatype, then also
2577 kstrtou8 fails */
2578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2579 "%s: kstrtou8 failed range [%d - %d]", __func__,
2580 CFG_ROAM_RSSI_DIFF_MIN,
2581 CFG_ROAM_RSSI_DIFF_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
2586 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2587 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2588 {
2589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2590 "Roam rssi diff value %d is out of range"
2591 " (Min: %d Max: %d)", roamRssiDiff,
2592 CFG_ROAM_RSSI_DIFF_MIN,
2593 CFG_ROAM_RSSI_DIFF_MAX);
2594 ret = -EINVAL;
2595 goto exit;
2596 }
2597
2598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2599 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2600
2601 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2602 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2603 }
2604 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2605 {
2606 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2607 char extra[32];
2608 tANI_U8 len = 0;
2609
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302610 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2611 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2612 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002613 len = scnprintf(extra, sizeof(extra), "%s %d",
2614 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002615 if (copy_to_user(priv_data.buf, &extra, len + 1))
2616 {
2617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2618 "%s: failed to copy data to user buffer", __func__);
2619 ret = -EFAULT;
2620 goto exit;
2621 }
2622 }
2623#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002624#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002625 else if (strncmp(command, "GETBAND", 7) == 0)
2626 {
2627 int band = -1;
2628 char extra[32];
2629 tANI_U8 len = 0;
2630 hdd_getBand_helper(pHddCtx, &band);
2631
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302632 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2633 TRACE_CODE_HDD_GETBAND_IOCTL,
2634 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002635 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002636 if (copy_to_user(priv_data.buf, &extra, len + 1))
2637 {
2638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2639 "%s: failed to copy data to user buffer", __func__);
2640 ret = -EFAULT;
2641 goto exit;
2642 }
2643 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002644 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2645 {
2646 tANI_U8 *value = command;
2647 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2648 tANI_U8 numChannels = 0;
2649 eHalStatus status = eHAL_STATUS_SUCCESS;
2650
2651 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2652 if (eHAL_STATUS_SUCCESS != status)
2653 {
2654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2655 "%s: Failed to parse channel list information", __func__);
2656 ret = -EINVAL;
2657 goto exit;
2658 }
2659
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302660 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2661 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2662 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002663 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2664 {
2665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2666 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2667 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2668 ret = -EINVAL;
2669 goto exit;
2670 }
2671 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2672 numChannels);
2673 if (eHAL_STATUS_SUCCESS != status)
2674 {
2675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2676 "%s: Failed to update channel list information", __func__);
2677 ret = -EINVAL;
2678 goto exit;
2679 }
2680 }
2681 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2682 {
2683 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2684 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002685 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002686 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002687 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002688
2689 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2690 ChannelList, &numChannels ))
2691 {
2692 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2693 "%s: failed to get roam scan channel list", __func__);
2694 ret = -EFAULT;
2695 goto exit;
2696 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302697 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2698 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2699 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002700 /* output channel list is of the format
2701 [Number of roam scan channels][Channel1][Channel2]... */
2702 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002703 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002704 for (j = 0; (j < numChannels); j++)
2705 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002706 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2707 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002708 }
2709
2710 if (copy_to_user(priv_data.buf, &extra, len + 1))
2711 {
2712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2713 "%s: failed to copy data to user buffer", __func__);
2714 ret = -EFAULT;
2715 goto exit;
2716 }
2717 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002718 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2719 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002720 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002721 char extra[32];
2722 tANI_U8 len = 0;
2723
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002724 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002725 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002726 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002727 hdd_is_okc_mode_enabled(pHddCtx) &&
2728 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2729 {
2730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002731 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002732 " hence this operation is not permitted!", __func__);
2733 ret = -EPERM;
2734 goto exit;
2735 }
2736
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002737 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002738 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002739 if (copy_to_user(priv_data.buf, &extra, len + 1))
2740 {
2741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2742 "%s: failed to copy data to user buffer", __func__);
2743 ret = -EFAULT;
2744 goto exit;
2745 }
2746 }
2747 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2748 {
2749 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2750 char extra[32];
2751 tANI_U8 len = 0;
2752
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002753 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002754 then this operation is not permitted (return FAILURE) */
2755 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002756 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002757 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2758 {
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002760 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002761 " hence this operation is not permitted!", __func__);
2762 ret = -EPERM;
2763 goto exit;
2764 }
2765
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002766 len = scnprintf(extra, sizeof(extra), "%s %d",
2767 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002768 if (copy_to_user(priv_data.buf, &extra, len + 1))
2769 {
2770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: failed to copy data to user buffer", __func__);
2772 ret = -EFAULT;
2773 goto exit;
2774 }
2775 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002776 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002777 {
2778 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2779 char extra[32];
2780 tANI_U8 len = 0;
2781
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002782 len = scnprintf(extra, sizeof(extra), "%s %d",
2783 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002784 if (copy_to_user(priv_data.buf, &extra, len + 1))
2785 {
2786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2787 "%s: failed to copy data to user buffer", __func__);
2788 ret = -EFAULT;
2789 goto exit;
2790 }
2791 }
2792 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2793 {
2794 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2795 char extra[32];
2796 tANI_U8 len = 0;
2797
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002798 len = scnprintf(extra, sizeof(extra), "%s %d",
2799 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002800 if (copy_to_user(priv_data.buf, &extra, len + 1))
2801 {
2802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2803 "%s: failed to copy data to user buffer", __func__);
2804 ret = -EFAULT;
2805 goto exit;
2806 }
2807 }
2808 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2809 {
2810 tANI_U8 *value = command;
2811 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2812
2813 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2814 value = value + 26;
2815 /* Convert the value from ascii to integer */
2816 ret = kstrtou8(value, 10, &minTime);
2817 if (ret < 0)
2818 {
2819 /* If the input value is greater than max value of datatype, then also
2820 kstrtou8 fails */
2821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2822 "%s: kstrtou8 failed range [%d - %d]", __func__,
2823 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2824 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2825 ret = -EINVAL;
2826 goto exit;
2827 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002828 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2829 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2830 {
2831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2832 "scan min channel time value %d is out of range"
2833 " (Min: %d Max: %d)", minTime,
2834 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2835 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
2839
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302840 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2841 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2842 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2844 "%s: Received Command to change channel min time = %d", __func__, minTime);
2845
2846 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2847 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2848 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002849 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2850 {
2851 tANI_U8 *value = command;
2852 tANI_U8 channel = 0;
2853 tANI_U8 dwellTime = 0;
2854 tANI_U8 bufLen = 0;
2855 tANI_U8 *buf = NULL;
2856 tSirMacAddr targetApBssid;
2857 eHalStatus status = eHAL_STATUS_SUCCESS;
2858 struct ieee80211_channel chan;
2859 tANI_U8 finalLen = 0;
2860 tANI_U8 *finalBuf = NULL;
2861 tANI_U8 temp = 0;
2862 u64 cookie;
2863 hdd_station_ctx_t *pHddStaCtx = NULL;
2864 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2865
2866 /* if not associated, no need to send action frame */
2867 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2868 {
2869 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2870 ret = -EINVAL;
2871 goto exit;
2872 }
2873
2874 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2875 &dwellTime, &buf, &bufLen);
2876 if (eHAL_STATUS_SUCCESS != status)
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2879 "%s: Failed to parse send action frame data", __func__);
2880 ret = -EINVAL;
2881 goto exit;
2882 }
2883
2884 /* if the target bssid is different from currently associated AP,
2885 then no need to send action frame */
2886 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2887 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2888 {
2889 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2890 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002891 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002892 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002893 goto exit;
2894 }
2895
2896 /* if the channel number is different from operating channel then
2897 no need to send action frame */
2898 if (channel != pHddStaCtx->conn_info.operationChannel)
2899 {
2900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2901 "%s: channel(%d) is different from operating channel(%d)",
2902 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2903 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002904 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002905 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002906 goto exit;
2907 }
2908 chan.center_freq = sme_ChnToFreq(channel);
2909
2910 finalLen = bufLen + 24;
2911 finalBuf = vos_mem_malloc(finalLen);
2912 if (NULL == finalBuf)
2913 {
2914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2915 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002916 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002917 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002918 goto exit;
2919 }
2920 vos_mem_zero(finalBuf, finalLen);
2921
2922 /* Fill subtype */
2923 temp = SIR_MAC_MGMT_ACTION << 4;
2924 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2925
2926 /* Fill type */
2927 temp = SIR_MAC_MGMT_FRAME;
2928 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2929
2930 /* Fill destination address (bssid of the AP) */
2931 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2932
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002933 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002934 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2935
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002936 /* Fill BSSID (AP mac address) */
2937 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002938
2939 /* Fill received buffer from 24th address */
2940 vos_mem_copy(finalBuf + 24, buf, bufLen);
2941
Jeff Johnson11c33152013-04-16 17:52:40 -07002942 /* done with the parsed buffer */
2943 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002944 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002945
DARAM SUDHA39eede62014-02-12 11:16:40 +05302946 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002947#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2948 &(pAdapter->wdev),
2949#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002950 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002951#endif
2952 &chan, 0,
2953#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2954 NL80211_CHAN_HT20, 1,
2955#endif
2956 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002957 1, &cookie );
2958 vos_mem_free(finalBuf);
2959 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002960 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2961 {
2962 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2963 char extra[32];
2964 tANI_U8 len = 0;
2965
2966 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002967 len = scnprintf(extra, sizeof(extra), "%s %d",
2968 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302969 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2970 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2971 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002972 if (copy_to_user(priv_data.buf, &extra, len + 1))
2973 {
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2975 "%s: failed to copy data to user buffer", __func__);
2976 ret = -EFAULT;
2977 goto exit;
2978 }
2979 }
2980 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2981 {
2982 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002983 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002984
2985 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2986 value = value + 19;
2987 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002988 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002989 if (ret < 0)
2990 {
2991 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002992 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002994 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002995 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2996 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2997 ret = -EINVAL;
2998 goto exit;
2999 }
3000
3001 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
3002 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
3003 {
3004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3005 "lfr mode value %d is out of range"
3006 " (Min: %d Max: %d)", maxTime,
3007 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3008 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3009 ret = -EINVAL;
3010 goto exit;
3011 }
3012
3013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3014 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3015
3016 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3017 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3018 }
3019 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3020 {
3021 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3022 char extra[32];
3023 tANI_U8 len = 0;
3024
3025 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003026 len = scnprintf(extra, sizeof(extra), "%s %d",
3027 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003028 if (copy_to_user(priv_data.buf, &extra, len + 1))
3029 {
3030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3031 "%s: failed to copy data to user buffer", __func__);
3032 ret = -EFAULT;
3033 goto exit;
3034 }
3035 }
3036 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3037 {
3038 tANI_U8 *value = command;
3039 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3040
3041 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3042 value = value + 16;
3043 /* Convert the value from ascii to integer */
3044 ret = kstrtou16(value, 10, &val);
3045 if (ret < 0)
3046 {
3047 /* If the input value is greater than max value of datatype, then also
3048 kstrtou16 fails */
3049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3050 "%s: kstrtou16 failed range [%d - %d]", __func__,
3051 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3052 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3053 ret = -EINVAL;
3054 goto exit;
3055 }
3056
3057 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3058 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3059 {
3060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3061 "scan home time value %d is out of range"
3062 " (Min: %d Max: %d)", val,
3063 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3064 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3065 ret = -EINVAL;
3066 goto exit;
3067 }
3068
3069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3070 "%s: Received Command to change scan home time = %d", __func__, val);
3071
3072 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3073 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3074 }
3075 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3076 {
3077 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3078 char extra[32];
3079 tANI_U8 len = 0;
3080
3081 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003082 len = scnprintf(extra, sizeof(extra), "%s %d",
3083 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003084 if (copy_to_user(priv_data.buf, &extra, len + 1))
3085 {
3086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3087 "%s: failed to copy data to user buffer", __func__);
3088 ret = -EFAULT;
3089 goto exit;
3090 }
3091 }
3092 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3093 {
3094 tANI_U8 *value = command;
3095 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3096
3097 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3098 value = value + 17;
3099 /* Convert the value from ascii to integer */
3100 ret = kstrtou8(value, 10, &val);
3101 if (ret < 0)
3102 {
3103 /* If the input value is greater than max value of datatype, then also
3104 kstrtou8 fails */
3105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3106 "%s: kstrtou8 failed range [%d - %d]", __func__,
3107 CFG_ROAM_INTRA_BAND_MIN,
3108 CFG_ROAM_INTRA_BAND_MAX);
3109 ret = -EINVAL;
3110 goto exit;
3111 }
3112
3113 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3114 (val > CFG_ROAM_INTRA_BAND_MAX))
3115 {
3116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3117 "intra band mode value %d is out of range"
3118 " (Min: %d Max: %d)", val,
3119 CFG_ROAM_INTRA_BAND_MIN,
3120 CFG_ROAM_INTRA_BAND_MAX);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3125 "%s: Received Command to change intra band = %d", __func__, val);
3126
3127 pHddCtx->cfg_ini->nRoamIntraBand = val;
3128 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3129 }
3130 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3131 {
3132 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3133 char extra[32];
3134 tANI_U8 len = 0;
3135
3136 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003137 len = scnprintf(extra, sizeof(extra), "%s %d",
3138 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003139 if (copy_to_user(priv_data.buf, &extra, len + 1))
3140 {
3141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3142 "%s: failed to copy data to user buffer", __func__);
3143 ret = -EFAULT;
3144 goto exit;
3145 }
3146 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003147 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3148 {
3149 tANI_U8 *value = command;
3150 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3151
3152 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3153 value = value + 15;
3154 /* Convert the value from ascii to integer */
3155 ret = kstrtou8(value, 10, &nProbes);
3156 if (ret < 0)
3157 {
3158 /* If the input value is greater than max value of datatype, then also
3159 kstrtou8 fails */
3160 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3161 "%s: kstrtou8 failed range [%d - %d]", __func__,
3162 CFG_ROAM_SCAN_N_PROBES_MIN,
3163 CFG_ROAM_SCAN_N_PROBES_MAX);
3164 ret = -EINVAL;
3165 goto exit;
3166 }
3167
3168 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3169 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3170 {
3171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3172 "NProbes value %d is out of range"
3173 " (Min: %d Max: %d)", nProbes,
3174 CFG_ROAM_SCAN_N_PROBES_MIN,
3175 CFG_ROAM_SCAN_N_PROBES_MAX);
3176 ret = -EINVAL;
3177 goto exit;
3178 }
3179
3180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3181 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3182
3183 pHddCtx->cfg_ini->nProbes = nProbes;
3184 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3185 }
3186 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3187 {
3188 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3189 char extra[32];
3190 tANI_U8 len = 0;
3191
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003192 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003193 if (copy_to_user(priv_data.buf, &extra, len + 1))
3194 {
3195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3196 "%s: failed to copy data to user buffer", __func__);
3197 ret = -EFAULT;
3198 goto exit;
3199 }
3200 }
3201 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3202 {
3203 tANI_U8 *value = command;
3204 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3205
3206 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3207 /* input value is in units of msec */
3208 value = value + 20;
3209 /* Convert the value from ascii to integer */
3210 ret = kstrtou16(value, 10, &homeAwayTime);
3211 if (ret < 0)
3212 {
3213 /* If the input value is greater than max value of datatype, then also
3214 kstrtou8 fails */
3215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "%s: kstrtou8 failed range [%d - %d]", __func__,
3217 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3218 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3219 ret = -EINVAL;
3220 goto exit;
3221 }
3222
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003223 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3224 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3225 {
3226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3227 "homeAwayTime value %d is out of range"
3228 " (Min: %d Max: %d)", homeAwayTime,
3229 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3230 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3231 ret = -EINVAL;
3232 goto exit;
3233 }
3234
3235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3236 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003237 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3238 {
3239 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3240 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3241 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003242 }
3243 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3244 {
3245 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3246 char extra[32];
3247 tANI_U8 len = 0;
3248
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003249 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003250 if (copy_to_user(priv_data.buf, &extra, len + 1))
3251 {
3252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3253 "%s: failed to copy data to user buffer", __func__);
3254 ret = -EFAULT;
3255 goto exit;
3256 }
3257 }
3258 else if (strncmp(command, "REASSOC", 7) == 0)
3259 {
3260 tANI_U8 *value = command;
3261 tANI_U8 channel = 0;
3262 tSirMacAddr targetApBssid;
3263 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003264#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3265 tCsrHandoffRequest handoffInfo;
3266#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003267 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003268 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3269
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003270 /* if not associated, no need to proceed with reassoc */
3271 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3272 {
3273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3274 ret = -EINVAL;
3275 goto exit;
3276 }
3277
3278 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3279 if (eHAL_STATUS_SUCCESS != status)
3280 {
3281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "%s: Failed to parse reassoc command data", __func__);
3283 ret = -EINVAL;
3284 goto exit;
3285 }
3286
3287 /* if the target bssid is same as currently associated AP,
3288 then no need to proceed with reassoc */
3289 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3290 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3291 {
3292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3293 ret = -EINVAL;
3294 goto exit;
3295 }
3296
3297 /* Check channel number is a valid channel number */
3298 if(VOS_STATUS_SUCCESS !=
3299 wlan_hdd_validate_operation_channel(pAdapter, channel))
3300 {
3301 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003302 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003303 return -EINVAL;
3304 }
3305
3306 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003307#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3308 handoffInfo.channel = channel;
3309 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3310 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3311#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003312 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003313 else if (strncmp(command, "SETWESMODE", 10) == 0)
3314 {
3315 tANI_U8 *value = command;
3316 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3317
3318 /* Move pointer to ahead of SETWESMODE<delimiter> */
3319 value = value + 11;
3320 /* Convert the value from ascii to integer */
3321 ret = kstrtou8(value, 10, &wesMode);
3322 if (ret < 0)
3323 {
3324 /* If the input value is greater than max value of datatype, then also
3325 kstrtou8 fails */
3326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3327 "%s: kstrtou8 failed range [%d - %d]", __func__,
3328 CFG_ENABLE_WES_MODE_NAME_MIN,
3329 CFG_ENABLE_WES_MODE_NAME_MAX);
3330 ret = -EINVAL;
3331 goto exit;
3332 }
3333
3334 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3335 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3336 {
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3338 "WES Mode value %d is out of range"
3339 " (Min: %d Max: %d)", wesMode,
3340 CFG_ENABLE_WES_MODE_NAME_MIN,
3341 CFG_ENABLE_WES_MODE_NAME_MAX);
3342 ret = -EINVAL;
3343 goto exit;
3344 }
3345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3346 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3347
3348 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3349 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3350 }
3351 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3352 {
3353 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3354 char extra[32];
3355 tANI_U8 len = 0;
3356
Arif Hussain826d9412013-11-12 16:44:54 -08003357 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003358 if (copy_to_user(priv_data.buf, &extra, len + 1))
3359 {
3360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3361 "%s: failed to copy data to user buffer", __func__);
3362 ret = -EFAULT;
3363 goto exit;
3364 }
3365 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003366#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003367#ifdef FEATURE_WLAN_LFR
3368 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3369 {
3370 tANI_U8 *value = command;
3371 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3372
3373 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3374 value = value + 12;
3375 /* Convert the value from ascii to integer */
3376 ret = kstrtou8(value, 10, &lfrMode);
3377 if (ret < 0)
3378 {
3379 /* If the input value is greater than max value of datatype, then also
3380 kstrtou8 fails */
3381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3382 "%s: kstrtou8 failed range [%d - %d]", __func__,
3383 CFG_LFR_FEATURE_ENABLED_MIN,
3384 CFG_LFR_FEATURE_ENABLED_MAX);
3385 ret = -EINVAL;
3386 goto exit;
3387 }
3388
3389 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3390 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3391 {
3392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3393 "lfr mode value %d is out of range"
3394 " (Min: %d Max: %d)", lfrMode,
3395 CFG_LFR_FEATURE_ENABLED_MIN,
3396 CFG_LFR_FEATURE_ENABLED_MAX);
3397 ret = -EINVAL;
3398 goto exit;
3399 }
3400
3401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3402 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3403
3404 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3405 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3406 }
3407#endif
3408#ifdef WLAN_FEATURE_VOWIFI_11R
3409 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3410 {
3411 tANI_U8 *value = command;
3412 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3413
3414 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3415 value = value + 18;
3416 /* Convert the value from ascii to integer */
3417 ret = kstrtou8(value, 10, &ft);
3418 if (ret < 0)
3419 {
3420 /* If the input value is greater than max value of datatype, then also
3421 kstrtou8 fails */
3422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3423 "%s: kstrtou8 failed range [%d - %d]", __func__,
3424 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3425 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3426 ret = -EINVAL;
3427 goto exit;
3428 }
3429
3430 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3431 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3432 {
3433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3434 "ft mode value %d is out of range"
3435 " (Min: %d Max: %d)", ft,
3436 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3437 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3438 ret = -EINVAL;
3439 goto exit;
3440 }
3441
3442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3443 "%s: Received Command to change ft mode = %d", __func__, ft);
3444
3445 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3446 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3447 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303448
3449 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3450 {
3451 tANI_U8 *value = command;
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303452 tANI_U8 channel = 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303453 tSirMacAddr targetApBssid;
3454 tANI_U8 trigger = 0;
3455 eHalStatus status = eHAL_STATUS_SUCCESS;
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303456 tHalHandle hHal;
3457 v_U32_t roamId = 0;
3458 tCsrRoamModifyProfileFields modProfileFields;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303459 hdd_station_ctx_t *pHddStaCtx = NULL;
3460 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303461 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303462
3463 /* if not associated, no need to proceed with reassoc */
3464 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3465 {
3466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3467 ret = -EINVAL;
3468 goto exit;
3469 }
3470
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303471 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303472 if (eHAL_STATUS_SUCCESS != status)
3473 {
3474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3475 "%s: Failed to parse reassoc command data", __func__);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 /* if the target bssid is same as currently associated AP,
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303481 issue reassoc to same AP */
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303482 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3483 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3484 {
3485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3486 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3487 __func__);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303488 sme_GetModifyProfileFields(hHal, pAdapter->sessionId,
3489 &modProfileFields);
3490 sme_RoamReassoc(hHal, pAdapter->sessionId,
3491 NULL, modProfileFields, &roamId, 1);
3492 return 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303493 }
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303494 trigger = eSME_ROAM_TRIGGER_SCAN;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303495
3496 /* Proceed with scan/roam */
3497 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3498 &targetApBssid[0],
3499 (tSmeFastRoamTrigger)(trigger));
3500 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003501#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003502#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003503 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3504 {
3505 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003506 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003507
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003508 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003509 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003510 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003511 hdd_is_okc_mode_enabled(pHddCtx) &&
3512 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3513 {
3514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003515 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003516 " hence this operation is not permitted!", __func__);
3517 ret = -EPERM;
3518 goto exit;
3519 }
3520
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003521 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3522 value = value + 11;
3523 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003524 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003525 if (ret < 0)
3526 {
3527 /* If the input value is greater than max value of datatype, then also
3528 kstrtou8 fails */
3529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3530 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003531 CFG_ESE_FEATURE_ENABLED_MIN,
3532 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003533 ret = -EINVAL;
3534 goto exit;
3535 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003536 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3537 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003538 {
3539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003540 "Ese mode value %d is out of range"
3541 " (Min: %d Max: %d)", eseMode,
3542 CFG_ESE_FEATURE_ENABLED_MIN,
3543 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003544 ret = -EINVAL;
3545 goto exit;
3546 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003548 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003549
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003550 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3551 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003552 }
3553#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003554 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3555 {
3556 tANI_U8 *value = command;
3557 tANI_BOOLEAN roamScanControl = 0;
3558
3559 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3560 value = value + 19;
3561 /* Convert the value from ascii to integer */
3562 ret = kstrtou8(value, 10, &roamScanControl);
3563 if (ret < 0)
3564 {
3565 /* If the input value is greater than max value of datatype, then also
3566 kstrtou8 fails */
3567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3568 "%s: kstrtou8 failed ", __func__);
3569 ret = -EINVAL;
3570 goto exit;
3571 }
3572
3573 if (0 != roamScanControl)
3574 {
3575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3576 "roam scan control invalid value = %d",
3577 roamScanControl);
3578 ret = -EINVAL;
3579 goto exit;
3580 }
3581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3582 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3583
3584 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3585 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003586#ifdef FEATURE_WLAN_OKC
3587 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3588 {
3589 tANI_U8 *value = command;
3590 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3591
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003592 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003593 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003594 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003595 hdd_is_okc_mode_enabled(pHddCtx) &&
3596 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3597 {
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003599 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003600 " hence this operation is not permitted!", __func__);
3601 ret = -EPERM;
3602 goto exit;
3603 }
3604
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003605 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3606 value = value + 11;
3607 /* Convert the value from ascii to integer */
3608 ret = kstrtou8(value, 10, &okcMode);
3609 if (ret < 0)
3610 {
3611 /* If the input value is greater than max value of datatype, then also
3612 kstrtou8 fails */
3613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3614 "%s: kstrtou8 failed range [%d - %d]", __func__,
3615 CFG_OKC_FEATURE_ENABLED_MIN,
3616 CFG_OKC_FEATURE_ENABLED_MAX);
3617 ret = -EINVAL;
3618 goto exit;
3619 }
3620
3621 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3622 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3623 {
3624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3625 "Okc mode value %d is out of range"
3626 " (Min: %d Max: %d)", okcMode,
3627 CFG_OKC_FEATURE_ENABLED_MIN,
3628 CFG_OKC_FEATURE_ENABLED_MAX);
3629 ret = -EINVAL;
3630 goto exit;
3631 }
3632
3633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3634 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3635
3636 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3637 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003638#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003639 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3640 {
3641 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3642 char extra[32];
3643 tANI_U8 len = 0;
3644
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003645 len = scnprintf(extra, sizeof(extra), "%s %d",
3646 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003647 if (copy_to_user(priv_data.buf, &extra, len + 1))
3648 {
3649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3650 "%s: failed to copy data to user buffer", __func__);
3651 ret = -EFAULT;
3652 goto exit;
3653 }
3654 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303655#ifdef WLAN_FEATURE_PACKET_FILTERING
3656 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3657 {
3658 tANI_U8 filterType = 0;
3659 tANI_U8 *value = command;
3660
3661 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3662 value = value + 22;
3663
3664 /* Convert the value from ascii to integer */
3665 ret = kstrtou8(value, 10, &filterType);
3666 if (ret < 0)
3667 {
3668 /* If the input value is greater than max value of datatype,
3669 * then also kstrtou8 fails
3670 */
3671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3672 "%s: kstrtou8 failed range ", __func__);
3673 ret = -EINVAL;
3674 goto exit;
3675 }
3676
3677 if (filterType != 0 && filterType != 1)
3678 {
3679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3680 "%s: Accepted Values are 0 and 1 ", __func__);
3681 ret = -EINVAL;
3682 goto exit;
3683 }
3684 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3685 pAdapter->sessionId);
3686 }
3687#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303688 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3689 {
Kiet Lamad161252014-07-22 11:23:32 -07003690 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303691 int ret;
3692
Kiet Lamad161252014-07-22 11:23:32 -07003693 dhcpPhase = command + 11;
3694 if ('1' == *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 START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303698
3699 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003700
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303701 ret = wlan_hdd_scan_abort(pAdapter);
3702 if (ret < 0)
3703 {
3704 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3705 FL("failed to abort existing scan %d"), ret);
3706 }
3707
Kiet Lamad161252014-07-22 11:23:32 -07003708 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3709 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303710 }
Kiet Lamad161252014-07-22 11:23:32 -07003711 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303712 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003714 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303715
3716 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003717
3718 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3719 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303720 }
3721 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003722 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3723 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3725 FL("making default scan to ACTIVE"));
3726 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003727 }
3728 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3729 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3731 FL("making default scan to PASSIVE"));
3732 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003733 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303734 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3735 {
3736 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3737 char extra[32];
3738 tANI_U8 len = 0;
3739
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303740 memset(extra, 0, sizeof(extra));
3741 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3742 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303743 {
3744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3745 "%s: failed to copy data to user buffer", __func__);
3746 ret = -EFAULT;
3747 goto exit;
3748 }
3749 ret = len;
3750 }
3751 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3752 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303753 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303754 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003755 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3756 {
3757 tANI_U8 filterType = 0;
3758 tANI_U8 *value;
3759 value = command + 9;
3760
3761 /* Convert the value from ascii to integer */
3762 ret = kstrtou8(value, 10, &filterType);
3763 if (ret < 0)
3764 {
3765 /* If the input value is greater than max value of datatype,
3766 * then also kstrtou8 fails
3767 */
3768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3769 "%s: kstrtou8 failed range ", __func__);
3770 ret = -EINVAL;
3771 goto exit;
3772 }
3773 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3774 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3775 {
3776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3777 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3778 " 2-Sink ", __func__);
3779 ret = -EINVAL;
3780 goto exit;
3781 }
3782 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3783 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303784 pScanInfo = &pHddCtx->scan_info;
3785 if (filterType && pScanInfo != NULL &&
3786 pHddCtx->scan_info.mScanPending)
3787 {
3788 /*Miracast Session started. Abort Scan */
3789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3790 "%s, Aborting Scan For Miracast",__func__);
3791 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
3792 eCSR_SCAN_ABORT_DEFAULT);
3793 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003794 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303795 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003796 }
Leo Chang614d2072013-08-22 14:59:44 -07003797 else if (strncmp(command, "SETMCRATE", 9) == 0)
3798 {
Leo Chang614d2072013-08-22 14:59:44 -07003799 tANI_U8 *value = command;
3800 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003801 tSirRateUpdateInd *rateUpdate;
3802 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003803
3804 /* Only valid for SAP mode */
3805 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3806 {
3807 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3808 "%s: SAP mode is not running", __func__);
3809 ret = -EFAULT;
3810 goto exit;
3811 }
3812
3813 /* Move pointer to ahead of SETMCRATE<delimiter> */
3814 /* input value is in units of hundred kbps */
3815 value = value + 10;
3816 /* Convert the value from ascii to integer, decimal base */
3817 ret = kstrtouint(value, 10, &targetRate);
3818
Leo Chang1f98cbd2013-10-17 15:03:52 -07003819 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3820 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003821 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003822 hddLog(VOS_TRACE_LEVEL_ERROR,
3823 "%s: SETMCRATE indication alloc fail", __func__);
3824 ret = -EFAULT;
3825 goto exit;
3826 }
3827 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3828
3829 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3830 "MC Target rate %d", targetRate);
3831 /* Ignore unicast */
3832 rateUpdate->ucastDataRate = -1;
3833 rateUpdate->mcastDataRate24GHz = targetRate;
3834 rateUpdate->mcastDataRate5GHz = targetRate;
3835 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3836 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3837 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3838 if (eHAL_STATUS_SUCCESS != status)
3839 {
3840 hddLog(VOS_TRACE_LEVEL_ERROR,
3841 "%s: SET_MC_RATE failed", __func__);
3842 vos_mem_free(rateUpdate);
3843 ret = -EFAULT;
3844 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003845 }
3846 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303847#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003848 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303849 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003850 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303851 }
3852#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003853#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003854 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3855 {
3856 tANI_U8 *value = command;
3857 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3858 tANI_U8 numChannels = 0;
3859 eHalStatus status = eHAL_STATUS_SUCCESS;
3860
3861 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3862 if (eHAL_STATUS_SUCCESS != status)
3863 {
3864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3865 "%s: Failed to parse channel list information", __func__);
3866 ret = -EINVAL;
3867 goto exit;
3868 }
3869
3870 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3871 {
3872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3873 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3874 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3875 ret = -EINVAL;
3876 goto exit;
3877 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003878 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003879 ChannelList,
3880 numChannels);
3881 if (eHAL_STATUS_SUCCESS != status)
3882 {
3883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3884 "%s: Failed to update channel list information", __func__);
3885 ret = -EINVAL;
3886 goto exit;
3887 }
3888 }
3889 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3890 {
3891 tANI_U8 *value = command;
3892 char extra[128] = {0};
3893 int len = 0;
3894 tANI_U8 tid = 0;
3895 hdd_station_ctx_t *pHddStaCtx = NULL;
3896 tAniTrafStrmMetrics tsmMetrics;
3897 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3898
3899 /* if not associated, return error */
3900 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3901 {
3902 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3903 ret = -EINVAL;
3904 goto exit;
3905 }
3906
3907 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3908 value = value + 12;
3909 /* Convert the value from ascii to integer */
3910 ret = kstrtou8(value, 10, &tid);
3911 if (ret < 0)
3912 {
3913 /* If the input value is greater than max value of datatype, then also
3914 kstrtou8 fails */
3915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3916 "%s: kstrtou8 failed range [%d - %d]", __func__,
3917 TID_MIN_VALUE,
3918 TID_MAX_VALUE);
3919 ret = -EINVAL;
3920 goto exit;
3921 }
3922
3923 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3924 {
3925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3926 "tid value %d is out of range"
3927 " (Min: %d Max: %d)", tid,
3928 TID_MIN_VALUE,
3929 TID_MAX_VALUE);
3930 ret = -EINVAL;
3931 goto exit;
3932 }
3933
3934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3935 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3936
3937 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3938 {
3939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3940 "%s: failed to get tsm stats", __func__);
3941 ret = -EFAULT;
3942 goto exit;
3943 }
3944
3945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3946 "UplinkPktQueueDly(%d)\n"
3947 "UplinkPktQueueDlyHist[0](%d)\n"
3948 "UplinkPktQueueDlyHist[1](%d)\n"
3949 "UplinkPktQueueDlyHist[2](%d)\n"
3950 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303951 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003952 "UplinkPktLoss(%d)\n"
3953 "UplinkPktCount(%d)\n"
3954 "RoamingCount(%d)\n"
3955 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3956 tsmMetrics.UplinkPktQueueDlyHist[0],
3957 tsmMetrics.UplinkPktQueueDlyHist[1],
3958 tsmMetrics.UplinkPktQueueDlyHist[2],
3959 tsmMetrics.UplinkPktQueueDlyHist[3],
3960 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3961 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3962
3963 /* Output TSM stats is of the format
3964 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3965 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003966 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003967 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3968 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3969 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3970 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3971 tsmMetrics.RoamingDly);
3972
3973 if (copy_to_user(priv_data.buf, &extra, len + 1))
3974 {
3975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3976 "%s: failed to copy data to user buffer", __func__);
3977 ret = -EFAULT;
3978 goto exit;
3979 }
3980 }
3981 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3982 {
3983 tANI_U8 *value = command;
3984 tANI_U8 *cckmIe = NULL;
3985 tANI_U8 cckmIeLen = 0;
3986 eHalStatus status = eHAL_STATUS_SUCCESS;
3987
3988 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3989 if (eHAL_STATUS_SUCCESS != status)
3990 {
3991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3992 "%s: Failed to parse cckm ie data", __func__);
3993 ret = -EINVAL;
3994 goto exit;
3995 }
3996
3997 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3998 {
3999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4000 "%s: CCKM Ie input length is more than max[%d]", __func__,
4001 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004002 vos_mem_free(cckmIe);
4003 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004004 ret = -EINVAL;
4005 goto exit;
4006 }
4007 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004008 vos_mem_free(cckmIe);
4009 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004010 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004011 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
4012 {
4013 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004014 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004015 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004016
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004017 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004018 if (eHAL_STATUS_SUCCESS != status)
4019 {
4020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004021 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004022 ret = -EINVAL;
4023 goto exit;
4024 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004025 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4026 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4027 hdd_indicateEseBcnReportNoResults (pAdapter,
4028 eseBcnReq.bcnReq[0].measurementToken,
4029 0x02, //BIT(1) set for measurement done
4030 0); // no BSS
4031 goto exit;
4032 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004033
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004034 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4035 if (eHAL_STATUS_SUCCESS != status)
4036 {
4037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4038 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4039 ret = -EINVAL;
4040 goto exit;
4041 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004042 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004043#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304044 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4045 {
4046 eHalStatus status;
4047 char buf[32], len;
4048 long waitRet;
4049 bcnMissRateContext_t getBcnMissRateCtx;
4050
4051 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4052
4053 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4054 {
4055 hddLog(VOS_TRACE_LEVEL_WARN,
4056 FL("GETBCNMISSRATE: STA is not in connected state"));
4057 ret = -1;
4058 goto exit;
4059 }
4060
4061 init_completion(&(getBcnMissRateCtx.completion));
4062 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4063
4064 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4065 pAdapter->sessionId,
4066 (void *)getBcnMissRateCB,
4067 (void *)(&getBcnMissRateCtx));
4068 if( eHAL_STATUS_SUCCESS != status)
4069 {
4070 hddLog(VOS_TRACE_LEVEL_INFO,
4071 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4072 ret = -EINVAL;
4073 goto exit;
4074 }
4075
4076 waitRet = wait_for_completion_interruptible_timeout
4077 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4078 if(waitRet <= 0)
4079 {
4080 hddLog(VOS_TRACE_LEVEL_ERROR,
4081 FL("failed to wait on bcnMissRateComp %d"), ret);
4082
4083 //Make magic number to zero so that callback is not called.
4084 spin_lock(&hdd_context_lock);
4085 getBcnMissRateCtx.magic = 0x0;
4086 spin_unlock(&hdd_context_lock);
4087 ret = -EINVAL;
4088 goto exit;
4089 }
4090
4091 hddLog(VOS_TRACE_LEVEL_INFO,
4092 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4093
4094 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4095 if (copy_to_user(priv_data.buf, &buf, len + 1))
4096 {
4097 hddLog(VOS_TRACE_LEVEL_ERROR,
4098 "%s: failed to copy data to user buffer", __func__);
4099 ret = -EFAULT;
4100 goto exit;
4101 }
4102 ret = len;
4103 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304104#ifdef FEATURE_WLAN_TDLS
4105 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4106 tANI_U8 *value = command;
4107 int set_value;
4108 /* Move pointer to ahead of TDLSOFFCH*/
4109 value += 26;
4110 sscanf(value, "%d", &set_value);
4111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4112 "%s: Tdls offchannel offset:%d",
4113 __func__, set_value);
4114 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4115 if (ret < 0)
4116 {
4117 ret = -EINVAL;
4118 goto exit;
4119 }
4120
4121 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4122 tANI_U8 *value = command;
4123 int set_value;
4124 /* Move pointer to ahead of tdlsoffchnmode*/
4125 value += 18;
4126 sscanf(value, "%d", &set_value);
4127 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4128 "%s: Tdls offchannel mode:%d",
4129 __func__, set_value);
4130 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4131 if (ret < 0)
4132 {
4133 ret = -EINVAL;
4134 goto exit;
4135 }
4136 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4137 tANI_U8 *value = command;
4138 int set_value;
4139 /* Move pointer to ahead of TDLSOFFCH*/
4140 value += 14;
4141 sscanf(value, "%d", &set_value);
4142 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4143 "%s: Tdls offchannel num: %d",
4144 __func__, set_value);
4145 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4146 if (ret < 0)
4147 {
4148 ret = -EINVAL;
4149 goto exit;
4150 }
4151 }
4152#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004153 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304154 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4155 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4156 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004157 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4158 __func__, command);
4159 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004160 }
4161exit:
4162 if (command)
4163 {
4164 kfree(command);
4165 }
4166 return ret;
4167}
4168
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004169#ifdef CONFIG_COMPAT
4170static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4171{
4172 struct {
4173 compat_uptr_t buf;
4174 int used_len;
4175 int total_len;
4176 } compat_priv_data;
4177 hdd_priv_data_t priv_data;
4178 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004179
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004180 /*
4181 * Note that pAdapter and ifr have already been verified by caller,
4182 * and HDD context has also been validated
4183 */
4184 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4185 sizeof(compat_priv_data))) {
4186 ret = -EFAULT;
4187 goto exit;
4188 }
4189 priv_data.buf = compat_ptr(compat_priv_data.buf);
4190 priv_data.used_len = compat_priv_data.used_len;
4191 priv_data.total_len = compat_priv_data.total_len;
4192 ret = hdd_driver_command(pAdapter, &priv_data);
4193 exit:
4194 return ret;
4195}
4196#else /* CONFIG_COMPAT */
4197static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4198{
4199 /* will never be invoked */
4200 return 0;
4201}
4202#endif /* CONFIG_COMPAT */
4203
4204static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4205{
4206 hdd_priv_data_t priv_data;
4207 int ret = 0;
4208
4209 /*
4210 * Note that pAdapter and ifr have already been verified by caller,
4211 * and HDD context has also been validated
4212 */
4213 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4214 ret = -EFAULT;
4215 } else {
4216 ret = hdd_driver_command(pAdapter, &priv_data);
4217 }
4218 return ret;
4219}
4220
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304221int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004222{
4223 hdd_adapter_t *pAdapter;
4224 hdd_context_t *pHddCtx;
4225 int ret;
4226
4227 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4228 if (NULL == pAdapter) {
4229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4230 "%s: HDD adapter context is Null", __func__);
4231 ret = -ENODEV;
4232 goto exit;
4233 }
4234 if (dev != pAdapter->dev) {
4235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4236 "%s: HDD adapter/dev inconsistency", __func__);
4237 ret = -ENODEV;
4238 goto exit;
4239 }
4240
4241 if ((!ifr) || (!ifr->ifr_data)) {
4242 ret = -EINVAL;
4243 goto exit;
4244 }
4245
4246 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4247 ret = wlan_hdd_validate_context(pHddCtx);
4248 if (ret) {
Mahesh A Saptasagar5b16d0a2014-11-03 17:55:29 +05304249 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004250 "%s: invalid context", __func__);
4251 ret = -EBUSY;
4252 goto exit;
4253 }
4254
4255 switch (cmd) {
4256 case (SIOCDEVPRIVATE + 1):
4257 if (is_compat_task())
4258 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4259 else
4260 ret = hdd_driver_ioctl(pAdapter, ifr);
4261 break;
4262 default:
4263 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4264 __func__, cmd);
4265 ret = -EINVAL;
4266 break;
4267 }
4268 exit:
4269 return ret;
4270}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004271
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304272int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4273{
4274 int ret;
4275
4276 vos_ssr_protect(__func__);
4277 ret = __hdd_ioctl(dev, ifr, cmd);
4278 vos_ssr_unprotect(__func__);
4279
4280 return ret;
4281}
4282
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004283#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004284/**---------------------------------------------------------------------------
4285
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004286 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004287
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004288 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004289 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4290 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4291 <space>Scan Mode N<space>Meas Duration N
4292 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4293 then take N.
4294 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4295 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4296 This function does not take care of removing duplicate channels from the list
4297
4298 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004299 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004300
4301 \return - 0 for success non-zero for failure
4302
4303 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004304static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4305 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004306{
4307 tANI_U8 *inPtr = pValue;
4308 int tempInt = 0;
4309 int j = 0, i = 0, v = 0;
4310 char buf[32];
4311
4312 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4313 /*no argument after the command*/
4314 if (NULL == inPtr)
4315 {
4316 return -EINVAL;
4317 }
4318 /*no space after the command*/
4319 else if (SPACE_ASCII_VALUE != *inPtr)
4320 {
4321 return -EINVAL;
4322 }
4323
4324 /*removing empty spaces*/
4325 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4326
4327 /*no argument followed by spaces*/
4328 if ('\0' == *inPtr) return -EINVAL;
4329
4330 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004331 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004332 if (1 != v) return -EINVAL;
4333
4334 v = kstrtos32(buf, 10, &tempInt);
4335 if ( v < 0) return -EINVAL;
4336
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004337 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004338
4339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004340 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004341
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004342 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004343 {
4344 for (i = 0; i < 4; i++)
4345 {
4346 /*inPtr pointing to the beginning of first space after number of ie fields*/
4347 inPtr = strpbrk( inPtr, " " );
4348 /*no ie data after the number of ie fields argument*/
4349 if (NULL == inPtr) return -EINVAL;
4350
4351 /*removing empty space*/
4352 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4353
4354 /*no ie data after the number of ie fields argument and spaces*/
4355 if ( '\0' == *inPtr ) return -EINVAL;
4356
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004357 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004358 if (1 != v) return -EINVAL;
4359
4360 v = kstrtos32(buf, 10, &tempInt);
4361 if (v < 0) return -EINVAL;
4362
4363 switch (i)
4364 {
4365 case 0: /* Measurement token */
4366 if (tempInt <= 0)
4367 {
4368 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4369 "Invalid Measurement Token(%d)", tempInt);
4370 return -EINVAL;
4371 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004372 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004373 break;
4374
4375 case 1: /* Channel number */
4376 if ((tempInt <= 0) ||
4377 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4378 {
4379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4380 "Invalid Channel Number(%d)", tempInt);
4381 return -EINVAL;
4382 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004383 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004384 break;
4385
4386 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004387 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004388 {
4389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4390 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4391 return -EINVAL;
4392 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004393 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004394 break;
4395
4396 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004397 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4398 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004399 {
4400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4401 "Invalid Measurement Duration(%d)", tempInt);
4402 return -EINVAL;
4403 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004404 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004405 break;
4406 }
4407 }
4408 }
4409
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004410 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004411 {
4412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304413 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004414 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004415 pEseBcnReq->bcnReq[j].measurementToken,
4416 pEseBcnReq->bcnReq[j].channel,
4417 pEseBcnReq->bcnReq[j].scanMode,
4418 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004419 }
4420
4421 return VOS_STATUS_SUCCESS;
4422}
4423
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004424static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4425{
4426 struct statsContext *pStatsContext = NULL;
4427 hdd_adapter_t *pAdapter = NULL;
4428
4429 if (NULL == pContext)
4430 {
4431 hddLog(VOS_TRACE_LEVEL_ERROR,
4432 "%s: Bad param, pContext [%p]",
4433 __func__, pContext);
4434 return;
4435 }
4436
Jeff Johnson72a40512013-12-19 10:14:15 -08004437 /* there is a race condition that exists between this callback
4438 function and the caller since the caller could time out either
4439 before or while this code is executing. we use a spinlock to
4440 serialize these actions */
4441 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004442
4443 pStatsContext = pContext;
4444 pAdapter = pStatsContext->pAdapter;
4445 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4446 {
4447 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004448 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004449 hddLog(VOS_TRACE_LEVEL_WARN,
4450 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4451 __func__, pAdapter, pStatsContext->magic);
4452 return;
4453 }
4454
Jeff Johnson72a40512013-12-19 10:14:15 -08004455 /* context is valid so caller is still waiting */
4456
4457 /* paranoia: invalidate the magic */
4458 pStatsContext->magic = 0;
4459
4460 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004461 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4462 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4463 tsmMetrics.UplinkPktQueueDlyHist,
4464 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4465 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4466 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4467 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4468 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4469 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4470 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4471
Jeff Johnson72a40512013-12-19 10:14:15 -08004472 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004473 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004474
4475 /* serialization is complete */
4476 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004477}
4478
4479
4480
4481static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4482 tAniTrafStrmMetrics* pTsmMetrics)
4483{
4484 hdd_station_ctx_t *pHddStaCtx = NULL;
4485 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004486 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004487 long lrc;
4488 struct statsContext context;
4489 hdd_context_t *pHddCtx = NULL;
4490
4491 if (NULL == pAdapter)
4492 {
4493 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4494 return VOS_STATUS_E_FAULT;
4495 }
4496
4497 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4498 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4499
4500 /* we are connected prepare our callback context */
4501 init_completion(&context.completion);
4502 context.pAdapter = pAdapter;
4503 context.magic = STATS_CONTEXT_MAGIC;
4504
4505 /* query tsm stats */
4506 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4507 pHddStaCtx->conn_info.staId[ 0 ],
4508 pHddStaCtx->conn_info.bssId,
4509 &context, pHddCtx->pvosContext, tid);
4510
4511 if (eHAL_STATUS_SUCCESS != hstatus)
4512 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004513 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4514 __func__);
4515 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004516 }
4517 else
4518 {
4519 /* request was sent -- wait for the response */
4520 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4521 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004522 if (lrc <= 0)
4523 {
4524 hddLog(VOS_TRACE_LEVEL_ERROR,
4525 "%s: SME %s while retrieving statistics",
4526 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004527 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004528 }
4529 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004530
Jeff Johnson72a40512013-12-19 10:14:15 -08004531 /* either we never sent a request, we sent a request and received a
4532 response or we sent a request and timed out. if we never sent a
4533 request or if we sent a request and got a response, we want to
4534 clear the magic out of paranoia. if we timed out there is a
4535 race condition such that the callback function could be
4536 executing at the same time we are. of primary concern is if the
4537 callback function had already verified the "magic" but had not
4538 yet set the completion variable when a timeout occurred. we
4539 serialize these activities by invalidating the magic while
4540 holding a shared spinlock which will cause us to block if the
4541 callback is currently executing */
4542 spin_lock(&hdd_context_lock);
4543 context.magic = 0;
4544 spin_unlock(&hdd_context_lock);
4545
4546 if (VOS_STATUS_SUCCESS == vstatus)
4547 {
4548 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4549 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4550 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4551 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4552 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4553 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4554 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4555 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4556 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4557 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4558 }
4559 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004560}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004561#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004562
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004563#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004564void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4565{
4566 eCsrBand band = -1;
4567 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4568 switch (band)
4569 {
4570 case eCSR_BAND_ALL:
4571 *pBand = WLAN_HDD_UI_BAND_AUTO;
4572 break;
4573
4574 case eCSR_BAND_24:
4575 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4576 break;
4577
4578 case eCSR_BAND_5G:
4579 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4580 break;
4581
4582 default:
4583 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4584 *pBand = -1;
4585 break;
4586 }
4587}
4588
4589/**---------------------------------------------------------------------------
4590
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004591 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4592
4593 This function parses the send action frame data passed in the format
4594 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4595
Srinivas Girigowda56076852013-08-20 14:00:50 -07004596 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004597 \param - pTargetApBssid Pointer to target Ap bssid
4598 \param - pChannel Pointer to the Target AP channel
4599 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4600 \param - pBuf Pointer to data
4601 \param - pBufLen Pointer to data length
4602
4603 \return - 0 for success non-zero for failure
4604
4605 --------------------------------------------------------------------------*/
4606VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4607 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4608{
4609 tANI_U8 *inPtr = pValue;
4610 tANI_U8 *dataEnd;
4611 int tempInt;
4612 int j = 0;
4613 int i = 0;
4614 int v = 0;
4615 tANI_U8 tempBuf[32];
4616 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004617 /* 12 hexa decimal digits, 5 ':' and '\0' */
4618 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004619
4620 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4621 /*no argument after the command*/
4622 if (NULL == inPtr)
4623 {
4624 return -EINVAL;
4625 }
4626
4627 /*no space after the command*/
4628 else if (SPACE_ASCII_VALUE != *inPtr)
4629 {
4630 return -EINVAL;
4631 }
4632
4633 /*removing empty spaces*/
4634 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4635
4636 /*no argument followed by spaces*/
4637 if ('\0' == *inPtr)
4638 {
4639 return -EINVAL;
4640 }
4641
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004642 v = sscanf(inPtr, "%17s", macAddress);
4643 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004644 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4646 "Invalid MAC address or All hex inputs are not read (%d)", v);
4647 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004648 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004649
4650 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4651 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4652 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4653 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4654 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4655 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004656
4657 /* point to the next argument */
4658 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4659 /*no argument after the command*/
4660 if (NULL == inPtr) return -EINVAL;
4661
4662 /*removing empty spaces*/
4663 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4664
4665 /*no argument followed by spaces*/
4666 if ('\0' == *inPtr)
4667 {
4668 return -EINVAL;
4669 }
4670
4671 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004672 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004673 if (1 != v) return -EINVAL;
4674
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004675 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304676 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304677 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004678
4679 *pChannel = tempInt;
4680
4681 /* point to the next argument */
4682 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4683 /*no argument after the command*/
4684 if (NULL == inPtr) return -EINVAL;
4685 /*removing empty spaces*/
4686 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4687
4688 /*no argument followed by spaces*/
4689 if ('\0' == *inPtr)
4690 {
4691 return -EINVAL;
4692 }
4693
4694 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004695 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004696 if (1 != v) return -EINVAL;
4697
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004698 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004699 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004700
4701 *pDwellTime = tempInt;
4702
4703 /* point to the next argument */
4704 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4705 /*no argument after the command*/
4706 if (NULL == inPtr) return -EINVAL;
4707 /*removing empty spaces*/
4708 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4709
4710 /*no argument followed by spaces*/
4711 if ('\0' == *inPtr)
4712 {
4713 return -EINVAL;
4714 }
4715
4716 /* find the length of data */
4717 dataEnd = inPtr;
4718 while(('\0' != *dataEnd) )
4719 {
4720 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004721 }
Kiet Lambe150c22013-11-21 16:30:32 +05304722 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004723 if ( *pBufLen <= 0) return -EINVAL;
4724
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004725 /* Allocate the number of bytes based on the number of input characters
4726 whether it is even or odd.
4727 if the number of input characters are even, then we need N/2 byte.
4728 if the number of input characters are odd, then we need do (N+1)/2 to
4729 compensate rounding off.
4730 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4731 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4732 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004733 if (NULL == *pBuf)
4734 {
4735 hddLog(VOS_TRACE_LEVEL_FATAL,
4736 "%s: vos_mem_alloc failed ", __func__);
4737 return -EINVAL;
4738 }
4739
4740 /* the buffer received from the upper layer is character buffer,
4741 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4742 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4743 and f0 in 3rd location */
4744 for (i = 0, j = 0; j < *pBufLen; j += 2)
4745 {
Kiet Lambe150c22013-11-21 16:30:32 +05304746 if( j+1 == *pBufLen)
4747 {
4748 tempByte = hdd_parse_hex(inPtr[j]);
4749 }
4750 else
4751 {
4752 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4753 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004754 (*pBuf)[i++] = tempByte;
4755 }
4756 *pBufLen = i;
4757 return VOS_STATUS_SUCCESS;
4758}
4759
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004760/**---------------------------------------------------------------------------
4761
Srinivas Girigowdade697412013-02-14 16:31:48 -08004762 \brief hdd_parse_channellist() - HDD Parse channel list
4763
4764 This function parses the channel list passed in the format
4765 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004766 if the Number of channels (N) does not match with the actual number of channels passed
4767 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4768 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4769 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4770 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004771
4772 \param - pValue Pointer to input channel list
4773 \param - ChannelList Pointer to local output array to record channel list
4774 \param - pNumChannels Pointer to number of roam scan channels
4775
4776 \return - 0 for success non-zero for failure
4777
4778 --------------------------------------------------------------------------*/
4779VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4780{
4781 tANI_U8 *inPtr = pValue;
4782 int tempInt;
4783 int j = 0;
4784 int v = 0;
4785 char buf[32];
4786
4787 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4788 /*no argument after the command*/
4789 if (NULL == inPtr)
4790 {
4791 return -EINVAL;
4792 }
4793
4794 /*no space after the command*/
4795 else if (SPACE_ASCII_VALUE != *inPtr)
4796 {
4797 return -EINVAL;
4798 }
4799
4800 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004801 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004802
4803 /*no argument followed by spaces*/
4804 if ('\0' == *inPtr)
4805 {
4806 return -EINVAL;
4807 }
4808
4809 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004810 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004811 if (1 != v) return -EINVAL;
4812
Srinivas Girigowdade697412013-02-14 16:31:48 -08004813 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004814 if ((v < 0) ||
4815 (tempInt <= 0) ||
4816 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4817 {
4818 return -EINVAL;
4819 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004820
4821 *pNumChannels = tempInt;
4822
4823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4824 "Number of channels are: %d", *pNumChannels);
4825
4826 for (j = 0; j < (*pNumChannels); j++)
4827 {
4828 /*inPtr pointing to the beginning of first space after number of channels*/
4829 inPtr = strpbrk( inPtr, " " );
4830 /*no channel list after the number of channels argument*/
4831 if (NULL == inPtr)
4832 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004833 if (0 != j)
4834 {
4835 *pNumChannels = j;
4836 return VOS_STATUS_SUCCESS;
4837 }
4838 else
4839 {
4840 return -EINVAL;
4841 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004842 }
4843
4844 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004845 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004846
4847 /*no channel list after the number of channels argument and spaces*/
4848 if ( '\0' == *inPtr )
4849 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004850 if (0 != j)
4851 {
4852 *pNumChannels = j;
4853 return VOS_STATUS_SUCCESS;
4854 }
4855 else
4856 {
4857 return -EINVAL;
4858 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004859 }
4860
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004861 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004862 if (1 != v) return -EINVAL;
4863
Srinivas Girigowdade697412013-02-14 16:31:48 -08004864 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004865 if ((v < 0) ||
4866 (tempInt <= 0) ||
4867 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4868 {
4869 return -EINVAL;
4870 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004871 pChannelList[j] = tempInt;
4872
4873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4874 "Channel %d added to preferred channel list",
4875 pChannelList[j] );
4876 }
4877
Srinivas Girigowdade697412013-02-14 16:31:48 -08004878 return VOS_STATUS_SUCCESS;
4879}
4880
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004881
4882/**---------------------------------------------------------------------------
4883
4884 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4885
4886 This function parses the reasoc command data passed in the format
4887 REASSOC<space><bssid><space><channel>
4888
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004889 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004890 \param - pTargetApBssid Pointer to target Ap bssid
4891 \param - pChannel Pointer to the Target AP channel
4892
4893 \return - 0 for success non-zero for failure
4894
4895 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004896VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4897 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004898{
4899 tANI_U8 *inPtr = pValue;
4900 int tempInt;
4901 int v = 0;
4902 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004903 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004904 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004905
4906 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4907 /*no argument after the command*/
4908 if (NULL == inPtr)
4909 {
4910 return -EINVAL;
4911 }
4912
4913 /*no space after the command*/
4914 else if (SPACE_ASCII_VALUE != *inPtr)
4915 {
4916 return -EINVAL;
4917 }
4918
4919 /*removing empty spaces*/
4920 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4921
4922 /*no argument followed by spaces*/
4923 if ('\0' == *inPtr)
4924 {
4925 return -EINVAL;
4926 }
4927
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004928 v = sscanf(inPtr, "%17s", macAddress);
4929 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004930 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4932 "Invalid MAC address or All hex inputs are not read (%d)", v);
4933 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004934 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004935
4936 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4937 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4938 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4939 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4940 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4941 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004942
4943 /* point to the next argument */
4944 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4945 /*no argument after the command*/
4946 if (NULL == inPtr) return -EINVAL;
4947
4948 /*removing empty spaces*/
4949 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4950
4951 /*no argument followed by spaces*/
4952 if ('\0' == *inPtr)
4953 {
4954 return -EINVAL;
4955 }
4956
4957 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004958 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004959 if (1 != v) return -EINVAL;
4960
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004961 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004962 if ((v < 0) ||
4963 (tempInt <= 0) ||
4964 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4965 {
4966 return -EINVAL;
4967 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004968
4969 *pChannel = tempInt;
4970 return VOS_STATUS_SUCCESS;
4971}
4972
4973#endif
4974
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004975#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004976/**---------------------------------------------------------------------------
4977
4978 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4979
4980 This function parses the SETCCKM IE command
4981 SETCCKMIE<space><ie data>
4982
4983 \param - pValue Pointer to input data
4984 \param - pCckmIe Pointer to output cckm Ie
4985 \param - pCckmIeLen Pointer to output cckm ie length
4986
4987 \return - 0 for success non-zero for failure
4988
4989 --------------------------------------------------------------------------*/
4990VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4991 tANI_U8 *pCckmIeLen)
4992{
4993 tANI_U8 *inPtr = pValue;
4994 tANI_U8 *dataEnd;
4995 int j = 0;
4996 int i = 0;
4997 tANI_U8 tempByte = 0;
4998
4999 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
5000 /*no argument after the command*/
5001 if (NULL == inPtr)
5002 {
5003 return -EINVAL;
5004 }
5005
5006 /*no space after the command*/
5007 else if (SPACE_ASCII_VALUE != *inPtr)
5008 {
5009 return -EINVAL;
5010 }
5011
5012 /*removing empty spaces*/
5013 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5014
5015 /*no argument followed by spaces*/
5016 if ('\0' == *inPtr)
5017 {
5018 return -EINVAL;
5019 }
5020
5021 /* find the length of data */
5022 dataEnd = inPtr;
5023 while(('\0' != *dataEnd) )
5024 {
5025 dataEnd++;
5026 ++(*pCckmIeLen);
5027 }
5028 if ( *pCckmIeLen <= 0) return -EINVAL;
5029
5030 /* Allocate the number of bytes based on the number of input characters
5031 whether it is even or odd.
5032 if the number of input characters are even, then we need N/2 byte.
5033 if the number of input characters are odd, then we need do (N+1)/2 to
5034 compensate rounding off.
5035 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5036 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5037 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5038 if (NULL == *pCckmIe)
5039 {
5040 hddLog(VOS_TRACE_LEVEL_FATAL,
5041 "%s: vos_mem_alloc failed ", __func__);
5042 return -EINVAL;
5043 }
5044 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5045 /* the buffer received from the upper layer is character buffer,
5046 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5047 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5048 and f0 in 3rd location */
5049 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5050 {
5051 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5052 (*pCckmIe)[i++] = tempByte;
5053 }
5054 *pCckmIeLen = i;
5055
5056 return VOS_STATUS_SUCCESS;
5057}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005058#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005059
Jeff Johnson295189b2012-06-20 16:38:30 -07005060/**---------------------------------------------------------------------------
5061
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005062 \brief hdd_is_valid_mac_address() - Validate MAC address
5063
5064 This function validates whether the given MAC address is valid or not
5065 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5066 where X is the hexa decimal digit character and separated by ':'
5067 This algorithm works even if MAC address is not separated by ':'
5068
5069 This code checks given input string mac contains exactly 12 hexadecimal digits.
5070 and a separator colon : appears in the input string only after
5071 an even number of hex digits.
5072
5073 \param - pMacAddr pointer to the input MAC address
5074 \return - 1 for valid and 0 for invalid
5075
5076 --------------------------------------------------------------------------*/
5077
5078v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5079{
5080 int xdigit = 0;
5081 int separator = 0;
5082 while (*pMacAddr)
5083 {
5084 if (isxdigit(*pMacAddr))
5085 {
5086 xdigit++;
5087 }
5088 else if (':' == *pMacAddr)
5089 {
5090 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5091 break;
5092
5093 ++separator;
5094 }
5095 else
5096 {
5097 separator = -1;
5098 /* Invalid MAC found */
5099 return 0;
5100 }
5101 ++pMacAddr;
5102 }
5103 return (xdigit == 12 && (separator == 5 || separator == 0));
5104}
5105
5106/**---------------------------------------------------------------------------
5107
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305108 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005109
5110 \param - dev Pointer to net_device structure
5111
5112 \return - 0 for success non-zero for failure
5113
5114 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305115int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005116{
5117 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5118 hdd_context_t *pHddCtx;
5119 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5120 VOS_STATUS status;
5121 v_BOOL_t in_standby = TRUE;
5122
5123 if (NULL == pAdapter)
5124 {
5125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305126 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005127 return -ENODEV;
5128 }
5129
5130 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305131 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5132 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 if (NULL == pHddCtx)
5134 {
5135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005136 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 return -ENODEV;
5138 }
5139
5140 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5141 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5142 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005143 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5144 {
5145 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305146 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005147 in_standby = FALSE;
5148 break;
5149 }
5150 else
5151 {
5152 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5153 pAdapterNode = pNext;
5154 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005155 }
5156
5157 if (TRUE == in_standby)
5158 {
5159 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5160 {
5161 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5162 "wlan out of power save", __func__);
5163 return -EINVAL;
5164 }
5165 }
5166
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005167 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005168 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5169 {
5170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005171 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005172 /* Enable TX queues only when we are connected */
5173 netif_tx_start_all_queues(dev);
5174 }
5175
5176 return 0;
5177}
5178
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305179/**---------------------------------------------------------------------------
5180
5181 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5182
5183 This is called in response to ifconfig up
5184
5185 \param - dev Pointer to net_device structure
5186
5187 \return - 0 for success non-zero for failure
5188
5189 --------------------------------------------------------------------------*/
5190int hdd_open(struct net_device *dev)
5191{
5192 int ret;
5193
5194 vos_ssr_protect(__func__);
5195 ret = __hdd_open(dev);
5196 vos_ssr_unprotect(__func__);
5197
5198 return ret;
5199}
5200
Jeff Johnson295189b2012-06-20 16:38:30 -07005201int hdd_mon_open (struct net_device *dev)
5202{
5203 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5204
5205 if(pAdapter == NULL) {
5206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005207 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005208 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 }
5210
5211 netif_start_queue(dev);
5212
5213 return 0;
5214}
5215/**---------------------------------------------------------------------------
5216
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305217 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005218
5219 \param - dev Pointer to net_device structure
5220
5221 \return - 0 for success non-zero for failure
5222
5223 --------------------------------------------------------------------------*/
5224
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305225int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005226{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305227 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005228 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5229 hdd_context_t *pHddCtx;
5230 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5231 VOS_STATUS status;
5232 v_BOOL_t enter_standby = TRUE;
5233
5234 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 if (NULL == pAdapter)
5236 {
5237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305238 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 return -ENODEV;
5240 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305241 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5242 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305243
5244 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5245 ret = wlan_hdd_validate_context(pHddCtx);
5246 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07005247 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5249 "%s: HDD context is not valid!", __func__);
5250 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 }
5252
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305253 /* Nothing to be done if the interface is not opened */
5254 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5255 {
5256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5257 "%s: NETDEV Interface is not OPENED", __func__);
5258 return -ENODEV;
5259 }
5260
5261 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005262 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005263 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305264
5265 /* Disable TX on the interface, after this hard_start_xmit() will not
5266 * be called on that interface
5267 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305269
5270 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005271 netif_carrier_off(pAdapter->dev);
5272
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305273 /* The interface is marked as down for outside world (aka kernel)
5274 * But the driver is pretty much alive inside. The driver needs to
5275 * tear down the existing connection on the netdev (session)
5276 * cleanup the data pipes and wait until the control plane is stabilized
5277 * for this interface. The call also needs to wait until the above
5278 * mentioned actions are completed before returning to the caller.
5279 * Notice that the hdd_stop_adapter is requested not to close the session
5280 * That is intentional to be able to scan if it is a STA/P2P interface
5281 */
5282 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005283
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305284 /* DeInit the adapter. This ensures datapath cleanup as well */
5285 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 /* SoftAP ifaces should never go in power save mode
5287 making sure same here. */
5288 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5289 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005291 )
5292 {
5293 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5295 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005296 EXIT();
5297 return 0;
5298 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305299 /* Find if any iface is up. If any iface is up then can't put device to
5300 * sleep/power save mode
5301 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5303 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5304 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005305 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5306 {
5307 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305308 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005309 enter_standby = FALSE;
5310 break;
5311 }
5312 else
5313 {
5314 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5315 pAdapterNode = pNext;
5316 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 }
5318
5319 if (TRUE == enter_standby)
5320 {
5321 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5322 "entering standby", __func__);
5323 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5324 {
5325 /*log and return success*/
5326 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5327 "wlan in power save", __func__);
5328 }
5329 }
5330
5331 EXIT();
5332 return 0;
5333}
5334
5335/**---------------------------------------------------------------------------
5336
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305337 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005338
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305339 This is called in response to ifconfig down
5340
5341 \param - dev Pointer to net_device structure
5342
5343 \return - 0 for success non-zero for failure
5344-----------------------------------------------------------------------------*/
5345int hdd_stop (struct net_device *dev)
5346{
5347 int ret;
5348
5349 vos_ssr_protect(__func__);
5350 ret = __hdd_stop(dev);
5351 vos_ssr_unprotect(__func__);
5352
5353 return ret;
5354}
5355
5356/**---------------------------------------------------------------------------
5357
5358 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005359
5360 \param - dev Pointer to net_device structure
5361
5362 \return - void
5363
5364 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305365static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005366{
5367 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5368
5369 ENTER();
5370
5371 do
5372 {
5373 if (NULL == pAdapter)
5374 {
5375 hddLog(VOS_TRACE_LEVEL_FATAL,
5376 "%s: NULL pAdapter", __func__);
5377 break;
5378 }
5379
5380 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5381 {
5382 hddLog(VOS_TRACE_LEVEL_FATAL,
5383 "%s: Invalid magic", __func__);
5384 break;
5385 }
5386
5387 if (NULL == pAdapter->pHddCtx)
5388 {
5389 hddLog(VOS_TRACE_LEVEL_FATAL,
5390 "%s: NULL pHddCtx", __func__);
5391 break;
5392 }
5393
5394 if (dev != pAdapter->dev)
5395 {
5396 hddLog(VOS_TRACE_LEVEL_FATAL,
5397 "%s: Invalid device reference", __func__);
5398 /* we haven't validated all cases so let this go for now */
5399 }
5400
5401 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5402
5403 /* after uninit our adapter structure will no longer be valid */
5404 pAdapter->dev = NULL;
5405 pAdapter->magic = 0;
5406 } while (0);
5407
5408 EXIT();
5409}
5410
5411/**---------------------------------------------------------------------------
5412
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305413 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5414
5415 This is called during the netdev unregister to uninitialize all data
5416associated with the device
5417
5418 \param - dev Pointer to net_device structure
5419
5420 \return - void
5421
5422 --------------------------------------------------------------------------*/
5423static void hdd_uninit (struct net_device *dev)
5424{
5425 vos_ssr_protect(__func__);
5426 __hdd_uninit(dev);
5427 vos_ssr_unprotect(__func__);
5428}
5429
5430/**---------------------------------------------------------------------------
5431
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 \brief hdd_release_firmware() -
5433
5434 This function calls the release firmware API to free the firmware buffer.
5435
5436 \param - pFileName Pointer to the File Name.
5437 pCtx - Pointer to the adapter .
5438
5439
5440 \return - 0 for success, non zero for failure
5441
5442 --------------------------------------------------------------------------*/
5443
5444VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5445{
5446 VOS_STATUS status = VOS_STATUS_SUCCESS;
5447 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5448 ENTER();
5449
5450
5451 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5452
5453 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5454
5455 if(pHddCtx->fw) {
5456 release_firmware(pHddCtx->fw);
5457 pHddCtx->fw = NULL;
5458 }
5459 else
5460 status = VOS_STATUS_E_FAILURE;
5461 }
5462 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5463 if(pHddCtx->nv) {
5464 release_firmware(pHddCtx->nv);
5465 pHddCtx->nv = NULL;
5466 }
5467 else
5468 status = VOS_STATUS_E_FAILURE;
5469
5470 }
5471
5472 EXIT();
5473 return status;
5474}
5475
5476/**---------------------------------------------------------------------------
5477
5478 \brief hdd_request_firmware() -
5479
5480 This function reads the firmware file using the request firmware
5481 API and returns the the firmware data and the firmware file size.
5482
5483 \param - pfileName - Pointer to the file name.
5484 - pCtx - Pointer to the adapter .
5485 - ppfw_data - Pointer to the pointer of the firmware data.
5486 - pSize - Pointer to the file size.
5487
5488 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5489
5490 --------------------------------------------------------------------------*/
5491
5492
5493VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5494{
5495 int status;
5496 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5497 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5498 ENTER();
5499
5500 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5501
5502 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5503
5504 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5505 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5506 __func__, pfileName);
5507 retval = VOS_STATUS_E_FAILURE;
5508 }
5509
5510 else {
5511 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5512 *pSize = pHddCtx->fw->size;
5513 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5514 __func__, *pSize);
5515 }
5516 }
5517 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5518
5519 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5520
5521 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5522 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5523 __func__, pfileName);
5524 retval = VOS_STATUS_E_FAILURE;
5525 }
5526
5527 else {
5528 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5529 *pSize = pHddCtx->nv->size;
5530 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5531 __func__, *pSize);
5532 }
5533 }
5534
5535 EXIT();
5536 return retval;
5537}
5538/**---------------------------------------------------------------------------
5539 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5540
5541 This is the function invoked by SME to inform the result of a full power
5542 request issued by HDD
5543
5544 \param - callbackcontext - Pointer to cookie
5545 status - result of request
5546
5547 \return - None
5548
5549--------------------------------------------------------------------------*/
5550void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5551{
5552 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5553
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005554 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 if(&pHddCtx->full_pwr_comp_var)
5556 {
5557 complete(&pHddCtx->full_pwr_comp_var);
5558 }
5559}
5560
5561/**---------------------------------------------------------------------------
5562
5563 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5564
5565 This is the function invoked by SME to inform the result of BMPS
5566 request issued by HDD
5567
5568 \param - callbackcontext - Pointer to cookie
5569 status - result of request
5570
5571 \return - None
5572
5573--------------------------------------------------------------------------*/
5574void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5575{
5576
5577 struct completion *completion_var = (struct completion*) callbackContext;
5578
Arif Hussain6d2a3322013-11-17 19:50:10 -08005579 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 if(completion_var != NULL)
5581 {
5582 complete(completion_var);
5583 }
5584}
5585
5586/**---------------------------------------------------------------------------
5587
5588 \brief hdd_get_cfg_file_size() -
5589
5590 This function reads the configuration file using the request firmware
5591 API and returns the configuration file size.
5592
5593 \param - pCtx - Pointer to the adapter .
5594 - pFileName - Pointer to the file name.
5595 - pBufSize - Pointer to the buffer size.
5596
5597 \return - 0 for success, non zero for failure
5598
5599 --------------------------------------------------------------------------*/
5600
5601VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5602{
5603 int status;
5604 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5605
5606 ENTER();
5607
5608 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5609
5610 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5611 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5612 status = VOS_STATUS_E_FAILURE;
5613 }
5614 else {
5615 *pBufSize = pHddCtx->fw->size;
5616 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5617 release_firmware(pHddCtx->fw);
5618 pHddCtx->fw = NULL;
5619 }
5620
5621 EXIT();
5622 return VOS_STATUS_SUCCESS;
5623}
5624
5625/**---------------------------------------------------------------------------
5626
5627 \brief hdd_read_cfg_file() -
5628
5629 This function reads the configuration file using the request firmware
5630 API and returns the cfg data and the buffer size of the configuration file.
5631
5632 \param - pCtx - Pointer to the adapter .
5633 - pFileName - Pointer to the file name.
5634 - pBuffer - Pointer to the data buffer.
5635 - pBufSize - Pointer to the buffer size.
5636
5637 \return - 0 for success, non zero for failure
5638
5639 --------------------------------------------------------------------------*/
5640
5641VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5642 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5643{
5644 int status;
5645 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5646
5647 ENTER();
5648
5649 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5650
5651 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5652 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5653 return VOS_STATUS_E_FAILURE;
5654 }
5655 else {
5656 if(*pBufSize != pHddCtx->fw->size) {
5657 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5658 "file size", __func__);
5659 release_firmware(pHddCtx->fw);
5660 pHddCtx->fw = NULL;
5661 return VOS_STATUS_E_FAILURE;
5662 }
5663 else {
5664 if(pBuffer) {
5665 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5666 }
5667 release_firmware(pHddCtx->fw);
5668 pHddCtx->fw = NULL;
5669 }
5670 }
5671
5672 EXIT();
5673
5674 return VOS_STATUS_SUCCESS;
5675}
5676
5677/**---------------------------------------------------------------------------
5678
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305679 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005680
5681 This function sets the user specified mac address using
5682 the command ifconfig wlanX hw ether <mac adress>.
5683
5684 \param - dev - Pointer to the net device.
5685 - addr - Pointer to the sockaddr.
5686 \return - 0 for success, non zero for failure
5687
5688 --------------------------------------------------------------------------*/
5689
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305690static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005691{
5692 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5693 struct sockaddr *psta_mac_addr = addr;
5694 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5695
5696 ENTER();
5697
5698 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5700
5701 EXIT();
5702 return halStatus;
5703}
5704
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305705/**---------------------------------------------------------------------------
5706
5707 \brief hdd_set_mac_address() -
5708
5709 Wrapper function to protect __hdd_set_mac_address() function from ssr
5710
5711 \param - dev - Pointer to the net device.
5712 - addr - Pointer to the sockaddr.
5713 \return - 0 for success, non zero for failure
5714
5715 --------------------------------------------------------------------------*/
5716static int hdd_set_mac_address(struct net_device *dev, void *addr)
5717{
5718 int ret;
5719
5720 vos_ssr_protect(__func__);
5721 ret = __hdd_set_mac_address(dev, addr);
5722 vos_ssr_unprotect(__func__);
5723
5724 return ret;
5725}
5726
Jeff Johnson295189b2012-06-20 16:38:30 -07005727tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5728{
5729 int i;
5730 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5731 {
Abhishek Singheb183782014-02-06 13:37:21 +05305732 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 break;
5734 }
5735
5736 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5737 return NULL;
5738
5739 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5740 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5741}
5742
5743void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5744{
5745 int i;
5746 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5747 {
5748 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5749 {
5750 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5751 break;
5752 }
5753 }
5754 return;
5755}
5756
5757#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5758 static struct net_device_ops wlan_drv_ops = {
5759 .ndo_open = hdd_open,
5760 .ndo_stop = hdd_stop,
5761 .ndo_uninit = hdd_uninit,
5762 .ndo_start_xmit = hdd_hard_start_xmit,
5763 .ndo_tx_timeout = hdd_tx_timeout,
5764 .ndo_get_stats = hdd_stats,
5765 .ndo_do_ioctl = hdd_ioctl,
5766 .ndo_set_mac_address = hdd_set_mac_address,
5767 .ndo_select_queue = hdd_select_queue,
5768#ifdef WLAN_FEATURE_PACKET_FILTERING
5769#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5770 .ndo_set_rx_mode = hdd_set_multicast_list,
5771#else
5772 .ndo_set_multicast_list = hdd_set_multicast_list,
5773#endif //LINUX_VERSION_CODE
5774#endif
5775 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 static struct net_device_ops wlan_mon_drv_ops = {
5777 .ndo_open = hdd_mon_open,
5778 .ndo_stop = hdd_stop,
5779 .ndo_uninit = hdd_uninit,
5780 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5781 .ndo_tx_timeout = hdd_tx_timeout,
5782 .ndo_get_stats = hdd_stats,
5783 .ndo_do_ioctl = hdd_ioctl,
5784 .ndo_set_mac_address = hdd_set_mac_address,
5785 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005786
5787#endif
5788
5789void hdd_set_station_ops( struct net_device *pWlanDev )
5790{
5791#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 pWlanDev->netdev_ops = &wlan_drv_ops;
5793#else
5794 pWlanDev->open = hdd_open;
5795 pWlanDev->stop = hdd_stop;
5796 pWlanDev->uninit = hdd_uninit;
5797 pWlanDev->hard_start_xmit = NULL;
5798 pWlanDev->tx_timeout = hdd_tx_timeout;
5799 pWlanDev->get_stats = hdd_stats;
5800 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005801 pWlanDev->set_mac_address = hdd_set_mac_address;
5802#endif
5803}
5804
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005805static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005806{
5807 struct net_device *pWlanDev = NULL;
5808 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005809 /*
5810 * cfg80211 initialization and registration....
5811 */
5812 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5813
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 if(pWlanDev != NULL)
5815 {
5816
5817 //Save the pointer to the net_device in the HDD adapter
5818 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5819
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5821
5822 pAdapter->dev = pWlanDev;
5823 pAdapter->pHddCtx = pHddCtx;
5824 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305825 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005826
5827 init_completion(&pAdapter->session_open_comp_var);
5828 init_completion(&pAdapter->session_close_comp_var);
5829 init_completion(&pAdapter->disconnect_comp_var);
5830 init_completion(&pAdapter->linkup_event_var);
5831 init_completion(&pAdapter->cancel_rem_on_chan_var);
5832 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305833 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005834#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5835 init_completion(&pAdapter->offchannel_tx_event);
5836#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005838#ifdef FEATURE_WLAN_TDLS
5839 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005840 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005841 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305842 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005843#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 init_completion(&pHddCtx->mc_sus_event_var);
5845 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305846 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005847 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005848 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005849
Rajeev79dbe4c2013-10-05 11:03:42 +05305850#ifdef FEATURE_WLAN_BATCH_SCAN
5851 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5852 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5853 pAdapter->pBatchScanRsp = NULL;
5854 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005855 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005856 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305857 mutex_init(&pAdapter->hdd_batch_scan_lock);
5858#endif
5859
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 pAdapter->isLinkUpSvcNeeded = FALSE;
5861 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5862 //Init the net_device structure
5863 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5864
5865 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5866 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5867 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5868 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5869
5870 hdd_set_station_ops( pAdapter->dev );
5871
5872 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5874 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5875 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 /* set pWlanDev's parent to underlying device */
5877 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005878
5879 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 }
5881
5882 return pAdapter;
5883}
5884
5885VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5886{
5887 struct net_device *pWlanDev = pAdapter->dev;
5888 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5889 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5890 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5891
5892 if( rtnl_lock_held )
5893 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005894 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5896 {
5897 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5898 return VOS_STATUS_E_FAILURE;
5899 }
5900 }
5901 if (register_netdevice(pWlanDev))
5902 {
5903 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5904 return VOS_STATUS_E_FAILURE;
5905 }
5906 }
5907 else
5908 {
5909 if(register_netdev(pWlanDev))
5910 {
5911 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5912 return VOS_STATUS_E_FAILURE;
5913 }
5914 }
5915 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5916
5917 return VOS_STATUS_SUCCESS;
5918}
5919
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005920static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005921{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005922 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005923
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005924 if (NULL == pAdapter)
5925 {
5926 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5927 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005929
5930 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5931 {
5932 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5933 return eHAL_STATUS_NOT_INITIALIZED;
5934 }
5935
5936 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5937
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005938#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005939 /* need to make sure all of our scheduled work has completed.
5940 * This callback is called from MC thread context, so it is safe to
5941 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005942 *
5943 * Even though this is called from MC thread context, if there is a faulty
5944 * work item in the system, that can hang this call forever. So flushing
5945 * this global work queue is not safe; and now we make sure that
5946 * individual work queues are stopped correctly. But the cancel work queue
5947 * is a GPL only API, so the proprietary version of the driver would still
5948 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005949 */
5950 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005951#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005952
5953 /* We can be blocked while waiting for scheduled work to be
5954 * flushed, and the adapter structure can potentially be freed, in
5955 * which case the magic will have been reset. So make sure the
5956 * magic is still good, and hence the adapter structure is still
5957 * valid, before signaling completion */
5958 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5959 {
5960 complete(&pAdapter->session_close_comp_var);
5961 }
5962
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 return eHAL_STATUS_SUCCESS;
5964}
5965
5966VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5967{
5968 struct net_device *pWlanDev = pAdapter->dev;
5969 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5970 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5971 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5972 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305973 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005974
5975 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005976 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005977 //Open a SME session for future operation
5978 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005979 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5981 {
5982 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005983 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005984 halStatus, halStatus );
5985 status = VOS_STATUS_E_FAILURE;
5986 goto error_sme_open;
5987 }
5988
5989 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305990 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 &pAdapter->session_open_comp_var,
5992 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305993 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005994 {
5995 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305996 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 status = VOS_STATUS_E_FAILURE;
5998 goto error_sme_open;
5999 }
6000
6001 // Register wireless extensions
6002 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
6003 {
6004 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006005 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 halStatus, halStatus );
6007 status = VOS_STATUS_E_FAILURE;
6008 goto error_register_wext;
6009 }
6010 //Safe to register the hard_start_xmit function again
6011#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
6012 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
6013#else
6014 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
6015#endif
6016
6017 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05306018 hddLog(VOS_TRACE_LEVEL_INFO,
6019 "%s: Set HDD connState to eConnectionState_NotConnected",
6020 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006021 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6022
6023 //Set the default operation channel
6024 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
6025
6026 /* Make the default Auth Type as OPEN*/
6027 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
6028
6029 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6030 {
6031 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006032 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 status, status );
6034 goto error_init_txrx;
6035 }
6036
6037 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6038
6039 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6040 {
6041 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006042 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 status, status );
6044 goto error_wmm_init;
6045 }
6046
6047 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6048
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006049#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306050 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006051 {
6052 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306053 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006054 goto error_tdls_init;
6055 }
6056 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6057#endif
6058
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 return VOS_STATUS_SUCCESS;
6060
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006061#ifdef FEATURE_WLAN_TDLS
6062error_tdls_init:
6063 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6064 hdd_wmm_adapter_close(pAdapter);
6065#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006066error_wmm_init:
6067 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6068 hdd_deinit_tx_rx(pAdapter);
6069error_init_txrx:
6070 hdd_UnregisterWext(pWlanDev);
6071error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006072 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006073 {
6074 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006075 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006077 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006078 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306079 unsigned long rc;
6080
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306082 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006083 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006084 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306085 if (rc <= 0)
6086 hddLog(VOS_TRACE_LEVEL_ERROR,
6087 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006088 }
6089}
6090error_sme_open:
6091 return status;
6092}
6093
Jeff Johnson295189b2012-06-20 16:38:30 -07006094void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6095{
6096 hdd_cfg80211_state_t *cfgState;
6097
6098 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6099
6100 if( NULL != cfgState->buf )
6101 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306102 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006103 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6104 rc = wait_for_completion_interruptible_timeout(
6105 &pAdapter->tx_action_cnf_event,
6106 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306107 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306110 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6111 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 }
6113 }
6114 return;
6115}
Jeff Johnson295189b2012-06-20 16:38:30 -07006116
6117void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6118{
6119 ENTER();
6120 switch ( pAdapter->device_mode )
6121 {
6122 case WLAN_HDD_INFRA_STATION:
6123 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006124 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 {
6126 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6127 {
6128 hdd_deinit_tx_rx( pAdapter );
6129 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6130 }
6131
6132 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6133 {
6134 hdd_wmm_adapter_close( pAdapter );
6135 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6136 }
6137
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006139#ifdef FEATURE_WLAN_TDLS
6140 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6141 {
6142 wlan_hdd_tdls_exit(pAdapter);
6143 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6144 }
6145#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006146
6147 break;
6148 }
6149
6150 case WLAN_HDD_SOFTAP:
6151 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306153
6154 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6155 {
6156 hdd_wmm_adapter_close( pAdapter );
6157 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6158 }
6159
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006161
6162 hdd_unregister_hostapd(pAdapter);
6163 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 break;
6166 }
6167
6168 case WLAN_HDD_MONITOR:
6169 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6172 {
6173 hdd_deinit_tx_rx( pAdapter );
6174 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6175 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 if(NULL != pAdapterforTx)
6177 {
6178 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6179 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 break;
6181 }
6182
6183
6184 default:
6185 break;
6186 }
6187
6188 EXIT();
6189}
6190
6191void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6192{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006193 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306194
6195 ENTER();
6196 if (NULL == pAdapter)
6197 {
6198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6199 "%s: HDD adapter is Null", __func__);
6200 return;
6201 }
6202
6203 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006204
Rajeev79dbe4c2013-10-05 11:03:42 +05306205#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306206 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6207 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006208 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306209 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6210 )
6211 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006212 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306213 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006214 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6215 {
6216 hdd_deinit_batch_scan(pAdapter);
6217 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306218 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006219 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306220#endif
6221
Jeff Johnson295189b2012-06-20 16:38:30 -07006222 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6223 if( rtnl_held )
6224 {
6225 unregister_netdevice(pWlanDev);
6226 }
6227 else
6228 {
6229 unregister_netdev(pWlanDev);
6230 }
6231 // note that the pAdapter is no longer valid at this point
6232 // since the memory has been reclaimed
6233 }
6234
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306235 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006236}
6237
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006238void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6239{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306240 VOS_STATUS status;
6241 hdd_adapter_t *pAdapter = NULL;
6242 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006243
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306244 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006245
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306246 /*loop through all adapters.*/
6247 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006248 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306249 pAdapter = pAdapterNode->pAdapter;
6250 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6251 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006252
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306253 { // we skip this registration for modes other than STA and P2P client modes.
6254 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6255 pAdapterNode = pNext;
6256 continue;
6257 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006258
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306259 //Apply Dynamic DTIM For P2P
6260 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6261 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6262 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6263 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6264 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6265 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6266 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6267 (eConnectionState_Associated ==
6268 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6269 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6270 {
6271 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006272
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306273 powerRequest.uIgnoreDTIM = 1;
6274 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6275
6276 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6277 {
6278 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6279 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6280 }
6281 else
6282 {
6283 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6284 }
6285
6286 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6287 * specified during Enter/Exit BMPS when LCD off*/
6288 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6289 NULL, eANI_BOOLEAN_FALSE);
6290 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6291 NULL, eANI_BOOLEAN_FALSE);
6292
6293 /* switch to the DTIM specified in cfg.ini */
6294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6295 "Switch to DTIM %d", powerRequest.uListenInterval);
6296 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6297 break;
6298
6299 }
6300
6301 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6302 pAdapterNode = pNext;
6303 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006304}
6305
6306void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6307{
6308 /*Switch back to DTIM 1*/
6309 tSirSetPowerParamsReq powerRequest = { 0 };
6310
6311 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6312 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006313 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006314
6315 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6316 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6317 NULL, eANI_BOOLEAN_FALSE);
6318 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6319 NULL, eANI_BOOLEAN_FALSE);
6320
6321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6322 "Switch to DTIM%d",powerRequest.uListenInterval);
6323 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6324
6325}
6326
Jeff Johnson295189b2012-06-20 16:38:30 -07006327VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6328{
6329 VOS_STATUS status = VOS_STATUS_SUCCESS;
6330
6331 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6332 {
6333 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6334 }
6335
6336 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6337 {
6338 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6339 }
6340
6341 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6342 {
6343 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6344 }
6345
6346 return status;
6347}
6348
6349VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6350{
6351 hdd_adapter_t *pAdapter = NULL;
6352 eHalStatus halStatus;
6353 VOS_STATUS status = VOS_STATUS_E_INVAL;
6354 v_BOOL_t disableBmps = FALSE;
6355 v_BOOL_t disableImps = FALSE;
6356
6357 switch(session_type)
6358 {
6359 case WLAN_HDD_INFRA_STATION:
6360 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 case WLAN_HDD_P2P_CLIENT:
6362 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 //Exit BMPS -> Is Sta/P2P Client is already connected
6364 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6365 if((NULL != pAdapter)&&
6366 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6367 {
6368 disableBmps = TRUE;
6369 }
6370
6371 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6372 if((NULL != pAdapter)&&
6373 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6374 {
6375 disableBmps = TRUE;
6376 }
6377
6378 //Exit both Bmps and Imps incase of Go/SAP Mode
6379 if((WLAN_HDD_SOFTAP == session_type) ||
6380 (WLAN_HDD_P2P_GO == session_type))
6381 {
6382 disableBmps = TRUE;
6383 disableImps = TRUE;
6384 }
6385
6386 if(TRUE == disableImps)
6387 {
6388 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6389 {
6390 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6391 }
6392 }
6393
6394 if(TRUE == disableBmps)
6395 {
6396 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6397 {
6398 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6399
6400 if(eHAL_STATUS_SUCCESS != halStatus)
6401 {
6402 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006403 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006404 VOS_ASSERT(0);
6405 return status;
6406 }
6407 }
6408
6409 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6410 {
6411 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6412
6413 if(eHAL_STATUS_SUCCESS != halStatus)
6414 {
6415 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006416 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 VOS_ASSERT(0);
6418 return status;
6419 }
6420 }
6421 }
6422
6423 if((TRUE == disableBmps) ||
6424 (TRUE == disableImps))
6425 {
6426 /* Now, get the chip into Full Power now */
6427 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6428 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6429 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6430
6431 if(halStatus != eHAL_STATUS_SUCCESS)
6432 {
6433 if(halStatus == eHAL_STATUS_PMC_PENDING)
6434 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306435 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306437 ret = wait_for_completion_interruptible_timeout(
6438 &pHddCtx->full_pwr_comp_var,
6439 msecs_to_jiffies(1000));
6440 if (ret <= 0)
6441 {
6442 hddLog(VOS_TRACE_LEVEL_ERROR,
6443 "%s: wait on full_pwr_comp_var failed %ld",
6444 __func__, ret);
6445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006446 }
6447 else
6448 {
6449 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006450 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 VOS_ASSERT(0);
6452 return status;
6453 }
6454 }
6455
6456 status = VOS_STATUS_SUCCESS;
6457 }
6458
6459 break;
6460 }
6461 return status;
6462}
6463
6464hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006465 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 tANI_U8 rtnl_held )
6467{
6468 hdd_adapter_t *pAdapter = NULL;
6469 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6470 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6471 VOS_STATUS exitbmpsStatus;
6472
Arif Hussain6d2a3322013-11-17 19:50:10 -08006473 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006474
Nirav Shah436658f2014-02-28 17:05:45 +05306475 if(macAddr == NULL)
6476 {
6477 /* Not received valid macAddr */
6478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6479 "%s:Unable to add virtual intf: Not able to get"
6480 "valid mac address",__func__);
6481 return NULL;
6482 }
6483
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 //Disable BMPS incase of Concurrency
6485 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6486
6487 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6488 {
6489 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306490 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006491 VOS_ASSERT(0);
6492 return NULL;
6493 }
6494
6495 switch(session_type)
6496 {
6497 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006499 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006500 {
6501 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6502
6503 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306504 {
6505 hddLog(VOS_TRACE_LEVEL_FATAL,
6506 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006507 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006509
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306510#ifdef FEATURE_WLAN_TDLS
6511 /* A Mutex Lock is introduced while changing/initializing the mode to
6512 * protect the concurrent access for the Adapters by TDLS module.
6513 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306514 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306515#endif
6516
Jeff Johnsone7245742012-09-05 17:12:55 -07006517 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6518 NL80211_IFTYPE_P2P_CLIENT:
6519 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006520
Jeff Johnson295189b2012-06-20 16:38:30 -07006521 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306522#ifdef FEATURE_WLAN_TDLS
6523 mutex_unlock(&pHddCtx->tdls_lock);
6524#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306525
6526 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 if( VOS_STATUS_SUCCESS != status )
6528 goto err_free_netdev;
6529
6530 status = hdd_register_interface( pAdapter, rtnl_held );
6531 if( VOS_STATUS_SUCCESS != status )
6532 {
6533 hdd_deinit_adapter(pHddCtx, pAdapter);
6534 goto err_free_netdev;
6535 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306536
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306537 // Workqueue which gets scheduled in IPv4 notification callback.
6538 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6539
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306540#ifdef WLAN_NS_OFFLOAD
6541 // Workqueue which gets scheduled in IPv6 notification callback.
6542 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6543#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 //Stop the Interface TX queue.
6545 netif_tx_disable(pAdapter->dev);
6546 //netif_tx_disable(pWlanDev);
6547 netif_carrier_off(pAdapter->dev);
6548
6549 break;
6550 }
6551
Jeff Johnson295189b2012-06-20 16:38:30 -07006552 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006553 case WLAN_HDD_SOFTAP:
6554 {
6555 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6556 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306557 {
6558 hddLog(VOS_TRACE_LEVEL_FATAL,
6559 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306561 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006562
Jeff Johnson295189b2012-06-20 16:38:30 -07006563 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6564 NL80211_IFTYPE_AP:
6565 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006566 pAdapter->device_mode = session_type;
6567
6568 status = hdd_init_ap_mode(pAdapter);
6569 if( VOS_STATUS_SUCCESS != status )
6570 goto err_free_netdev;
6571
6572 status = hdd_register_hostapd( pAdapter, rtnl_held );
6573 if( VOS_STATUS_SUCCESS != status )
6574 {
6575 hdd_deinit_adapter(pHddCtx, pAdapter);
6576 goto err_free_netdev;
6577 }
6578
6579 netif_tx_disable(pAdapter->dev);
6580 netif_carrier_off(pAdapter->dev);
6581
6582 hdd_set_conparam( 1 );
6583 break;
6584 }
6585 case WLAN_HDD_MONITOR:
6586 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006587 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6588 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306589 {
6590 hddLog(VOS_TRACE_LEVEL_FATAL,
6591 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006594
6595 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6596 pAdapter->device_mode = session_type;
6597 status = hdd_register_interface( pAdapter, rtnl_held );
6598#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6599 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6600#else
6601 pAdapter->dev->open = hdd_mon_open;
6602 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6603#endif
6604 hdd_init_tx_rx( pAdapter );
6605 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6606 //Set adapter to be used for data tx. It will use either GO or softap.
6607 pAdapter->sessionCtx.monitor.pAdapterForTx =
6608 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006609 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6610 {
6611 pAdapter->sessionCtx.monitor.pAdapterForTx =
6612 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6613 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006614 /* This workqueue will be used to transmit management packet over
6615 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006616 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6617 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6618 return NULL;
6619 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006620
Jeff Johnson295189b2012-06-20 16:38:30 -07006621 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6622 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006623 }
6624 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 case WLAN_HDD_FTM:
6626 {
6627 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6628
6629 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306630 {
6631 hddLog(VOS_TRACE_LEVEL_FATAL,
6632 FL("failed to allocate adapter for session %d"), session_type);
6633 return NULL;
6634 }
6635
Jeff Johnson295189b2012-06-20 16:38:30 -07006636 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6637 * message while loading driver in FTM mode. */
6638 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6639 pAdapter->device_mode = session_type;
6640 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306641
6642 hdd_init_tx_rx( pAdapter );
6643
6644 //Stop the Interface TX queue.
6645 netif_tx_disable(pAdapter->dev);
6646 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006647 }
6648 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006649 default:
6650 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306651 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6652 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006653 VOS_ASSERT(0);
6654 return NULL;
6655 }
6656 }
6657
Jeff Johnson295189b2012-06-20 16:38:30 -07006658 if( VOS_STATUS_SUCCESS == status )
6659 {
6660 //Add it to the hdd's session list.
6661 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6662 if( NULL == pHddAdapterNode )
6663 {
6664 status = VOS_STATUS_E_NOMEM;
6665 }
6666 else
6667 {
6668 pHddAdapterNode->pAdapter = pAdapter;
6669 status = hdd_add_adapter_back ( pHddCtx,
6670 pHddAdapterNode );
6671 }
6672 }
6673
6674 if( VOS_STATUS_SUCCESS != status )
6675 {
6676 if( NULL != pAdapter )
6677 {
6678 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6679 pAdapter = NULL;
6680 }
6681 if( NULL != pHddAdapterNode )
6682 {
6683 vos_mem_free( pHddAdapterNode );
6684 }
6685
6686 goto resume_bmps;
6687 }
6688
6689 if(VOS_STATUS_SUCCESS == status)
6690 {
6691 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6692
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006693 //Initialize the WoWL service
6694 if(!hdd_init_wowl(pAdapter))
6695 {
6696 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6697 goto err_free_netdev;
6698 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006699 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006700 return pAdapter;
6701
6702err_free_netdev:
6703 free_netdev(pAdapter->dev);
6704 wlan_hdd_release_intf_addr( pHddCtx,
6705 pAdapter->macAddressCurrent.bytes );
6706
6707resume_bmps:
6708 //If bmps disabled enable it
6709 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6710 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306711 if (pHddCtx->hdd_wlan_suspended)
6712 {
6713 hdd_set_pwrparams(pHddCtx);
6714 }
6715 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006716 }
6717 return NULL;
6718}
6719
6720VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6721 tANI_U8 rtnl_held )
6722{
6723 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6724 VOS_STATUS status;
6725
6726 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6727 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306728 {
6729 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6730 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006731 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306732 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006733
6734 while ( pCurrent->pAdapter != pAdapter )
6735 {
6736 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6737 if( VOS_STATUS_SUCCESS != status )
6738 break;
6739
6740 pCurrent = pNext;
6741 }
6742 pAdapterNode = pCurrent;
6743 if( VOS_STATUS_SUCCESS == status )
6744 {
6745 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6746 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306747
6748#ifdef FEATURE_WLAN_TDLS
6749
6750 /* A Mutex Lock is introduced while changing/initializing the mode to
6751 * protect the concurrent access for the Adapters by TDLS module.
6752 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306753 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306754#endif
6755
Jeff Johnson295189b2012-06-20 16:38:30 -07006756 hdd_remove_adapter( pHddCtx, pAdapterNode );
6757 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006758 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006759
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306760#ifdef FEATURE_WLAN_TDLS
6761 mutex_unlock(&pHddCtx->tdls_lock);
6762#endif
6763
Jeff Johnson295189b2012-06-20 16:38:30 -07006764
6765 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306766 if ((!vos_concurrent_open_sessions_running()) &&
6767 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6768 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006769 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306770 if (pHddCtx->hdd_wlan_suspended)
6771 {
6772 hdd_set_pwrparams(pHddCtx);
6773 }
6774 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006775 }
6776
6777 return VOS_STATUS_SUCCESS;
6778 }
6779
6780 return VOS_STATUS_E_FAILURE;
6781}
6782
6783VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6784{
6785 hdd_adapter_list_node_t *pHddAdapterNode;
6786 VOS_STATUS status;
6787
6788 ENTER();
6789
6790 do
6791 {
6792 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6793 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6794 {
6795 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6796 vos_mem_free( pHddAdapterNode );
6797 }
6798 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6799
6800 EXIT();
6801
6802 return VOS_STATUS_SUCCESS;
6803}
6804
6805void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6806{
6807 v_U8_t addIE[1] = {0};
6808
6809 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6810 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6811 eANI_BOOLEAN_FALSE) )
6812 {
6813 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006814 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006815 }
6816
6817 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6818 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6819 eANI_BOOLEAN_FALSE) )
6820 {
6821 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006822 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006823 }
6824
6825 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6826 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6827 eANI_BOOLEAN_FALSE) )
6828 {
6829 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006830 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006831 }
6832}
6833
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306834VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6835 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006836{
6837 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6838 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306839 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006840 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306841 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306842 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006843
6844 ENTER();
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306845 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07006846 switch(pAdapter->device_mode)
6847 {
6848 case WLAN_HDD_INFRA_STATION:
6849 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006850 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306851 {
6852 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6853 if( hdd_connIsConnected(pstation) ||
6854 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006855 {
6856 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6857 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6858 pAdapter->sessionId,
6859 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6860 else
6861 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6862 pAdapter->sessionId,
6863 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6864 //success implies disconnect command got queued up successfully
6865 if(halStatus == eHAL_STATUS_SUCCESS)
6866 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306867 ret = wait_for_completion_interruptible_timeout(
6868 &pAdapter->disconnect_comp_var,
6869 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6870 if (ret <= 0)
6871 {
6872 hddLog(VOS_TRACE_LEVEL_ERROR,
6873 "%s: wait on disconnect_comp_var failed %ld",
6874 __func__, ret);
6875 }
6876 }
6877 else
6878 {
6879 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6880 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006881 }
6882 memset(&wrqu, '\0', sizeof(wrqu));
6883 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6884 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6885 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6886 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306887 else if(pstation->conn_info.connState ==
6888 eConnectionState_Disconnecting)
6889 {
6890 ret = wait_for_completion_interruptible_timeout(
6891 &pAdapter->disconnect_comp_var,
6892 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6893 if (ret <= 0)
6894 {
6895 hddLog(VOS_TRACE_LEVEL_ERROR,
6896 FL("wait on disconnect_comp_var failed %ld"), ret);
6897 }
6898 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306899 else if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07006900 {
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306901 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306902 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006903 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306904 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6905 {
6906 while (pAdapter->is_roc_inprogress)
6907 {
6908 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6909 "%s: ROC in progress for session %d!!!",
6910 __func__, pAdapter->sessionId);
6911 // waiting for ROC to expire
6912 msleep(500);
6913 /* In GO present case , if retry exceeds 3,
6914 it means something went wrong. */
6915 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6916 {
6917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6918 "%s: ROC completion is not received.!!!", __func__);
6919 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6920 pAdapter->sessionId);
6921 wait_for_completion_interruptible_timeout(
6922 &pAdapter->cancel_rem_on_chan_var,
6923 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6924 break;
6925 }
6926 }
6927 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306928#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306929#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306930 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6931#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306932 if (pAdapter->ipv6_notifier_registered)
6933 {
6934 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6935 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6936 pAdapter->ipv6_notifier_registered = false;
6937 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306938#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306939 if (pAdapter->ipv4_notifier_registered)
6940 {
6941 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6942 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6943 pAdapter->ipv4_notifier_registered = false;
6944 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306945#ifdef WLAN_OPEN_SOURCE
6946 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6947#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306948 /* It is possible that the caller of this function does not
6949 * wish to close the session
6950 */
6951 if (VOS_TRUE == bCloseSession &&
6952 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 {
6954 INIT_COMPLETION(pAdapter->session_close_comp_var);
6955 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306956 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6957 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006958 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306959 unsigned long ret;
6960
Jeff Johnson295189b2012-06-20 16:38:30 -07006961 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306962 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306963 &pAdapter->session_close_comp_var,
6964 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306965 if ( 0 >= ret)
6966 {
6967 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306968 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306969 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 }
6971 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306972 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006973 break;
6974
6975 case WLAN_HDD_SOFTAP:
6976 case WLAN_HDD_P2P_GO:
6977 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306978 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6979 while (pAdapter->is_roc_inprogress) {
6980 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6981 "%s: ROC in progress for session %d!!!",
6982 __func__, pAdapter->sessionId);
6983 msleep(500);
6984 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6985 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6986 "%s: ROC completion is not received.!!!", __func__);
6987 WLANSAP_CancelRemainOnChannel(
6988 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6989 wait_for_completion_interruptible_timeout(
6990 &pAdapter->cancel_rem_on_chan_var,
6991 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6992 break;
6993 }
6994 }
6995 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006996 mutex_lock(&pHddCtx->sap_lock);
6997 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6998 {
6999 VOS_STATUS status;
7000 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7001
7002 //Stop Bss.
7003 status = WLANSAP_StopBss(pHddCtx->pvosContext);
7004 if (VOS_IS_STATUS_SUCCESS(status))
7005 {
7006 hdd_hostapd_state_t *pHostapdState =
7007 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7008
7009 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7010
7011 if (!VOS_IS_STATUS_SUCCESS(status))
7012 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307013 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
7014 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007015 }
7016 }
7017 else
7018 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007019 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007020 }
7021 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05307022 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07007023
7024 if (eHAL_STATUS_FAILURE ==
7025 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
7026 0, NULL, eANI_BOOLEAN_FALSE))
7027 {
7028 hddLog(LOGE,
7029 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007030 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007031 }
7032
7033 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7034 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7035 eANI_BOOLEAN_FALSE) )
7036 {
7037 hddLog(LOGE,
7038 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7039 }
7040
7041 // Reset WNI_CFG_PROBE_RSP Flags
7042 wlan_hdd_reset_prob_rspies(pAdapter);
7043 kfree(pAdapter->sessionCtx.ap.beacon);
7044 pAdapter->sessionCtx.ap.beacon = NULL;
7045 }
7046 mutex_unlock(&pHddCtx->sap_lock);
7047 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007048
Jeff Johnson295189b2012-06-20 16:38:30 -07007049 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007050#ifdef WLAN_OPEN_SOURCE
7051 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7052#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007053 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007054
Jeff Johnson295189b2012-06-20 16:38:30 -07007055 default:
7056 break;
7057 }
7058
7059 EXIT();
7060 return VOS_STATUS_SUCCESS;
7061}
7062
7063VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7064{
7065 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7066 VOS_STATUS status;
7067 hdd_adapter_t *pAdapter;
7068
7069 ENTER();
7070
7071 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7072
7073 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7074 {
7075 pAdapter = pAdapterNode->pAdapter;
7076 netif_tx_disable(pAdapter->dev);
7077 netif_carrier_off(pAdapter->dev);
7078
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307079 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007080
7081 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7082 pAdapterNode = pNext;
7083 }
7084
7085 EXIT();
7086
7087 return VOS_STATUS_SUCCESS;
7088}
7089
Rajeev Kumarf999e582014-01-09 17:33:29 -08007090
7091#ifdef FEATURE_WLAN_BATCH_SCAN
7092/**---------------------------------------------------------------------------
7093
7094 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7095 structures
7096
7097 \param - pAdapter Pointer to HDD adapter
7098
7099 \return - None
7100
7101 --------------------------------------------------------------------------*/
7102void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7103{
7104 tHddBatchScanRsp *pNode;
7105 tHddBatchScanRsp *pPrev;
7106
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307107 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007108 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307109 hddLog(VOS_TRACE_LEVEL_ERROR,
7110 "%s: Adapter context is Null", __func__);
7111 return;
7112 }
7113
7114 pNode = pAdapter->pBatchScanRsp;
7115 while (pNode)
7116 {
7117 pPrev = pNode;
7118 pNode = pNode->pNext;
7119 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007120 }
7121
7122 pAdapter->pBatchScanRsp = NULL;
7123 pAdapter->numScanList = 0;
7124 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7125 pAdapter->prev_batch_id = 0;
7126
7127 return;
7128}
7129#endif
7130
7131
Jeff Johnson295189b2012-06-20 16:38:30 -07007132VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7133{
7134 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7135 VOS_STATUS status;
7136 hdd_adapter_t *pAdapter;
7137
7138 ENTER();
7139
7140 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7141
7142 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7143 {
7144 pAdapter = pAdapterNode->pAdapter;
7145 netif_tx_disable(pAdapter->dev);
7146 netif_carrier_off(pAdapter->dev);
7147
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007148 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7149
Jeff Johnson295189b2012-06-20 16:38:30 -07007150 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307151
7152 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7153
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307154 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7155 {
7156 hdd_wmm_adapter_close( pAdapter );
7157 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7158 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007159
Rajeev Kumarf999e582014-01-09 17:33:29 -08007160#ifdef FEATURE_WLAN_BATCH_SCAN
7161 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7162 {
7163 hdd_deinit_batch_scan(pAdapter);
7164 }
7165#endif
7166
Jeff Johnson295189b2012-06-20 16:38:30 -07007167 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7168 pAdapterNode = pNext;
7169 }
7170
7171 EXIT();
7172
7173 return VOS_STATUS_SUCCESS;
7174}
7175
7176VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7177{
7178 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7179 VOS_STATUS status;
7180 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307181 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007182
7183 ENTER();
7184
7185 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7186
7187 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7188 {
7189 pAdapter = pAdapterNode->pAdapter;
7190
Kumar Anand82c009f2014-05-29 00:29:42 -07007191 hdd_wmm_init( pAdapter );
7192
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 switch(pAdapter->device_mode)
7194 {
7195 case WLAN_HDD_INFRA_STATION:
7196 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007197 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307198
7199 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7200
Jeff Johnson295189b2012-06-20 16:38:30 -07007201 hdd_init_station_mode(pAdapter);
7202 /* Open the gates for HDD to receive Wext commands */
7203 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007204 pHddCtx->scan_info.mScanPending = FALSE;
7205 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007206
7207 //Trigger the initial scan
7208 hdd_wlan_initial_scan(pAdapter);
7209
7210 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307211 if (eConnectionState_Associated == connState ||
7212 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 {
7214 union iwreq_data wrqu;
7215 memset(&wrqu, '\0', sizeof(wrqu));
7216 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7217 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7218 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007219 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007220
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 /* indicate disconnected event to nl80211 */
7222 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7223 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307225 else if (eConnectionState_Connecting == connState)
7226 {
7227 /*
7228 * Indicate connect failure to supplicant if we were in the
7229 * process of connecting
7230 */
7231 cfg80211_connect_result(pAdapter->dev, NULL,
7232 NULL, 0, NULL, 0,
7233 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7234 GFP_KERNEL);
7235 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007236 break;
7237
7238 case WLAN_HDD_SOFTAP:
7239 /* softAP can handle SSR */
7240 break;
7241
7242 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007243 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007245 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007246 break;
7247
7248 case WLAN_HDD_MONITOR:
7249 /* monitor interface start */
7250 break;
7251 default:
7252 break;
7253 }
7254
7255 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7256 pAdapterNode = pNext;
7257 }
7258
7259 EXIT();
7260
7261 return VOS_STATUS_SUCCESS;
7262}
7263
7264VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7265{
7266 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7267 hdd_adapter_t *pAdapter;
7268 VOS_STATUS status;
7269 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307270 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007271
7272 ENTER();
7273
7274 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7275
7276 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7277 {
7278 pAdapter = pAdapterNode->pAdapter;
7279
7280 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7281 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7282 {
7283 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7284 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7285
Abhishek Singhf4669da2014-05-26 15:07:49 +05307286 hddLog(VOS_TRACE_LEVEL_INFO,
7287 "%s: Set HDD connState to eConnectionState_NotConnected",
7288 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007289 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7290 init_completion(&pAdapter->disconnect_comp_var);
7291 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7292 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7293
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307294 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007295 &pAdapter->disconnect_comp_var,
7296 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307297 if (0 >= ret)
7298 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7299 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007300
7301 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7302 pHddCtx->isAmpAllowed = VOS_FALSE;
7303 sme_RoamConnect(pHddCtx->hHal,
7304 pAdapter->sessionId, &(pWextState->roamProfile),
7305 &roamId);
7306 }
7307
7308 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7309 pAdapterNode = pNext;
7310 }
7311
7312 EXIT();
7313
7314 return VOS_STATUS_SUCCESS;
7315}
7316
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007317void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7318{
7319 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7320 VOS_STATUS status;
7321 hdd_adapter_t *pAdapter;
7322 hdd_station_ctx_t *pHddStaCtx;
7323 hdd_ap_ctx_t *pHddApCtx;
7324 hdd_hostapd_state_t * pHostapdState;
7325 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7326 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7327 const char *p2pMode = "DEV";
7328 const char *ccMode = "Standalone";
7329 int n;
7330
7331 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7332 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7333 {
7334 pAdapter = pAdapterNode->pAdapter;
7335 switch (pAdapter->device_mode) {
7336 case WLAN_HDD_INFRA_STATION:
7337 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7338 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7339 staChannel = pHddStaCtx->conn_info.operationChannel;
7340 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7341 }
7342 break;
7343 case WLAN_HDD_P2P_CLIENT:
7344 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7345 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7346 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7347 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7348 p2pMode = "CLI";
7349 }
7350 break;
7351 case WLAN_HDD_P2P_GO:
7352 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7353 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7354 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7355 p2pChannel = pHddApCtx->operatingChannel;
7356 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7357 }
7358 p2pMode = "GO";
7359 break;
7360 case WLAN_HDD_SOFTAP:
7361 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7362 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7363 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7364 apChannel = pHddApCtx->operatingChannel;
7365 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7366 }
7367 break;
7368 default:
7369 break;
7370 }
7371 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7372 pAdapterNode = pNext;
7373 }
7374 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7375 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7376 }
7377 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7378 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7379 if (p2pChannel > 0) {
7380 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7381 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7382 }
7383 if (apChannel > 0) {
7384 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7385 apChannel, MAC_ADDR_ARRAY(apBssid));
7386 }
7387
7388 if (p2pChannel > 0 && apChannel > 0) {
7389 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7390 }
7391}
7392
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007393bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007394{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007395 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007396}
7397
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007398/* Once SSR is disabled then it cannot be set. */
7399void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007400{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007401 if (HDD_SSR_DISABLED == isSsrRequired)
7402 return;
7403
Jeff Johnson295189b2012-06-20 16:38:30 -07007404 isSsrRequired = value;
7405}
7406
7407VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7408 hdd_adapter_list_node_t** ppAdapterNode)
7409{
7410 VOS_STATUS status;
7411 spin_lock(&pHddCtx->hddAdapters.lock);
7412 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7413 (hdd_list_node_t**) ppAdapterNode );
7414 spin_unlock(&pHddCtx->hddAdapters.lock);
7415 return status;
7416}
7417
7418VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7419 hdd_adapter_list_node_t* pAdapterNode,
7420 hdd_adapter_list_node_t** pNextAdapterNode)
7421{
7422 VOS_STATUS status;
7423 spin_lock(&pHddCtx->hddAdapters.lock);
7424 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7425 (hdd_list_node_t*) pAdapterNode,
7426 (hdd_list_node_t**)pNextAdapterNode );
7427
7428 spin_unlock(&pHddCtx->hddAdapters.lock);
7429 return status;
7430}
7431
7432VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7433 hdd_adapter_list_node_t* pAdapterNode)
7434{
7435 VOS_STATUS status;
7436 spin_lock(&pHddCtx->hddAdapters.lock);
7437 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7438 &pAdapterNode->node );
7439 spin_unlock(&pHddCtx->hddAdapters.lock);
7440 return status;
7441}
7442
7443VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7444 hdd_adapter_list_node_t** ppAdapterNode)
7445{
7446 VOS_STATUS status;
7447 spin_lock(&pHddCtx->hddAdapters.lock);
7448 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7449 (hdd_list_node_t**) ppAdapterNode );
7450 spin_unlock(&pHddCtx->hddAdapters.lock);
7451 return status;
7452}
7453
7454VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7455 hdd_adapter_list_node_t* pAdapterNode)
7456{
7457 VOS_STATUS status;
7458 spin_lock(&pHddCtx->hddAdapters.lock);
7459 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7460 (hdd_list_node_t*) pAdapterNode );
7461 spin_unlock(&pHddCtx->hddAdapters.lock);
7462 return status;
7463}
7464
7465VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7466 hdd_adapter_list_node_t* pAdapterNode)
7467{
7468 VOS_STATUS status;
7469 spin_lock(&pHddCtx->hddAdapters.lock);
7470 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7471 (hdd_list_node_t*) pAdapterNode );
7472 spin_unlock(&pHddCtx->hddAdapters.lock);
7473 return status;
7474}
7475
7476hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7477 tSirMacAddr macAddr )
7478{
7479 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7480 hdd_adapter_t *pAdapter;
7481 VOS_STATUS status;
7482
7483 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7484
7485 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7486 {
7487 pAdapter = pAdapterNode->pAdapter;
7488
7489 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7490 macAddr, sizeof(tSirMacAddr) ) )
7491 {
7492 return pAdapter;
7493 }
7494 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7495 pAdapterNode = pNext;
7496 }
7497
7498 return NULL;
7499
7500}
7501
7502hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7503{
7504 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7505 hdd_adapter_t *pAdapter;
7506 VOS_STATUS status;
7507
7508 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7509
7510 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7511 {
7512 pAdapter = pAdapterNode->pAdapter;
7513
7514 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7515 IFNAMSIZ ) )
7516 {
7517 return pAdapter;
7518 }
7519 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7520 pAdapterNode = pNext;
7521 }
7522
7523 return NULL;
7524
7525}
7526
7527hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7528{
7529 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7530 hdd_adapter_t *pAdapter;
7531 VOS_STATUS status;
7532
7533 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7534
7535 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7536 {
7537 pAdapter = pAdapterNode->pAdapter;
7538
7539 if( pAdapter && (mode == pAdapter->device_mode) )
7540 {
7541 return pAdapter;
7542 }
7543 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7544 pAdapterNode = pNext;
7545 }
7546
7547 return NULL;
7548
7549}
7550
7551//Remove this function later
7552hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7553{
7554 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7555 hdd_adapter_t *pAdapter;
7556 VOS_STATUS status;
7557
7558 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7559
7560 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7561 {
7562 pAdapter = pAdapterNode->pAdapter;
7563
7564 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7565 {
7566 return pAdapter;
7567 }
7568
7569 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7570 pAdapterNode = pNext;
7571 }
7572
7573 return NULL;
7574
7575}
7576
Jeff Johnson295189b2012-06-20 16:38:30 -07007577/**---------------------------------------------------------------------------
7578
7579 \brief hdd_set_monitor_tx_adapter() -
7580
7581 This API initializes the adapter to be used while transmitting on monitor
7582 adapter.
7583
7584 \param - pHddCtx - Pointer to the HDD context.
7585 pAdapter - Adapter that will used for TX. This can be NULL.
7586 \return - None.
7587 --------------------------------------------------------------------------*/
7588void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7589{
7590 hdd_adapter_t *pMonAdapter;
7591
7592 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7593
7594 if( NULL != pMonAdapter )
7595 {
7596 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7597 }
7598}
Jeff Johnson295189b2012-06-20 16:38:30 -07007599/**---------------------------------------------------------------------------
7600
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307601 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007602
7603 This API returns the operating channel of the requested device mode
7604
7605 \param - pHddCtx - Pointer to the HDD context.
7606 - mode - Device mode for which operating channel is required
7607 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7608 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7609 \return - channel number. "0" id the requested device is not found OR it is not connected.
7610 --------------------------------------------------------------------------*/
7611v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7612{
7613 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7614 VOS_STATUS status;
7615 hdd_adapter_t *pAdapter;
7616 v_U8_t operatingChannel = 0;
7617
7618 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7619
7620 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7621 {
7622 pAdapter = pAdapterNode->pAdapter;
7623
7624 if( mode == pAdapter->device_mode )
7625 {
7626 switch(pAdapter->device_mode)
7627 {
7628 case WLAN_HDD_INFRA_STATION:
7629 case WLAN_HDD_P2P_CLIENT:
7630 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7631 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7632 break;
7633 case WLAN_HDD_SOFTAP:
7634 case WLAN_HDD_P2P_GO:
7635 /*softap connection info */
7636 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7637 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7638 break;
7639 default:
7640 break;
7641 }
7642
7643 break; //Found the device of interest. break the loop
7644 }
7645
7646 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7647 pAdapterNode = pNext;
7648 }
7649 return operatingChannel;
7650}
7651
7652#ifdef WLAN_FEATURE_PACKET_FILTERING
7653/**---------------------------------------------------------------------------
7654
7655 \brief hdd_set_multicast_list() -
7656
7657 This used to set the multicast address list.
7658
7659 \param - dev - Pointer to the WLAN device.
7660 - skb - Pointer to OS packet (sk_buff).
7661 \return - success/fail
7662
7663 --------------------------------------------------------------------------*/
7664static void hdd_set_multicast_list(struct net_device *dev)
7665{
7666 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007667 int mc_count;
7668 int i = 0;
7669 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307670
7671 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007672 {
7673 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307674 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007675 return;
7676 }
7677
7678 if (dev->flags & IFF_ALLMULTI)
7679 {
7680 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007681 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307682 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007683 }
7684 else
7685 {
7686 mc_count = netdev_mc_count(dev);
7687 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007688 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007689 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7690 {
7691 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007692 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307693 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007694 return;
7695 }
7696
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307697 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007698
7699 netdev_for_each_mc_addr(ha, dev) {
7700 if (i == mc_count)
7701 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307702 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7703 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007704 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007705 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307706 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007707 i++;
7708 }
7709 }
7710 return;
7711}
7712#endif
7713
7714/**---------------------------------------------------------------------------
7715
7716 \brief hdd_select_queue() -
7717
7718 This function is registered with the Linux OS for network
7719 core to decide which queue to use first.
7720
7721 \param - dev - Pointer to the WLAN device.
7722 - skb - Pointer to OS packet (sk_buff).
7723 \return - ac, Queue Index/access category corresponding to UP in IP header
7724
7725 --------------------------------------------------------------------------*/
7726v_U16_t hdd_select_queue(struct net_device *dev,
7727 struct sk_buff *skb)
7728{
7729 return hdd_wmm_select_queue(dev, skb);
7730}
7731
7732
7733/**---------------------------------------------------------------------------
7734
7735 \brief hdd_wlan_initial_scan() -
7736
7737 This function triggers the initial scan
7738
7739 \param - pAdapter - Pointer to the HDD adapter.
7740
7741 --------------------------------------------------------------------------*/
7742void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7743{
7744 tCsrScanRequest scanReq;
7745 tCsrChannelInfo channelInfo;
7746 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007747 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007748 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7749
7750 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7751 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7752 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7753
7754 if(sme_Is11dSupported(pHddCtx->hHal))
7755 {
7756 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7757 if ( HAL_STATUS_SUCCESS( halStatus ) )
7758 {
7759 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7760 if( !scanReq.ChannelInfo.ChannelList )
7761 {
7762 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7763 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007764 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007765 return;
7766 }
7767 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7768 channelInfo.numOfChannels);
7769 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7770 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007771 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007772 }
7773
7774 scanReq.scanType = eSIR_PASSIVE_SCAN;
7775 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7776 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7777 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7778 }
7779 else
7780 {
7781 scanReq.scanType = eSIR_ACTIVE_SCAN;
7782 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7783 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7784 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7785 }
7786
7787 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7788 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7789 {
7790 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7791 __func__, halStatus );
7792 }
7793
7794 if(sme_Is11dSupported(pHddCtx->hHal))
7795 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7796}
7797
Jeff Johnson295189b2012-06-20 16:38:30 -07007798/**---------------------------------------------------------------------------
7799
7800 \brief hdd_full_power_callback() - HDD full power callback function
7801
7802 This is the function invoked by SME to inform the result of a full power
7803 request issued by HDD
7804
7805 \param - callbackcontext - Pointer to cookie
7806 \param - status - result of request
7807
7808 \return - None
7809
7810 --------------------------------------------------------------------------*/
7811static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7812{
Jeff Johnson72a40512013-12-19 10:14:15 -08007813 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007814
7815 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307816 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007817
7818 if (NULL == callbackContext)
7819 {
7820 hddLog(VOS_TRACE_LEVEL_ERROR,
7821 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007822 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007823 return;
7824 }
7825
Jeff Johnson72a40512013-12-19 10:14:15 -08007826 /* there is a race condition that exists between this callback
7827 function and the caller since the caller could time out either
7828 before or while this code is executing. we use a spinlock to
7829 serialize these actions */
7830 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007831
7832 if (POWER_CONTEXT_MAGIC != pContext->magic)
7833 {
7834 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007835 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 hddLog(VOS_TRACE_LEVEL_WARN,
7837 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007838 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007839 return;
7840 }
7841
Jeff Johnson72a40512013-12-19 10:14:15 -08007842 /* context is valid so caller is still waiting */
7843
7844 /* paranoia: invalidate the magic */
7845 pContext->magic = 0;
7846
7847 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007848 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007849
7850 /* serialization is complete */
7851 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007852}
7853
7854/**---------------------------------------------------------------------------
7855
7856 \brief hdd_wlan_exit() - HDD WLAN exit function
7857
7858 This is the driver exit point (invoked during rmmod)
7859
7860 \param - pHddCtx - Pointer to the HDD Context
7861
7862 \return - None
7863
7864 --------------------------------------------------------------------------*/
7865void hdd_wlan_exit(hdd_context_t *pHddCtx)
7866{
7867 eHalStatus halStatus;
7868 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7869 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307870 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007871 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007872 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007873 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307874 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007875
7876 ENTER();
7877
Jeff Johnson88ba7742013-02-27 14:36:02 -08007878 if (VOS_FTM_MODE != hdd_get_conparam())
7879 {
7880 // Unloading, restart logic is no more required.
7881 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007882
c_hpothu5ab05e92014-06-13 17:34:05 +05307883 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7884 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007885 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307886 pAdapter = pAdapterNode->pAdapter;
7887 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007888 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307889 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7890 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7891 {
7892 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7893 hdd_UnregisterWext(pAdapter->dev);
7894 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307895
Jeff Johnson295189b2012-06-20 16:38:30 -07007896 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307897 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7898 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007899 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307900 // Cancel any outstanding scan requests. We are about to close all
7901 // of our adapters, but an adapter structure is what SME passes back
7902 // to our callback function. Hence if there are any outstanding scan
7903 // requests then there is a race condition between when the adapter
7904 // is closed and when the callback is invoked.We try to resolve that
7905 // race condition here by canceling any outstanding scans before we
7906 // close the adapters.
7907 // Note that the scans may be cancelled in an asynchronous manner,
7908 // so ideally there needs to be some kind of synchronization. Rather
7909 // than introduce a new synchronization here, we will utilize the
7910 // fact that we are about to Request Full Power, and since that is
7911 // synchronized, the expectation is that by the time Request Full
7912 // Power has completed all scans will be cancelled.
7913 if (pHddCtx->scan_info.mScanPending)
7914 {
7915 hddLog(VOS_TRACE_LEVEL_INFO,
7916 FL("abort scan mode: %d sessionId: %d"),
7917 pAdapter->device_mode,
7918 pAdapter->sessionId);
7919 hdd_abort_mac_scan(pHddCtx,
7920 pHddCtx->scan_info.sessionId,
7921 eCSR_SCAN_ABORT_DEFAULT);
7922 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007923 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307924 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007925 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307926 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007927 wlan_hdd_ftm_close(pHddCtx);
7928 goto free_hdd_ctx;
7929 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307930
Jeff Johnson295189b2012-06-20 16:38:30 -07007931 /* DeRegister with platform driver as client for Suspend/Resume */
7932 vosStatus = hddDeregisterPmOps(pHddCtx);
7933 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7934 {
7935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7936 VOS_ASSERT(0);
7937 }
7938
7939 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7940 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7941 {
7942 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007944
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007945 //Stop the traffic monitor timer
7946 if ( VOS_TIMER_STATE_RUNNING ==
7947 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7948 {
7949 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7950 }
7951
7952 // Destroy the traffic monitor timer
7953 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7954 &pHddCtx->tx_rx_trafficTmr)))
7955 {
7956 hddLog(VOS_TRACE_LEVEL_ERROR,
7957 "%s: Cannot deallocate Traffic monitor timer", __func__);
7958 }
7959
Jeff Johnson295189b2012-06-20 16:38:30 -07007960 //Disable IMPS/BMPS as we do not want the device to enter any power
7961 //save mode during shutdown
7962 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7963 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7964 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7965
7966 //Ensure that device is in full power as we will touch H/W during vos_Stop
7967 init_completion(&powerContext.completion);
7968 powerContext.magic = POWER_CONTEXT_MAGIC;
7969
7970 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7971 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7972
7973 if (eHAL_STATUS_SUCCESS != halStatus)
7974 {
7975 if (eHAL_STATUS_PMC_PENDING == halStatus)
7976 {
7977 /* request was sent -- wait for the response */
7978 lrc = wait_for_completion_interruptible_timeout(
7979 &powerContext.completion,
7980 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007981 if (lrc <= 0)
7982 {
7983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007984 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007985 }
7986 }
7987 else
7988 {
7989 hddLog(VOS_TRACE_LEVEL_ERROR,
7990 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007991 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007992 /* continue -- need to clean up as much as possible */
7993 }
7994 }
7995
Jeff Johnson72a40512013-12-19 10:14:15 -08007996 /* either we never sent a request, we sent a request and received a
7997 response or we sent a request and timed out. if we never sent a
7998 request or if we sent a request and got a response, we want to
7999 clear the magic out of paranoia. if we timed out there is a
8000 race condition such that the callback function could be
8001 executing at the same time we are. of primary concern is if the
8002 callback function had already verified the "magic" but had not
8003 yet set the completion variable when a timeout occurred. we
8004 serialize these activities by invalidating the magic while
8005 holding a shared spinlock which will cause us to block if the
8006 callback is currently executing */
8007 spin_lock(&hdd_context_lock);
8008 powerContext.magic = 0;
8009 spin_unlock(&hdd_context_lock);
8010
Yue Ma0d4891e2013-08-06 17:01:45 -07008011 hdd_debugfs_exit(pHddCtx);
8012
Jeff Johnson295189b2012-06-20 16:38:30 -07008013 // Unregister the Net Device Notifier
8014 unregister_netdevice_notifier(&hdd_netdev_notifier);
8015
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 hdd_stop_all_adapters( pHddCtx );
8017
Jeff Johnson295189b2012-06-20 16:38:30 -07008018#ifdef WLAN_BTAMP_FEATURE
8019 vosStatus = WLANBAP_Stop(pVosContext);
8020 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8021 {
8022 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8023 "%s: Failed to stop BAP",__func__);
8024 }
8025#endif //WLAN_BTAMP_FEATURE
8026
8027 //Stop all the modules
8028 vosStatus = vos_stop( pVosContext );
8029 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8030 {
8031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8032 "%s: Failed to stop VOSS",__func__);
8033 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8034 }
8035
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008037 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008038
8039 //Close the scheduler before calling vos_close to make sure no thread is
8040 // scheduled after the each module close is called i.e after all the data
8041 // structures are freed.
8042 vosStatus = vos_sched_close( pVosContext );
8043 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8044 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8045 "%s: Failed to close VOSS Scheduler",__func__);
8046 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8047 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008048#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008049#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8050 /* Destroy the wake lock */
8051 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8052#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008053 /* Destroy the wake lock */
8054 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008055#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008056
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308057#ifdef CONFIG_ENABLE_LINUX_REG
8058 vosStatus = vos_nv_close();
8059 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8060 {
8061 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8062 "%s: Failed to close NV", __func__);
8063 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8064 }
8065#endif
8066
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 //Close VOSS
8068 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8069 vos_close(pVosContext);
8070
Jeff Johnson295189b2012-06-20 16:38:30 -07008071 //Close Watchdog
8072 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8073 vos_watchdog_close(pVosContext);
8074
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308075 //Clean up HDD Nlink Service
8076 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308077
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308078#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308079 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308080 {
8081 wlan_logging_sock_deactivate_svc();
8082 }
8083#endif
8084
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308085#ifdef WLAN_KD_READY_NOTIFIER
8086 nl_srv_exit(pHddCtx->ptt_pid);
8087#else
8088 nl_srv_exit();
8089#endif /* WLAN_KD_READY_NOTIFIER */
8090
8091
Jeff Johnson295189b2012-06-20 16:38:30 -07008092 hdd_close_all_adapters( pHddCtx );
8093
Jeff Johnson295189b2012-06-20 16:38:30 -07008094 /* free the power on lock from platform driver */
8095 if (free_riva_power_on_lock("wlan"))
8096 {
8097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8098 __func__);
8099 }
8100
Jeff Johnson88ba7742013-02-27 14:36:02 -08008101free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308102
8103 //Free up dynamically allocated members inside HDD Adapter
8104 if (pHddCtx->cfg_ini)
8105 {
8106 kfree(pHddCtx->cfg_ini);
8107 pHddCtx->cfg_ini= NULL;
8108 }
8109
Leo Changf04ddad2013-09-18 13:46:38 -07008110 /* FTM mode, WIPHY did not registered
8111 If un-register here, system crash will happen */
8112 if (VOS_FTM_MODE != hdd_get_conparam())
8113 {
8114 wiphy_unregister(wiphy) ;
8115 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008116 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 if (hdd_is_ssr_required())
8118 {
8119 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008120 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008121 msleep(5000);
8122 }
8123 hdd_set_ssr_required (VOS_FALSE);
8124}
8125
8126
8127/**---------------------------------------------------------------------------
8128
8129 \brief hdd_update_config_from_nv() - Function to update the contents of
8130 the running configuration with parameters taken from NV storage
8131
8132 \param - pHddCtx - Pointer to the HDD global context
8133
8134 \return - VOS_STATUS_SUCCESS if successful
8135
8136 --------------------------------------------------------------------------*/
8137static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8138{
Jeff Johnson295189b2012-06-20 16:38:30 -07008139 v_BOOL_t itemIsValid = VOS_FALSE;
8140 VOS_STATUS status;
8141 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8142 v_U8_t macLoop;
8143
8144 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8145 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8146 if(status != VOS_STATUS_SUCCESS)
8147 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008148 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 return VOS_STATUS_E_FAILURE;
8150 }
8151
8152 if (itemIsValid == VOS_TRUE)
8153 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008154 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008155 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8156 VOS_MAX_CONCURRENCY_PERSONA);
8157 if(status != VOS_STATUS_SUCCESS)
8158 {
8159 /* Get MAC from NV fail, not update CFG info
8160 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008161 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008162 return VOS_STATUS_E_FAILURE;
8163 }
8164
8165 /* If first MAC is not valid, treat all others are not valid
8166 * Then all MACs will be got from ini file */
8167 if(vos_is_macaddr_zero(&macFromNV[0]))
8168 {
8169 /* MAC address in NV file is not configured yet */
8170 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8171 return VOS_STATUS_E_INVAL;
8172 }
8173
8174 /* Get MAC address from NV, update CFG info */
8175 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8176 {
8177 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8178 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308179 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 /* This MAC is not valid, skip it
8181 * This MAC will be got from ini file */
8182 }
8183 else
8184 {
8185 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8186 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8187 VOS_MAC_ADDR_SIZE);
8188 }
8189 }
8190 }
8191 else
8192 {
8193 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8194 return VOS_STATUS_E_FAILURE;
8195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008196
Jeff Johnson295189b2012-06-20 16:38:30 -07008197
8198 return VOS_STATUS_SUCCESS;
8199}
8200
8201/**---------------------------------------------------------------------------
8202
8203 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8204
8205 \param - pAdapter - Pointer to the HDD
8206
8207 \return - None
8208
8209 --------------------------------------------------------------------------*/
8210VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8211{
8212 eHalStatus halStatus;
8213 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308214 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008215
Jeff Johnson295189b2012-06-20 16:38:30 -07008216
8217 // Send ready indication to the HDD. This will kick off the MAC
8218 // into a 'running' state and should kick off an initial scan.
8219 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8220 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8221 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308222 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008223 "code %08d [x%08x]",__func__, halStatus, halStatus );
8224 return VOS_STATUS_E_FAILURE;
8225 }
8226
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308227 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008228 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8229 // And RIVA will crash
8230 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8231 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308232 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8233 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8234
8235
Jeff Johnson295189b2012-06-20 16:38:30 -07008236 return VOS_STATUS_SUCCESS;
8237}
8238
Jeff Johnson295189b2012-06-20 16:38:30 -07008239/* wake lock APIs for HDD */
8240void hdd_prevent_suspend(void)
8241{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008242#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008243 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008244#else
8245 wcnss_prevent_suspend();
8246#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008247}
8248
8249void hdd_allow_suspend(void)
8250{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008251#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008252 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008253#else
8254 wcnss_allow_suspend();
8255#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008256}
8257
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308258void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008259{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008260#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008261 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008262#else
8263 /* Do nothing as there is no API in wcnss for timeout*/
8264#endif
8265}
8266
Jeff Johnson295189b2012-06-20 16:38:30 -07008267/**---------------------------------------------------------------------------
8268
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008269 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8270 information between Host and Riva
8271
8272 This function gets reported version of FW
8273 It also finds the version of Riva headers used to compile the host
8274 It compares the above two and prints a warning if they are different
8275 It gets the SW and HW version string
8276 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8277 indicating the features they support through a bitmap
8278
8279 \param - pHddCtx - Pointer to HDD context
8280
8281 \return - void
8282
8283 --------------------------------------------------------------------------*/
8284
8285void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8286{
8287
8288 tSirVersionType versionCompiled;
8289 tSirVersionType versionReported;
8290 tSirVersionString versionString;
8291 tANI_U8 fwFeatCapsMsgSupported = 0;
8292 VOS_STATUS vstatus;
8293
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008294 memset(&versionCompiled, 0, sizeof(versionCompiled));
8295 memset(&versionReported, 0, sizeof(versionReported));
8296
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008297 /* retrieve and display WCNSS version information */
8298 do {
8299
8300 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8301 &versionCompiled);
8302 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8303 {
8304 hddLog(VOS_TRACE_LEVEL_FATAL,
8305 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008306 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008307 break;
8308 }
8309
8310 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8311 &versionReported);
8312 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8313 {
8314 hddLog(VOS_TRACE_LEVEL_FATAL,
8315 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008316 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008317 break;
8318 }
8319
8320 if ((versionCompiled.major != versionReported.major) ||
8321 (versionCompiled.minor != versionReported.minor) ||
8322 (versionCompiled.version != versionReported.version) ||
8323 (versionCompiled.revision != versionReported.revision))
8324 {
8325 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8326 "Host expected %u.%u.%u.%u\n",
8327 WLAN_MODULE_NAME,
8328 (int)versionReported.major,
8329 (int)versionReported.minor,
8330 (int)versionReported.version,
8331 (int)versionReported.revision,
8332 (int)versionCompiled.major,
8333 (int)versionCompiled.minor,
8334 (int)versionCompiled.version,
8335 (int)versionCompiled.revision);
8336 }
8337 else
8338 {
8339 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8340 WLAN_MODULE_NAME,
8341 (int)versionReported.major,
8342 (int)versionReported.minor,
8343 (int)versionReported.version,
8344 (int)versionReported.revision);
8345 }
8346
8347 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8348 versionString,
8349 sizeof(versionString));
8350 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8351 {
8352 hddLog(VOS_TRACE_LEVEL_FATAL,
8353 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008354 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008355 break;
8356 }
8357
8358 pr_info("%s: WCNSS software version %s\n",
8359 WLAN_MODULE_NAME, versionString);
8360
8361 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8362 versionString,
8363 sizeof(versionString));
8364 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8365 {
8366 hddLog(VOS_TRACE_LEVEL_FATAL,
8367 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008368 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008369 break;
8370 }
8371
8372 pr_info("%s: WCNSS hardware version %s\n",
8373 WLAN_MODULE_NAME, versionString);
8374
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008375 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8376 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008377 send the message only if it the riva is 1.1
8378 minor numbers for different riva branches:
8379 0 -> (1.0)Mainline Build
8380 1 -> (1.1)Mainline Build
8381 2->(1.04) Stability Build
8382 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008383 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008384 ((versionReported.minor>=1) && (versionReported.version>=1)))
8385 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8386 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008387
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008388 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008389 {
8390#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8391 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8392 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8393#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008394 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8395 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8396 {
8397 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8398 }
8399
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008400 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008401 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008402
8403 } while (0);
8404
8405}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308406void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8407{
8408 struct sk_buff *skb;
8409 struct nlmsghdr *nlh;
8410 tAniMsgHdr *ani_hdr;
8411
8412 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8413
8414 if(skb == NULL) {
8415 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8416 "%s: alloc_skb failed", __func__);
8417 return;
8418 }
8419
8420 nlh = (struct nlmsghdr *)skb->data;
8421 nlh->nlmsg_pid = 0; /* from kernel */
8422 nlh->nlmsg_flags = 0;
8423 nlh->nlmsg_seq = 0;
8424 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8425
8426 ani_hdr = NLMSG_DATA(nlh);
8427 ani_hdr->type = type;
8428
8429 switch(type) {
8430 case WLAN_SVC_SAP_RESTART_IND:
8431 ani_hdr->length = 0;
8432 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8433 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8434 break;
8435 default:
8436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8437 "Attempt to send unknown nlink message %d", type);
8438 kfree_skb(skb);
8439 return;
8440 }
8441
8442 nl_srv_bcast(skb);
8443
8444 return;
8445}
8446
8447
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008448
8449/**---------------------------------------------------------------------------
8450
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308451 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8452
8453 \param - pHddCtx - Pointer to the hdd context
8454
8455 \return - true if hardware supports 5GHz
8456
8457 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308458boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308459{
8460 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8461 * then hardware support 5Ghz.
8462 */
8463 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8464 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308465 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308466 return true;
8467 }
8468 else
8469 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308470 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308471 __func__);
8472 return false;
8473 }
8474}
8475
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308476/**---------------------------------------------------------------------------
8477
8478 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8479 generate function
8480
8481 This is generate the random mac address for WLAN interface
8482
8483 \param - pHddCtx - Pointer to HDD context
8484 idx - Start interface index to get auto
8485 generated mac addr.
8486 mac_addr - Mac address
8487
8488 \return - 0 for success, < 0 for failure
8489
8490 --------------------------------------------------------------------------*/
8491
8492static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8493 int idx, v_MACADDR_t mac_addr)
8494{
8495 int i;
8496 unsigned int serialno;
8497 serialno = wcnss_get_serial_number();
8498
8499 if (0 != serialno)
8500 {
8501 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8502 bytes of the serial number that can be used to generate
8503 the other 3 bytes of the MAC address. Mask off all but
8504 the lower 3 bytes (this will also make sure we don't
8505 overflow in the next step) */
8506 serialno &= 0x00FFFFFF;
8507
8508 /* we need a unique address for each session */
8509 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8510
8511 /* autogen other Mac addresses */
8512 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8513 {
8514 /* start with the entire default address */
8515 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8516 /* then replace the lower 3 bytes */
8517 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8518 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8519 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8520
8521 serialno++;
8522 hddLog(VOS_TRACE_LEVEL_ERROR,
8523 "%s: Derived Mac Addr: "
8524 MAC_ADDRESS_STR, __func__,
8525 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8526 }
8527
8528 }
8529 else
8530 {
8531 hddLog(LOGE, FL("Failed to Get Serial NO"));
8532 return -1;
8533 }
8534 return 0;
8535}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308536
8537/**---------------------------------------------------------------------------
8538
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308539 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8540 completed to flush out the scan results
8541
8542 11d scan is done during driver load and is a passive scan on all
8543 channels supported by the device, 11d scans may find some APs on
8544 frequencies which are forbidden to be used in the regulatory domain
8545 the device is operating in. If these APs are notified to the supplicant
8546 it may try to connect to these APs, thus flush out all the scan results
8547 which are present in SME after 11d scan is done.
8548
8549 \return - eHalStatus
8550
8551 --------------------------------------------------------------------------*/
8552static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8553 tANI_U32 scanId, eCsrScanStatus status)
8554{
8555 ENTER();
8556
8557 sme_ScanFlushResult(halHandle, 0);
8558
8559 EXIT();
8560
8561 return eHAL_STATUS_SUCCESS;
8562}
8563
8564/**---------------------------------------------------------------------------
8565
Jeff Johnson295189b2012-06-20 16:38:30 -07008566 \brief hdd_wlan_startup() - HDD init function
8567
8568 This is the driver startup code executed once a WLAN device has been detected
8569
8570 \param - dev - Pointer to the underlying device
8571
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008572 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008573
8574 --------------------------------------------------------------------------*/
8575
8576int hdd_wlan_startup(struct device *dev )
8577{
8578 VOS_STATUS status;
8579 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008580 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008581 hdd_context_t *pHddCtx = NULL;
8582 v_CONTEXT_t pVosContext= NULL;
8583#ifdef WLAN_BTAMP_FEATURE
8584 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8585 WLANBAP_ConfigType btAmpConfig;
8586 hdd_config_t *pConfig;
8587#endif
8588 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008589 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308590 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008591
8592 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008593 /*
8594 * cfg80211: wiphy allocation
8595 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308596 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008597
8598 if(wiphy == NULL)
8599 {
8600 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008601 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 }
8603
8604 pHddCtx = wiphy_priv(wiphy);
8605
Jeff Johnson295189b2012-06-20 16:38:30 -07008606 //Initialize the adapter context to zeros.
8607 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8608
Jeff Johnson295189b2012-06-20 16:38:30 -07008609 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008610 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308611 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008612
8613 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8614
8615 /*Get vos context here bcoz vos_open requires it*/
8616 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8617
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008618 if(pVosContext == NULL)
8619 {
8620 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8621 goto err_free_hdd_context;
8622 }
8623
Jeff Johnson295189b2012-06-20 16:38:30 -07008624 //Save the Global VOSS context in adapter context for future.
8625 pHddCtx->pvosContext = pVosContext;
8626
8627 //Save the adapter context in global context for future.
8628 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8629
Jeff Johnson295189b2012-06-20 16:38:30 -07008630 pHddCtx->parent_dev = dev;
8631
8632 init_completion(&pHddCtx->full_pwr_comp_var);
8633 init_completion(&pHddCtx->standby_comp_var);
8634 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008635 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008636 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308637 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308638 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008639
8640#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008641 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008642#else
8643 init_completion(&pHddCtx->driver_crda_req);
8644#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008645
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308646 spin_lock_init(&pHddCtx->schedScan_lock);
8647
Jeff Johnson295189b2012-06-20 16:38:30 -07008648 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8649
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308650#ifdef FEATURE_WLAN_TDLS
8651 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8652 * invoked by other instances also) to protect the concurrent
8653 * access for the Adapters by TDLS module.
8654 */
8655 mutex_init(&pHddCtx->tdls_lock);
8656#endif
Siddharth Bhal76972212014-10-15 16:22:51 +05308657 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Agarwal Ashish1f422872014-07-22 00:11:55 +05308658 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308659
Agarwal Ashish1f422872014-07-22 00:11:55 +05308660 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008661 // Load all config first as TL config is needed during vos_open
8662 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8663 if(pHddCtx->cfg_ini == NULL)
8664 {
8665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8666 goto err_free_hdd_context;
8667 }
8668
8669 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8670
8671 // Read and parse the qcom_cfg.ini file
8672 status = hdd_parse_config_ini( pHddCtx );
8673 if ( VOS_STATUS_SUCCESS != status )
8674 {
8675 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8676 __func__, WLAN_INI_FILE);
8677 goto err_config;
8678 }
Arif Hussaind5218912013-12-05 01:10:55 -08008679#ifdef MEMORY_DEBUG
8680 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8681 vos_mem_init();
8682
8683 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8684 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8685#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008686
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308687 /* INI has been read, initialise the configuredMcastBcastFilter with
8688 * INI value as this will serve as the default value
8689 */
8690 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8691 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8692 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308693
8694 if (false == hdd_is_5g_supported(pHddCtx))
8695 {
8696 //5Ghz is not supported.
8697 if (1 != pHddCtx->cfg_ini->nBandCapability)
8698 {
8699 hddLog(VOS_TRACE_LEVEL_INFO,
8700 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8701 pHddCtx->cfg_ini->nBandCapability = 1;
8702 }
8703 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308704
8705 /* If SNR Monitoring is enabled, FW has to parse all beacons
8706 * for calcaluting and storing the average SNR, so set Nth beacon
8707 * filter to 1 to enable FW to parse all the beaocons
8708 */
8709 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8710 {
8711 /* The log level is deliberately set to WARN as overriding
8712 * nthBeaconFilter to 1 will increase power cosumption and this
8713 * might just prove helpful to detect the power issue.
8714 */
8715 hddLog(VOS_TRACE_LEVEL_WARN,
8716 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8717 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8718 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008719 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308720 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008721 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008722 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008723 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008724 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8725 {
8726 hddLog(VOS_TRACE_LEVEL_FATAL,
8727 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8728 goto err_config;
8729 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008731
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008732 // Update VOS trace levels based upon the cfg.ini
8733 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8734 pHddCtx->cfg_ini->vosTraceEnableBAP);
8735 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8736 pHddCtx->cfg_ini->vosTraceEnableTL);
8737 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8738 pHddCtx->cfg_ini->vosTraceEnableWDI);
8739 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8740 pHddCtx->cfg_ini->vosTraceEnableHDD);
8741 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8742 pHddCtx->cfg_ini->vosTraceEnableSME);
8743 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8744 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308745 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8746 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008747 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8748 pHddCtx->cfg_ini->vosTraceEnableWDA);
8749 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8750 pHddCtx->cfg_ini->vosTraceEnableSYS);
8751 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8752 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008753 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8754 pHddCtx->cfg_ini->vosTraceEnableSAP);
8755 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8756 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008757
Jeff Johnson295189b2012-06-20 16:38:30 -07008758 // Update WDI trace levels based upon the cfg.ini
8759 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8760 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8761 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8762 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8763 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8764 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8765 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8766 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008767
Jeff Johnson88ba7742013-02-27 14:36:02 -08008768 if (VOS_FTM_MODE == hdd_get_conparam())
8769 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008770 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8771 {
8772 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8773 goto err_free_hdd_context;
8774 }
8775 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308776
8777 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008778 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008779 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008780
Jeff Johnson88ba7742013-02-27 14:36:02 -08008781 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008782 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8783 {
8784 status = vos_watchdog_open(pVosContext,
8785 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8786
8787 if(!VOS_IS_STATUS_SUCCESS( status ))
8788 {
8789 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308790 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 }
8792 }
8793
8794 pHddCtx->isLogpInProgress = FALSE;
8795 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8796
Amar Singhala49cbc52013-10-08 18:37:44 -07008797#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008798 /* initialize the NV module. This is required so that
8799 we can initialize the channel information in wiphy
8800 from the NV.bin data. The channel information in
8801 wiphy needs to be initialized before wiphy registration */
8802
8803 status = vos_nv_open();
8804 if (!VOS_IS_STATUS_SUCCESS(status))
8805 {
8806 /* NV module cannot be initialized */
8807 hddLog( VOS_TRACE_LEVEL_FATAL,
8808 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05308809 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07008810 }
8811
8812 status = vos_init_wiphy_from_nv_bin();
8813 if (!VOS_IS_STATUS_SUCCESS(status))
8814 {
8815 /* NV module cannot be initialized */
8816 hddLog( VOS_TRACE_LEVEL_FATAL,
8817 "%s: vos_init_wiphy failed", __func__);
8818 goto err_vos_nv_close;
8819 }
8820
Amar Singhala49cbc52013-10-08 18:37:44 -07008821#endif
8822
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308823 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008824 if ( !VOS_IS_STATUS_SUCCESS( status ))
8825 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008826 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308827 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008828 }
8829
Jeff Johnson295189b2012-06-20 16:38:30 -07008830 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8831
8832 if ( NULL == pHddCtx->hHal )
8833 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008834 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008835 goto err_vosclose;
8836 }
8837
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008838 status = vos_preStart( pHddCtx->pvosContext );
8839 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8840 {
8841 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308842 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008843 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008844
Arif Hussaineaf68602013-12-30 23:10:44 -08008845 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8846 {
8847 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8848 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8849 __func__, enable_dfs_chan_scan);
8850 }
8851 if (0 == enable_11d || 1 == enable_11d)
8852 {
8853 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8854 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8855 __func__, enable_11d);
8856 }
8857
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008858 /* Note that the vos_preStart() sequence triggers the cfg download.
8859 The cfg download must occur before we update the SME config
8860 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008861 status = hdd_set_sme_config( pHddCtx );
8862
8863 if ( VOS_STATUS_SUCCESS != status )
8864 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008865 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308866 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008868
Jeff Johnson295189b2012-06-20 16:38:30 -07008869 /* In the integrated architecture we update the configuration from
8870 the INI file and from NV before vOSS has been started so that
8871 the final contents are available to send down to the cCPU */
8872
8873 // Apply the cfg.ini to cfg.dat
8874 if (FALSE == hdd_update_config_dat(pHddCtx))
8875 {
8876 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308877 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008878 }
8879
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308880 // Get mac addr from platform driver
8881 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8882
8883 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008884 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308885 /* Store the mac addr for first interface */
8886 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8887
8888 hddLog(VOS_TRACE_LEVEL_ERROR,
8889 "%s: WLAN Mac Addr: "
8890 MAC_ADDRESS_STR, __func__,
8891 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8892
8893 /* Here, passing Arg2 as 1 because we do not want to change the
8894 last 3 bytes (means non OUI bytes) of first interface mac
8895 addr.
8896 */
8897 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8898 {
8899 hddLog(VOS_TRACE_LEVEL_ERROR,
8900 "%s: Failed to generate wlan interface mac addr "
8901 "using MAC from ini file ", __func__);
8902 }
8903 }
8904 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8905 {
8906 // Apply the NV to cfg.dat
8907 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008908#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8909 /* There was not a valid set of MAC Addresses in NV. See if the
8910 default addresses were modified by the cfg.ini settings. If so,
8911 we'll use them, but if not, we'll autogenerate a set of MAC
8912 addresses based upon the device serial number */
8913
8914 static const v_MACADDR_t default_address =
8915 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008916
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308917 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8918 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 {
8920 /* cfg.ini has the default address, invoke autogen logic */
8921
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308922 /* Here, passing Arg2 as 0 because we want to change the
8923 last 3 bytes (means non OUI bytes) of all the interfaces
8924 mac addr.
8925 */
8926 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8927 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008928 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308929 hddLog(VOS_TRACE_LEVEL_ERROR,
8930 "%s: Failed to generate wlan interface mac addr "
8931 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8932 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008933 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008934 }
8935 else
8936#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8937 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008938 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008939 "%s: Invalid MAC address in NV, using MAC from ini file "
8940 MAC_ADDRESS_STR, __func__,
8941 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8942 }
8943 }
8944 {
8945 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308946
8947 /* Set the MAC Address Currently this is used by HAL to
8948 * add self sta. Remove this once self sta is added as
8949 * part of session open.
8950 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008951 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8952 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8953 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308954
Jeff Johnson295189b2012-06-20 16:38:30 -07008955 if (!HAL_STATUS_SUCCESS( halStatus ))
8956 {
8957 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8958 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308959 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008960 }
8961 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008962
8963 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8964 Note: Firmware image will be read and downloaded inside vos_start API */
8965 status = vos_start( pHddCtx->pvosContext );
8966 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8967 {
8968 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308969 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008970 }
8971
Leo Chang6cec3e22014-01-21 15:33:49 -08008972#ifdef FEATURE_WLAN_CH_AVOID
8973 /* Plug in avoid channel notification callback
8974 * This should happen before ADD_SELF_STA
8975 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308976
8977 /* check the Channel Avoidance is enabled */
8978 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8979 {
8980 sme_AddChAvoidCallback(pHddCtx->hHal,
8981 hdd_hostapd_ch_avoid_cb);
8982 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008983#endif /* FEATURE_WLAN_CH_AVOID */
8984
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008985 /* Exchange capability info between Host and FW and also get versioning info from FW */
8986 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008987
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308988#ifdef CONFIG_ENABLE_LINUX_REG
8989 status = wlan_hdd_init_channels(pHddCtx);
8990 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8991 {
8992 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8993 __func__);
8994 goto err_vosstop;
8995 }
8996#endif
8997
Jeff Johnson295189b2012-06-20 16:38:30 -07008998 status = hdd_post_voss_start_config( pHddCtx );
8999 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9000 {
9001 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
9002 __func__);
9003 goto err_vosstop;
9004 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009005
9006#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309007 wlan_hdd_cfg80211_update_reg_info( wiphy );
9008
9009 /* registration of wiphy dev with cfg80211 */
9010 if (0 > wlan_hdd_cfg80211_register(wiphy))
9011 {
9012 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9013 goto err_vosstop;
9014 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009015#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009016
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309017#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309018 /* registration of wiphy dev with cfg80211 */
9019 if (0 > wlan_hdd_cfg80211_register(wiphy))
9020 {
9021 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9022 goto err_vosstop;
9023 }
9024
Agarwal Ashish6db9d532014-09-30 18:19:10 +05309025 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309026 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9027 {
9028 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
9029 __func__);
9030 goto err_unregister_wiphy;
9031 }
9032#endif
9033
Jeff Johnson295189b2012-06-20 16:38:30 -07009034 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9035 {
9036 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9037 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9038 }
9039 else
9040 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009041 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9042 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9043 if (pAdapter != NULL)
9044 {
kaidde69982014-06-18 13:23:21 +08009045 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009046 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309047 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9048 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9049 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009050
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309051 /* Generate the P2P Device Address. This consists of the device's
9052 * primary MAC address with the locally administered bit set.
9053 */
9054 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009055 }
9056 else
9057 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309058 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9059 if (p2p_dev_addr != NULL)
9060 {
9061 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9062 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9063 }
9064 else
9065 {
9066 hddLog(VOS_TRACE_LEVEL_FATAL,
9067 "%s: Failed to allocate mac_address for p2p_device",
9068 __func__);
9069 goto err_close_adapter;
9070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009071 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009072
9073 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9074 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9075 if ( NULL == pP2pAdapter )
9076 {
9077 hddLog(VOS_TRACE_LEVEL_FATAL,
9078 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009079 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009080 goto err_close_adapter;
9081 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009082 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009083 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009084
9085 if( pAdapter == NULL )
9086 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9088 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009089 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009090
Arif Hussain66559122013-11-21 10:11:40 -08009091 if (country_code)
9092 {
9093 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009094 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009095 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9096#ifndef CONFIG_ENABLE_LINUX_REG
9097 hdd_checkandupdate_phymode(pAdapter, country_code);
9098#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009099 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9100 (void *)(tSmeChangeCountryCallback)
9101 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009102 country_code,
9103 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309104 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009105 if (eHAL_STATUS_SUCCESS == ret)
9106 {
Arif Hussaincb607082013-12-20 11:57:42 -08009107 ret = wait_for_completion_interruptible_timeout(
9108 &pAdapter->change_country_code,
9109 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9110
9111 if (0 >= ret)
9112 {
9113 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9114 "%s: SME while setting country code timed out", __func__);
9115 }
Arif Hussain66559122013-11-21 10:11:40 -08009116 }
9117 else
9118 {
Arif Hussaincb607082013-12-20 11:57:42 -08009119 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9120 "%s: SME Change Country code from module param fail ret=%d",
9121 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009122 }
9123 }
9124
Jeff Johnson295189b2012-06-20 16:38:30 -07009125#ifdef WLAN_BTAMP_FEATURE
9126 vStatus = WLANBAP_Open(pVosContext);
9127 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9128 {
9129 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9130 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009131 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009132 }
9133
9134 vStatus = BSL_Init(pVosContext);
9135 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9136 {
9137 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9138 "%s: Failed to Init BSL",__func__);
9139 goto err_bap_close;
9140 }
9141 vStatus = WLANBAP_Start(pVosContext);
9142 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9143 {
9144 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9145 "%s: Failed to start TL",__func__);
9146 goto err_bap_close;
9147 }
9148
9149 pConfig = pHddCtx->cfg_ini;
9150 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9151 status = WLANBAP_SetConfig(&btAmpConfig);
9152
9153#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009154
Mihir Shete9c238772014-10-15 14:35:16 +05309155 /*
9156 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
9157 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
9158 * which is greater than 0xf. So the below check is safe to make
9159 * sure that there is no entry for UapsdMask in the ini
9160 */
9161 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
9162 {
9163 if(IS_DYNAMIC_WMM_PS_ENABLED)
9164 {
9165 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
9166 __func__);
9167 pHddCtx->cfg_ini->UapsdMask =
9168 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
9169 }
9170 else
9171 {
9172 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
9173 __func__);
9174 pHddCtx->cfg_ini->UapsdMask =
9175 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
9176 }
9177 }
9178
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009179#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9180 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9181 {
9182 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9183 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9184 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9185 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9186 }
9187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009188
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309189 wlan_hdd_tdls_init(pHddCtx);
9190
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309191 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9192
Jeff Johnson295189b2012-06-20 16:38:30 -07009193 /* Register with platform driver as client for Suspend/Resume */
9194 status = hddRegisterPmOps(pHddCtx);
9195 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9196 {
9197 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9198#ifdef WLAN_BTAMP_FEATURE
9199 goto err_bap_stop;
9200#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009201 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009202#endif //WLAN_BTAMP_FEATURE
9203 }
9204
Yue Ma0d4891e2013-08-06 17:01:45 -07009205 /* Open debugfs interface */
9206 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9207 {
9208 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9209 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009210 }
9211
Jeff Johnson295189b2012-06-20 16:38:30 -07009212 /* Register TM level change handler function to the platform */
9213 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9214 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9215 {
9216 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9217 goto err_unregister_pmops;
9218 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009219
9220 /* register for riva power on lock to platform driver */
9221 if (req_riva_power_on_lock("wlan"))
9222 {
9223 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9224 __func__);
9225 goto err_unregister_pmops;
9226 }
9227
Jeff Johnson295189b2012-06-20 16:38:30 -07009228 // register net device notifier for device change notification
9229 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9230
9231 if(ret < 0)
9232 {
9233 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9234 goto err_free_power_on_lock;
9235 }
9236
9237 //Initialize the nlink service
9238 if(nl_srv_init() != 0)
9239 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309240 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 goto err_reg_netdev;
9242 }
9243
Leo Chang4ce1cc52013-10-21 18:27:15 -07009244#ifdef WLAN_KD_READY_NOTIFIER
9245 pHddCtx->kd_nl_init = 1;
9246#endif /* WLAN_KD_READY_NOTIFIER */
9247
Jeff Johnson295189b2012-06-20 16:38:30 -07009248 //Initialize the BTC service
9249 if(btc_activate_service(pHddCtx) != 0)
9250 {
9251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9252 goto err_nl_srv;
9253 }
9254
9255#ifdef PTT_SOCK_SVC_ENABLE
9256 //Initialize the PTT service
9257 if(ptt_sock_activate_svc(pHddCtx) != 0)
9258 {
9259 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9260 goto err_nl_srv;
9261 }
9262#endif
9263
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309264#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9265 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9266 {
Deepthi Gowri78083a32014-11-04 12:55:51 +05309267 if(wlan_logging_sock_activate_svc(
9268 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9269 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9270 {
9271 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9272 " failed", __func__);
9273 goto err_nl_srv;
9274 }
9275 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
9276 //EAPOL and DHCP
9277 pHddCtx->cfg_ini->enableDhcpDebug = CFG_DEBUG_DHCP_ENABLE;
9278 pHddCtx->cfg_ini->gEnableDebugLog = VOS_PKT_PROTO_TYPE_EAPOL;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309279 }
9280#endif
9281
Jeff Johnson295189b2012-06-20 16:38:30 -07009282 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009283 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009284 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009285 /* Action frame registered in one adapter which will
9286 * applicable to all interfaces
9287 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309288 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009289 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009290
9291 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +05309292 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009293
Jeff Johnson295189b2012-06-20 16:38:30 -07009294
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009295#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009296#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9297 /* Initialize the wake lcok */
9298 wake_lock_init(&pHddCtx->rx_wake_lock,
9299 WAKE_LOCK_SUSPEND,
9300 "qcom_rx_wakelock");
9301#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009302 /* Initialize the wake lcok */
9303 wake_lock_init(&pHddCtx->sap_wake_lock,
9304 WAKE_LOCK_SUSPEND,
9305 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009306#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009307
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009308 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9309 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009310
Katya Nigam5c306ea2014-06-19 15:39:54 +05309311 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009312 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9313 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309314
9315#ifdef FEATURE_WLAN_SCAN_PNO
9316 /*SME must send channel update configuration to RIVA*/
9317 sme_UpdateChannelConfig(pHddCtx->hHal);
9318#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309319 /* Send the update default channel list to the FW*/
9320 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309321#ifndef CONFIG_ENABLE_LINUX_REG
9322 /*updating wiphy so that regulatory user hints can be processed*/
9323 if (wiphy)
9324 {
9325 regulatory_hint(wiphy, "00");
9326 }
9327#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009328 // Initialize the restart logic
9329 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309330
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009331 //Register the traffic monitor timer now
9332 if ( pHddCtx->cfg_ini->dynSplitscan)
9333 {
9334 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9335 VOS_TIMER_TYPE_SW,
9336 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9337 (void *)pHddCtx);
9338 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309339#ifdef WLAN_FEATURE_EXTSCAN
9340 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9341 wlan_hdd_cfg80211_extscan_callback,
9342 pHddCtx);
9343#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009344 goto success;
9345
9346err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009347#ifdef WLAN_KD_READY_NOTIFIER
9348 nl_srv_exit(pHddCtx->ptt_pid);
9349#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009350 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009351#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009352err_reg_netdev:
9353 unregister_netdevice_notifier(&hdd_netdev_notifier);
9354
9355err_free_power_on_lock:
9356 free_riva_power_on_lock("wlan");
9357
9358err_unregister_pmops:
9359 hddDevTmUnregisterNotifyCallback(pHddCtx);
9360 hddDeregisterPmOps(pHddCtx);
9361
Yue Ma0d4891e2013-08-06 17:01:45 -07009362 hdd_debugfs_exit(pHddCtx);
9363
Jeff Johnson295189b2012-06-20 16:38:30 -07009364#ifdef WLAN_BTAMP_FEATURE
9365err_bap_stop:
9366 WLANBAP_Stop(pVosContext);
9367#endif
9368
9369#ifdef WLAN_BTAMP_FEATURE
9370err_bap_close:
9371 WLANBAP_Close(pVosContext);
9372#endif
9373
Jeff Johnson295189b2012-06-20 16:38:30 -07009374err_close_adapter:
9375 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309376#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309377err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309378#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309379 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009380err_vosstop:
9381 vos_stop(pVosContext);
9382
Amar Singhala49cbc52013-10-08 18:37:44 -07009383err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009384 status = vos_sched_close( pVosContext );
9385 if (!VOS_IS_STATUS_SUCCESS(status)) {
9386 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9387 "%s: Failed to close VOSS Scheduler", __func__);
9388 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9389 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009390 vos_close(pVosContext );
9391
Amar Singhal0a402232013-10-11 20:57:16 -07009392err_vos_nv_close:
9393
c_hpothue6a36282014-03-19 12:27:38 +05309394#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009395 vos_nv_close();
9396
c_hpothu70f8d812014-03-22 22:59:23 +05309397#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009398
9399err_wdclose:
9400 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9401 vos_watchdog_close(pVosContext);
9402
Jeff Johnson295189b2012-06-20 16:38:30 -07009403err_config:
9404 kfree(pHddCtx->cfg_ini);
9405 pHddCtx->cfg_ini= NULL;
9406
9407err_free_hdd_context:
9408 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009409 wiphy_free(wiphy) ;
9410 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009411 VOS_BUG(1);
9412
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009413 if (hdd_is_ssr_required())
9414 {
9415 /* WDI timeout had happened during load, so SSR is needed here */
9416 subsystem_restart("wcnss");
9417 msleep(5000);
9418 }
9419 hdd_set_ssr_required (VOS_FALSE);
9420
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009421 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009422
9423success:
9424 EXIT();
9425 return 0;
9426}
9427
9428/**---------------------------------------------------------------------------
9429
Jeff Johnson32d95a32012-09-10 13:15:23 -07009430 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009431
Jeff Johnson32d95a32012-09-10 13:15:23 -07009432 This is the driver entry point - called in different timeline depending
9433 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009434
9435 \param - None
9436
9437 \return - 0 for success, non zero for failure
9438
9439 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009440static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009441{
9442 VOS_STATUS status;
9443 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009444 struct device *dev = NULL;
9445 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009446#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9447 int max_retries = 0;
9448#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009449
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309450#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9451 wlan_logging_sock_init_svc();
9452#endif
9453
Jeff Johnson295189b2012-06-20 16:38:30 -07009454 ENTER();
9455
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009456#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009457 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009458#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009459
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309460 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009461 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9462 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9463
Jeff Johnson295189b2012-06-20 16:38:30 -07009464#ifdef ANI_BUS_TYPE_PCI
9465
9466 dev = wcnss_wlan_get_device();
9467
9468#endif // ANI_BUS_TYPE_PCI
9469
9470#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009471
9472#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9473 /* wait until WCNSS driver downloads NV */
9474 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9475 msleep(1000);
9476 }
9477 if (max_retries >= 5) {
9478 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309479#ifdef WLAN_OPEN_SOURCE
9480 wake_lock_destroy(&wlan_wake_lock);
9481#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309482
9483#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9484 wlan_logging_sock_deinit_svc();
9485#endif
9486
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009487 return -ENODEV;
9488 }
9489#endif
9490
Jeff Johnson295189b2012-06-20 16:38:30 -07009491 dev = wcnss_wlan_get_device();
9492#endif // ANI_BUS_TYPE_PLATFORM
9493
9494
9495 do {
9496 if (NULL == dev) {
9497 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9498 ret_status = -1;
9499 break;
9500 }
9501
Jeff Johnson295189b2012-06-20 16:38:30 -07009502#ifdef TIMER_MANAGER
9503 vos_timer_manager_init();
9504#endif
9505
9506 /* Preopen VOSS so that it is ready to start at least SAL */
9507 status = vos_preOpen(&pVosContext);
9508
9509 if (!VOS_IS_STATUS_SUCCESS(status))
9510 {
9511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9512 ret_status = -1;
9513 break;
9514 }
9515
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009516#ifndef MODULE
9517 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9518 */
9519 hdd_set_conparam((v_UINT_t)con_mode);
9520#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009521
9522 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009523 if (hdd_wlan_startup(dev))
9524 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009526 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009527 vos_preClose( &pVosContext );
9528 ret_status = -1;
9529 break;
9530 }
9531
Jeff Johnson295189b2012-06-20 16:38:30 -07009532 } while (0);
9533
9534 if (0 != ret_status)
9535 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009536#ifdef TIMER_MANAGER
9537 vos_timer_exit();
9538#endif
9539#ifdef MEMORY_DEBUG
9540 vos_mem_exit();
9541#endif
9542
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009543#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009544 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009545#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309546
9547#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9548 wlan_logging_sock_deinit_svc();
9549#endif
9550
Jeff Johnson295189b2012-06-20 16:38:30 -07009551 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9552 }
9553 else
9554 {
9555 //Send WLAN UP indication to Nlink Service
9556 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9557
9558 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009559 }
9560
9561 EXIT();
9562
9563 return ret_status;
9564}
9565
Jeff Johnson32d95a32012-09-10 13:15:23 -07009566/**---------------------------------------------------------------------------
9567
9568 \brief hdd_module_init() - Init Function
9569
9570 This is the driver entry point (invoked when module is loaded using insmod)
9571
9572 \param - None
9573
9574 \return - 0 for success, non zero for failure
9575
9576 --------------------------------------------------------------------------*/
9577#ifdef MODULE
9578static int __init hdd_module_init ( void)
9579{
9580 return hdd_driver_init();
9581}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009582#else /* #ifdef MODULE */
9583static int __init hdd_module_init ( void)
9584{
9585 /* Driver initialization is delayed to fwpath_changed_handler */
9586 return 0;
9587}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009588#endif /* #ifdef MODULE */
9589
Jeff Johnson295189b2012-06-20 16:38:30 -07009590
9591/**---------------------------------------------------------------------------
9592
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009593 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009594
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009595 This is the driver exit point (invoked when module is unloaded using rmmod
9596 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009597
9598 \param - None
9599
9600 \return - None
9601
9602 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009603static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009604{
9605 hdd_context_t *pHddCtx = NULL;
9606 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309607 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309608 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009609
9610 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9611
9612 //Get the global vos context
9613 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9614
9615 if(!pVosContext)
9616 {
9617 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9618 goto done;
9619 }
9620
9621 //Get the HDD context.
9622 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9623
9624 if(!pHddCtx)
9625 {
9626 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9627 }
9628 else
9629 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309630 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9631
9632 if (pHddCtx->isLogpInProgress)
9633 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009634 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309635 "%s:SSR in Progress; block rmmod !!!", __func__);
9636 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9637 msecs_to_jiffies(30000));
9638 if(!rc)
9639 {
9640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9641 "%s:SSR timedout, fatal error", __func__);
9642 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009643 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309644 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009645
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309646 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309647 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009648 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309649 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009650
Agarwal Ashish8db39882014-07-30 21:56:07 +05309651 /* Driver Need to send country code 00 in below condition
9652 * 1) If gCountryCodePriority is set to 1; and last country
9653 * code set is through 11d. This needs to be done in case
9654 * when NV country code is 00.
9655 * This Needs to be done as when kernel store last country
9656 * code and if stored country code is not through 11d,
9657 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9658 * in next load/unload as soon as we get any country through
9659 * 11d. In sme_HandleChangeCountryCodeByUser
9660 * pMsg->countryCode will be last countryCode and
9661 * pMac->scan.countryCode11d will be country through 11d so
9662 * due to mismatch driver will disable 11d.
9663 *
Agarwal Ashish8db39882014-07-30 21:56:07 +05309664 */
9665
9666 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309667 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +05309668 sme_Is11dSupported(pHddCtx->hHal)))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309669 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309670 hddLog(VOS_TRACE_LEVEL_INFO,
9671 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309672 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9673 }
9674
Jeff Johnson295189b2012-06-20 16:38:30 -07009675 //Do all the cleanup before deregistering the driver
9676 hdd_wlan_exit(pHddCtx);
9677 }
9678
Jeff Johnson295189b2012-06-20 16:38:30 -07009679 vos_preClose( &pVosContext );
9680
9681#ifdef TIMER_MANAGER
9682 vos_timer_exit();
9683#endif
9684#ifdef MEMORY_DEBUG
9685 vos_mem_exit();
9686#endif
9687
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309688#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9689 wlan_logging_sock_deinit_svc();
9690#endif
9691
Jeff Johnson295189b2012-06-20 16:38:30 -07009692done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009693#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009694 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009695#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309696
Jeff Johnson295189b2012-06-20 16:38:30 -07009697 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9698}
9699
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009700/**---------------------------------------------------------------------------
9701
9702 \brief hdd_module_exit() - Exit function
9703
9704 This is the driver exit point (invoked when module is unloaded using rmmod)
9705
9706 \param - None
9707
9708 \return - None
9709
9710 --------------------------------------------------------------------------*/
9711static void __exit hdd_module_exit(void)
9712{
9713 hdd_driver_exit();
9714}
9715
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009716#ifdef MODULE
9717static int fwpath_changed_handler(const char *kmessage,
9718 struct kernel_param *kp)
9719{
Jeff Johnson76052702013-04-16 13:55:05 -07009720 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009721}
9722
9723static int con_mode_handler(const char *kmessage,
9724 struct kernel_param *kp)
9725{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009726 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009727}
9728#else /* #ifdef MODULE */
9729/**---------------------------------------------------------------------------
9730
Jeff Johnson76052702013-04-16 13:55:05 -07009731 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009732
Jeff Johnson76052702013-04-16 13:55:05 -07009733 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009734 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009735 - invoked when module parameter fwpath is modified from userspace to signal
9736 initializing the WLAN driver or when con_mode is modified from userspace
9737 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009738
9739 \return - 0 for success, non zero for failure
9740
9741 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009742static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009743{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009744 int ret_status;
9745
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009746 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009747 ret_status = hdd_driver_init();
9748 wlan_hdd_inited = ret_status ? 0 : 1;
9749 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009750 }
9751
9752 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009753
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009754 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009755
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009756 ret_status = hdd_driver_init();
9757 wlan_hdd_inited = ret_status ? 0 : 1;
9758 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009759}
9760
Jeff Johnson295189b2012-06-20 16:38:30 -07009761/**---------------------------------------------------------------------------
9762
Jeff Johnson76052702013-04-16 13:55:05 -07009763 \brief fwpath_changed_handler() - Handler Function
9764
9765 Handle changes to the fwpath parameter
9766
9767 \return - 0 for success, non zero for failure
9768
9769 --------------------------------------------------------------------------*/
9770static int fwpath_changed_handler(const char *kmessage,
9771 struct kernel_param *kp)
9772{
9773 int ret;
9774
9775 ret = param_set_copystring(kmessage, kp);
9776 if (0 == ret)
9777 ret = kickstart_driver();
9778 return ret;
9779}
9780
9781/**---------------------------------------------------------------------------
9782
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009783 \brief con_mode_handler() -
9784
9785 Handler function for module param con_mode when it is changed by userspace
9786 Dynamically linked - do nothing
9787 Statically linked - exit and init driver, as in rmmod and insmod
9788
Jeff Johnson76052702013-04-16 13:55:05 -07009789 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009790
Jeff Johnson76052702013-04-16 13:55:05 -07009791 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009792
9793 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009794static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009795{
Jeff Johnson76052702013-04-16 13:55:05 -07009796 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009797
Jeff Johnson76052702013-04-16 13:55:05 -07009798 ret = param_set_int(kmessage, kp);
9799 if (0 == ret)
9800 ret = kickstart_driver();
9801 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009802}
9803#endif /* #ifdef MODULE */
9804
9805/**---------------------------------------------------------------------------
9806
Jeff Johnson295189b2012-06-20 16:38:30 -07009807 \brief hdd_get_conparam() -
9808
9809 This is the driver exit point (invoked when module is unloaded using rmmod)
9810
9811 \param - None
9812
9813 \return - tVOS_CON_MODE
9814
9815 --------------------------------------------------------------------------*/
9816tVOS_CON_MODE hdd_get_conparam ( void )
9817{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009818#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009819 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009820#else
9821 return (tVOS_CON_MODE)curr_con_mode;
9822#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009823}
9824void hdd_set_conparam ( v_UINT_t newParam )
9825{
9826 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009827#ifndef MODULE
9828 curr_con_mode = con_mode;
9829#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009830}
9831/**---------------------------------------------------------------------------
9832
9833 \brief hdd_softap_sta_deauth() - function
9834
9835 This to take counter measure to handle deauth req from HDD
9836
9837 \param - pAdapter - Pointer to the HDD
9838
9839 \param - enable - boolean value
9840
9841 \return - None
9842
9843 --------------------------------------------------------------------------*/
9844
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009845VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009846{
Jeff Johnson295189b2012-06-20 16:38:30 -07009847 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009848 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009849
9850 ENTER();
9851
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009852 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9853 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009854
9855 //Ignore request to deauth bcmc station
9856 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009857 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009858
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009859 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009860
9861 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009862 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009863}
9864
9865/**---------------------------------------------------------------------------
9866
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309867 \brief hdd_del_all_sta() - function
9868
9869 This function removes all the stations associated on stopping AP/P2P GO.
9870
9871 \param - pAdapter - Pointer to the HDD
9872
9873 \return - None
9874
9875 --------------------------------------------------------------------------*/
9876
9877int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9878{
9879 v_U16_t i;
9880 VOS_STATUS vos_status;
9881
9882 ENTER();
9883
9884 hddLog(VOS_TRACE_LEVEL_INFO,
9885 "%s: Delete all STAs associated.",__func__);
9886 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9887 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9888 )
9889 {
9890 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9891 {
9892 if ((pAdapter->aStaInfo[i].isUsed) &&
9893 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9894 {
9895 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
9896 hddLog(VOS_TRACE_LEVEL_ERROR,
9897 "%s: Delete STA with staid = %d and MAC::"
9898 MAC_ADDRESS_STR,
9899 __func__, i, MAC_ADDR_ARRAY(macAddr));
9900 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
9901 if (VOS_IS_STATUS_SUCCESS(vos_status))
9902 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9903 }
9904 }
9905 }
9906
9907 EXIT();
9908 return 0;
9909}
9910
9911/**---------------------------------------------------------------------------
9912
Jeff Johnson295189b2012-06-20 16:38:30 -07009913 \brief hdd_softap_sta_disassoc() - function
9914
9915 This to take counter measure to handle deauth req from HDD
9916
9917 \param - pAdapter - Pointer to the HDD
9918
9919 \param - enable - boolean value
9920
9921 \return - None
9922
9923 --------------------------------------------------------------------------*/
9924
9925void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9926{
9927 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9928
9929 ENTER();
9930
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309931 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009932
9933 //Ignore request to disassoc bcmc station
9934 if( pDestMacAddress[0] & 0x1 )
9935 return;
9936
9937 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9938}
9939
9940void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9941{
9942 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9943
9944 ENTER();
9945
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309946 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009947
9948 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9949}
9950
Jeff Johnson295189b2012-06-20 16:38:30 -07009951/**---------------------------------------------------------------------------
9952 *
9953 * \brief hdd_get__concurrency_mode() -
9954 *
9955 *
9956 * \param - None
9957 *
9958 * \return - CONCURRENCY MODE
9959 *
9960 * --------------------------------------------------------------------------*/
9961tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9962{
9963 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9964 hdd_context_t *pHddCtx;
9965
9966 if (NULL != pVosContext)
9967 {
9968 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9969 if (NULL != pHddCtx)
9970 {
9971 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9972 }
9973 }
9974
9975 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009976 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009977 return VOS_STA;
9978}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309979v_BOOL_t
9980wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9981{
9982 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009983
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309984 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9985 if (pAdapter == NULL)
9986 {
9987 hddLog(VOS_TRACE_LEVEL_INFO,
9988 FL("GO doesn't exist"));
9989 return TRUE;
9990 }
9991 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9992 {
9993 hddLog(VOS_TRACE_LEVEL_INFO,
9994 FL("GO started"));
9995 return TRUE;
9996 }
9997 else
9998 /* wait till GO changes its interface to p2p device */
9999 hddLog(VOS_TRACE_LEVEL_INFO,
10000 FL("Del_bss called, avoid apps suspend"));
10001 return FALSE;
10002
10003}
Jeff Johnson295189b2012-06-20 16:38:30 -070010004/* Decide whether to allow/not the apps power collapse.
10005 * Allow apps power collapse if we are in connected state.
10006 * if not, allow only if we are in IMPS */
10007v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
10008{
10009 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080010010 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010011 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070010012 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10013 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10014 hdd_adapter_t *pAdapter = NULL;
10015 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080010016 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010017
Jeff Johnson295189b2012-06-20 16:38:30 -070010018 if (VOS_STA_SAP_MODE == hdd_get_conparam())
10019 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010020
Yathish9f22e662012-12-10 14:21:35 -080010021 concurrent_state = hdd_get_concurrency_mode();
10022
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010023 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
10024 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
10025 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080010026#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010027
Yathish9f22e662012-12-10 14:21:35 -080010028 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010029 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080010030 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
10031 return TRUE;
10032#endif
10033
Jeff Johnson295189b2012-06-20 16:38:30 -070010034 /*loop through all adapters. TBD fix for Concurrency */
10035 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10036 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10037 {
10038 pAdapter = pAdapterNode->pAdapter;
10039 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10040 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10041 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010042 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010043 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010044 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010045 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10046 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010047 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010048 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010049 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10050 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010051 return FALSE;
10052 }
10053 }
10054 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10055 pAdapterNode = pNext;
10056 }
10057 return TRUE;
10058}
10059
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010060/* Decides whether to send suspend notification to Riva
10061 * if any adapter is in BMPS; then it is required */
10062v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10063{
10064 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10065 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10066
10067 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10068 {
10069 return TRUE;
10070 }
10071 return FALSE;
10072}
10073
Jeff Johnson295189b2012-06-20 16:38:30 -070010074void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10075{
10076 switch(mode)
10077 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010078 case VOS_STA_MODE:
10079 case VOS_P2P_CLIENT_MODE:
10080 case VOS_P2P_GO_MODE:
10081 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010082 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010083 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010084 break;
10085 default:
10086 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010087 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010088 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10089 "Number of open sessions for mode %d = %d"),
10090 pHddCtx->concurrency_mode, mode,
10091 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010092}
10093
10094
10095void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10096{
10097 switch(mode)
10098 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010099 case VOS_STA_MODE:
10100 case VOS_P2P_CLIENT_MODE:
10101 case VOS_P2P_GO_MODE:
10102 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010103 pHddCtx->no_of_open_sessions[mode]--;
10104 if (!(pHddCtx->no_of_open_sessions[mode]))
10105 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010106 break;
10107 default:
10108 break;
10109 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010110 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10111 "Number of open sessions for mode %d = %d"),
10112 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10113
10114}
10115/**---------------------------------------------------------------------------
10116 *
10117 * \brief wlan_hdd_incr_active_session()
10118 *
10119 * This function increments the number of active sessions
10120 * maintained per device mode
10121 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10122 * Incase of SAP/P2P GO upon bss start it is incremented
10123 *
10124 * \param pHddCtx - HDD Context
10125 * \param mode - device mode
10126 *
10127 * \return - None
10128 *
10129 * --------------------------------------------------------------------------*/
10130void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10131{
10132 switch (mode) {
10133 case VOS_STA_MODE:
10134 case VOS_P2P_CLIENT_MODE:
10135 case VOS_P2P_GO_MODE:
10136 case VOS_STA_SAP_MODE:
10137 pHddCtx->no_of_active_sessions[mode]++;
10138 break;
10139 default:
10140 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10141 break;
10142 }
10143 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10144 mode,
10145 pHddCtx->no_of_active_sessions[mode]);
10146}
10147
10148/**---------------------------------------------------------------------------
10149 *
10150 * \brief wlan_hdd_decr_active_session()
10151 *
10152 * This function decrements the number of active sessions
10153 * maintained per device mode
10154 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10155 * Incase of SAP/P2P GO upon bss stop it is decremented
10156 *
10157 * \param pHddCtx - HDD Context
10158 * \param mode - device mode
10159 *
10160 * \return - None
10161 *
10162 * --------------------------------------------------------------------------*/
10163void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10164{
10165 switch (mode) {
10166 case VOS_STA_MODE:
10167 case VOS_P2P_CLIENT_MODE:
10168 case VOS_P2P_GO_MODE:
10169 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010170 if (pHddCtx->no_of_active_sessions[mode] > 0)
10171 pHddCtx->no_of_active_sessions[mode]--;
10172 else
10173 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10174 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010175 break;
10176 default:
10177 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10178 break;
10179 }
10180 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10181 mode,
10182 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010183}
10184
Jeff Johnsone7245742012-09-05 17:12:55 -070010185/**---------------------------------------------------------------------------
10186 *
10187 * \brief wlan_hdd_restart_init
10188 *
10189 * This function initalizes restart timer/flag. An internal function.
10190 *
10191 * \param - pHddCtx
10192 *
10193 * \return - None
10194 *
10195 * --------------------------------------------------------------------------*/
10196
10197static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10198{
10199 /* Initialize */
10200 pHddCtx->hdd_restart_retries = 0;
10201 atomic_set(&pHddCtx->isRestartInProgress, 0);
10202 vos_timer_init(&pHddCtx->hdd_restart_timer,
10203 VOS_TIMER_TYPE_SW,
10204 wlan_hdd_restart_timer_cb,
10205 pHddCtx);
10206}
10207/**---------------------------------------------------------------------------
10208 *
10209 * \brief wlan_hdd_restart_deinit
10210 *
10211 * This function cleans up the resources used. An internal function.
10212 *
10213 * \param - pHddCtx
10214 *
10215 * \return - None
10216 *
10217 * --------------------------------------------------------------------------*/
10218
10219static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10220{
10221
10222 VOS_STATUS vos_status;
10223 /* Block any further calls */
10224 atomic_set(&pHddCtx->isRestartInProgress, 1);
10225 /* Cleanup */
10226 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10227 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010228 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010229 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10230 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010231 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010232
10233}
10234
10235/**---------------------------------------------------------------------------
10236 *
10237 * \brief wlan_hdd_framework_restart
10238 *
10239 * This function uses a cfg80211 API to start a framework initiated WLAN
10240 * driver module unload/load.
10241 *
10242 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10243 *
10244 *
10245 * \param - pHddCtx
10246 *
10247 * \return - VOS_STATUS_SUCCESS: Success
10248 * VOS_STATUS_E_EMPTY: Adapter is Empty
10249 * VOS_STATUS_E_NOMEM: No memory
10250
10251 * --------------------------------------------------------------------------*/
10252
10253static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10254{
10255 VOS_STATUS status = VOS_STATUS_SUCCESS;
10256 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010257 int len = (sizeof (struct ieee80211_mgmt));
10258 struct ieee80211_mgmt *mgmt = NULL;
10259
10260 /* Prepare the DEAUTH managment frame with reason code */
10261 mgmt = kzalloc(len, GFP_KERNEL);
10262 if(mgmt == NULL)
10263 {
10264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10265 "%s: memory allocation failed (%d bytes)", __func__, len);
10266 return VOS_STATUS_E_NOMEM;
10267 }
10268 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010269
10270 /* Iterate over all adapters/devices */
10271 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10272 do
10273 {
10274 if( (status == VOS_STATUS_SUCCESS) &&
10275 pAdapterNode &&
10276 pAdapterNode->pAdapter)
10277 {
10278 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10279 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10280 pAdapterNode->pAdapter->dev->name,
10281 pAdapterNode->pAdapter->device_mode,
10282 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010283 /*
10284 * CFG80211 event to restart the driver
10285 *
10286 * 'cfg80211_send_unprot_deauth' sends a
10287 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10288 * of SME(Linux Kernel) state machine.
10289 *
10290 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10291 * the driver.
10292 *
10293 */
10294
10295 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010296 }
10297 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10298 pAdapterNode = pNext;
10299 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10300
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010301
10302 /* Free the allocated management frame */
10303 kfree(mgmt);
10304
Jeff Johnsone7245742012-09-05 17:12:55 -070010305 /* Retry until we unload or reach max count */
10306 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10307 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10308
10309 return status;
10310
10311}
10312/**---------------------------------------------------------------------------
10313 *
10314 * \brief wlan_hdd_restart_timer_cb
10315 *
10316 * Restart timer callback. An internal function.
10317 *
10318 * \param - User data:
10319 *
10320 * \return - None
10321 *
10322 * --------------------------------------------------------------------------*/
10323
10324void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10325{
10326 hdd_context_t *pHddCtx = usrDataForCallback;
10327 wlan_hdd_framework_restart(pHddCtx);
10328 return;
10329
10330}
10331
10332
10333/**---------------------------------------------------------------------------
10334 *
10335 * \brief wlan_hdd_restart_driver
10336 *
10337 * This function sends an event to supplicant to restart the WLAN driver.
10338 *
10339 * This function is called from vos_wlanRestart.
10340 *
10341 * \param - pHddCtx
10342 *
10343 * \return - VOS_STATUS_SUCCESS: Success
10344 * VOS_STATUS_E_EMPTY: Adapter is Empty
10345 * VOS_STATUS_E_ALREADY: Request already in progress
10346
10347 * --------------------------------------------------------------------------*/
10348VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10349{
10350 VOS_STATUS status = VOS_STATUS_SUCCESS;
10351
10352 /* A tight check to make sure reentrancy */
10353 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10354 {
Mihir Shetefd528652014-06-23 19:07:50 +053010355 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010356 "%s: WLAN restart is already in progress", __func__);
10357
10358 return VOS_STATUS_E_ALREADY;
10359 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010360 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010361#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010362 wcnss_reset_intr();
10363#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010364
Jeff Johnsone7245742012-09-05 17:12:55 -070010365 return status;
10366}
10367
Mihir Shetee1093ba2014-01-21 20:13:32 +053010368/**---------------------------------------------------------------------------
10369 *
10370 * \brief wlan_hdd_init_channels
10371 *
10372 * This function is used to initialize the channel list in CSR
10373 *
10374 * This function is called from hdd_wlan_startup
10375 *
10376 * \param - pHddCtx: HDD context
10377 *
10378 * \return - VOS_STATUS_SUCCESS: Success
10379 * VOS_STATUS_E_FAULT: Failure reported by SME
10380
10381 * --------------------------------------------------------------------------*/
10382static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10383{
10384 eHalStatus status;
10385
10386 status = sme_InitChannels(pHddCtx->hHal);
10387 if (HAL_STATUS_SUCCESS(status))
10388 {
10389 return VOS_STATUS_SUCCESS;
10390 }
10391 else
10392 {
10393 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10394 __func__, status);
10395 return VOS_STATUS_E_FAULT;
10396 }
10397}
10398
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010399VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010400{
10401 eHalStatus status;
10402
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010403 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010404 if (HAL_STATUS_SUCCESS(status))
10405 {
10406 return VOS_STATUS_SUCCESS;
10407 }
10408 else
10409 {
10410 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10411 __func__, status);
10412 return VOS_STATUS_E_FAULT;
10413 }
10414}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010415/*
10416 * API to find if there is any STA or P2P-Client is connected
10417 */
10418VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10419{
10420 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10421}
Jeff Johnsone7245742012-09-05 17:12:55 -070010422
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010423int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10424{
10425 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10426 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010427 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010428
10429 pScanInfo = &pHddCtx->scan_info;
10430 if (pScanInfo->mScanPending)
10431 {
10432 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010433 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010434 eCSR_SCAN_ABORT_DEFAULT);
10435
10436 status = wait_for_completion_interruptible_timeout(
10437 &pScanInfo->abortscan_event_var,
10438 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010439 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010440 {
10441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010442 "%s: Timeout or Interrupt occurred while waiting for abort"
10443 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010444 return -ETIMEDOUT;
10445 }
10446 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010447 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010448}
10449
c_hpothu225aa7c2014-10-22 17:45:13 +053010450VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
10451{
10452 hdd_adapter_t *pAdapter;
10453 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10454 VOS_STATUS vosStatus;
10455
10456 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10457 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
10458 {
10459 pAdapter = pAdapterNode->pAdapter;
10460 if (NULL != pAdapter)
10461 {
10462 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
10463 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
10464 WLAN_HDD_P2P_GO == pAdapter->device_mode)
10465 {
10466 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
10467 pAdapter->device_mode);
10468 if (VOS_STATUS_SUCCESS !=
10469 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
10470 {
10471 hddLog(LOGE, FL("failed to abort ROC"));
10472 return VOS_STATUS_E_FAILURE;
10473 }
10474 }
10475 }
10476 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10477 pAdapterNode = pNext;
10478 }
10479 return VOS_STATUS_SUCCESS;
10480}
Jeff Johnson295189b2012-06-20 16:38:30 -070010481//Register the module init/exit functions
10482module_init(hdd_module_init);
10483module_exit(hdd_module_exit);
10484
10485MODULE_LICENSE("Dual BSD/GPL");
10486MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10487MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10488
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010489module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10490 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010491
Jeff Johnson76052702013-04-16 13:55:05 -070010492module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010493 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010494
10495module_param(enable_dfs_chan_scan, int,
10496 S_IRUSR | S_IRGRP | S_IROTH);
10497
10498module_param(enable_11d, int,
10499 S_IRUSR | S_IRGRP | S_IROTH);
10500
10501module_param(country_code, charp,
10502 S_IRUSR | S_IRGRP | S_IROTH);