blob: f6858cdc1bd553b374a96178186d53c5a22e4764 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Rajeev Kumar8b373292014-01-08 20:36:55 -08002 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08003 *
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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700112#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include <mach/subsystem_restart.h>
114#include <wlan_hdd_hostapd.h>
115#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "wlan_hdd_dev_pwr.h"
118#ifdef WLAN_BTAMP_FEATURE
119#include "bap_hdd_misc.h"
120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800123#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530124#ifdef FEATURE_WLAN_TDLS
125#include "wlan_hdd_tdls.h"
126#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700127#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Arif Hussain66559122013-11-21 10:11:40 -0800154
155static char *country_code;
156static int enable_11d = -1;
157static int enable_dfs_chan_scan = -1;
158
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700159#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700160static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162
Jeff Johnsone7245742012-09-05 17:12:55 -0700163/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800164 * spinlock for synchronizing asynchronous request/response
165 * (full description of use in wlan_hdd_main.h)
166 */
167DEFINE_SPINLOCK(hdd_context_lock);
168
169/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700170 * The rate at which the driver sends RESTART event to supplicant
171 * once the function 'vos_wlanRestart()' is called
172 *
173 */
174#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
175#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700176
177/*
178 * Size of Driver command strings from upper layer
179 */
180#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
181#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
182
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700183#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
184#define TID_MIN_VALUE 0
185#define TID_MAX_VALUE 15
186static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
187 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800188static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
189 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700190#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
191
Srinivas Girigowda4081bb12014-01-06 17:12:58 -0800192#define WLAN_PRIV_DATA_MAX_LEN 4096
193
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700194/*
195 * Driver miracast parameters 0-Disabled
196 * 1-Source, 2-Sink
197 */
198#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
199#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
200
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800201#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700202static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700203#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700204/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700205static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700206
207//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700208static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
209static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
210static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
211void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800212void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700213
Jeff Johnson295189b2012-06-20 16:38:30 -0700214v_U16_t hdd_select_queue(struct net_device *dev,
215 struct sk_buff *skb);
216
217#ifdef WLAN_FEATURE_PACKET_FILTERING
218static void hdd_set_multicast_list(struct net_device *dev);
219#endif
220
221void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700222int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700223
224extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700225
Srinivas Girigowdade697412013-02-14 16:31:48 -0800226#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
227void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
228static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700229static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
230 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
231 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700232static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
233 tANI_U8 *pTargetApBssid,
234 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800235#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700236#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
237VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
238#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
239
Jeff Johnson295189b2012-06-20 16:38:30 -0700240static int hdd_netdev_notifier_call(struct notifier_block * nb,
241 unsigned long state,
242 void *ndev)
243{
244 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700245 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700246 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700247#ifdef WLAN_BTAMP_FEATURE
248 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700249#endif
250
251 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700252 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700253 (strncmp(dev->name, "p2p", 3)))
254 return NOTIFY_DONE;
255
256 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 return NOTIFY_DONE;
258
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700260 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700261
Jeff Johnson27cee452013-03-27 11:10:24 -0700262 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 VOS_ASSERT(0);
266 return NOTIFY_DONE;
267 }
268
Jeff Johnson27cee452013-03-27 11:10:24 -0700269 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
270 if (NULL == pHddCtx)
271 {
272 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
273 VOS_ASSERT(0);
274 return NOTIFY_DONE;
275 }
276
277 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
278 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700279
280 switch (state) {
281 case NETDEV_REGISTER:
282 break;
283
284 case NETDEV_UNREGISTER:
285 break;
286
287 case NETDEV_UP:
288 break;
289
290 case NETDEV_DOWN:
291 break;
292
293 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700294 if(TRUE == pAdapter->isLinkUpSvcNeeded)
295 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 break;
297
298 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700299 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 {
301 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800302 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530303 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800305 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
307 if(!result)
308 {
309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800310 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700311 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 }
313 }
314 else
315 {
316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700317 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700318 }
319#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 status = WLANBAP_StopAmp();
322 if(VOS_STATUS_SUCCESS != status )
323 {
324 pHddCtx->isAmpAllowed = VOS_TRUE;
325 hddLog(VOS_TRACE_LEVEL_FATAL,
326 "%s: Failed to stop AMP", __func__);
327 }
328 else
329 {
330 //a state m/c implementation in PAL is TBD to avoid this delay
331 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700332 if ( pHddCtx->isAmpAllowed )
333 {
334 WLANBAP_DeregisterFromHCI();
335 pHddCtx->isAmpAllowed = VOS_FALSE;
336 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 }
338#endif //WLAN_BTAMP_FEATURE
339 break;
340
341 default:
342 break;
343 }
344
345 return NOTIFY_DONE;
346}
347
348struct notifier_block hdd_netdev_notifier = {
349 .notifier_call = hdd_netdev_notifier_call,
350};
351
352/*---------------------------------------------------------------------------
353 * Function definitions
354 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700355void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
356void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700357//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700358static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700359#ifndef MODULE
360/* current con_mode - used only for statically linked driver
361 * con_mode is changed by userspace to indicate a mode change which will
362 * result in calling the module exit and init functions. The module
363 * exit function will clean up based on the value of con_mode prior to it
364 * being changed by userspace. So curr_con_mode records the current con_mode
365 * for exit when con_mode becomes the next mode for init
366 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700367static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700368#endif
369
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800370/**---------------------------------------------------------------------------
371
372 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = VOS_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 vos_trace_setValue(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
410
411
Jeff Johnson295189b2012-06-20 16:38:30 -0700412/**---------------------------------------------------------------------------
413
414 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
415
416 Called immediately after the cfg.ini is read in order to configure
417 the desired trace levels in the WDI.
418
419 \param - moduleId - module whose trace level is being configured
420 \param - bitmask - bitmask of log levels to be enabled
421
422 \return - void
423
424 --------------------------------------------------------------------------*/
425static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
426{
427 wpt_tracelevel level;
428
429 /* if the bitmask is the default value, then a bitmask was not
430 specified in cfg.ini, so leave the logging level alone (it
431 will remain at the "compiled in" default value) */
432 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
433 {
434 return;
435 }
436
437 /* a mask was specified. start by disabling all logging */
438 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
439
440 /* now cycle through the bitmask until all "set" bits are serviced */
441 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
442 while (0 != bitmask)
443 {
444 if (bitmask & 1)
445 {
446 wpalTraceSetLevel(moduleId, level, 1);
447 }
448 level++;
449 bitmask >>= 1;
450 }
451}
Jeff Johnson295189b2012-06-20 16:38:30 -0700452
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530453/*
454 * FUNCTION: wlan_hdd_validate_context
455 * This function is used to check the HDD context
456 */
457int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
458{
459 ENTER();
460
461 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
462 {
463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
464 "%s: HDD context is Null", __func__);
465 return -ENODEV;
466 }
467
468 if (pHddCtx->isLogpInProgress)
469 {
470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
471 "%s: LOGP in Progress. Ignore!!!", __func__);
472 return -EAGAIN;
473 }
474
475 if (pHddCtx->isLoadUnloadInProgress)
476 {
477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
478 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
479 return -EAGAIN;
480 }
481 return 0;
482}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700483#ifdef CONFIG_ENABLE_LINUX_REG
484void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
485{
486 hdd_adapter_t *pAdapter = NULL;
487 hdd_station_ctx_t *pHddStaCtx = NULL;
488 eCsrPhyMode phyMode;
489 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530490
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700491 if (NULL == pHddCtx)
492 {
493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
494 "HDD Context is null !!");
495 return ;
496 }
497
498 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
499 if (NULL == pAdapter)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "pAdapter is null !!");
503 return ;
504 }
505
506 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
507 if (NULL == pHddStaCtx)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "pHddStaCtx is null !!");
511 return ;
512 }
513
514 cfg_param = pHddCtx->cfg_ini;
515 if (NULL == cfg_param)
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
518 "cfg_params not available !!");
519 return ;
520 }
521
522 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
523
524 if (!pHddCtx->isVHT80Allowed)
525 {
526 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
527 (eCSR_DOT11_MODE_11ac == phyMode) ||
528 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
529 {
530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
531 "Setting phymode to 11n!!");
532 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
533 }
534 }
535 else
536 {
537 /*New country Supports 11ac as well resetting value back from .ini*/
538 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
539 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
540 return ;
541 }
542
543 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
544 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
545 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
546 {
547 VOS_STATUS vosStatus;
548
549 // need to issue a disconnect to CSR.
550 INIT_COMPLETION(pAdapter->disconnect_comp_var);
551 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
552 pAdapter->sessionId,
553 eCSR_DISCONNECT_REASON_UNSPECIFIED );
554
555 if (VOS_STATUS_SUCCESS == vosStatus)
556 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
557 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
558
559 }
560}
561#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530562void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
563{
564 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
565 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
566 hdd_config_t *cfg_param;
567 eCsrPhyMode phyMode;
568
569 if (NULL == pHddCtx)
570 {
571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
572 "HDD Context is null !!");
573 return ;
574 }
575
576 cfg_param = pHddCtx->cfg_ini;
577
578 if (NULL == cfg_param)
579 {
580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
581 "cfg_params not available !!");
582 return ;
583 }
584
585 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
586
587 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
588 {
589 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
590 (eCSR_DOT11_MODE_11ac == phyMode) ||
591 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
592 {
593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
594 "Setting phymode to 11n!!");
595 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
596 }
597 }
598 else
599 {
600 /*New country Supports 11ac as well resetting value back from .ini*/
601 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
602 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
603 return ;
604 }
605
606 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
607 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
608 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
609 {
610 VOS_STATUS vosStatus;
611
612 // need to issue a disconnect to CSR.
613 INIT_COMPLETION(pAdapter->disconnect_comp_var);
614 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
615 pAdapter->sessionId,
616 eCSR_DISCONNECT_REASON_UNSPECIFIED );
617
618 if (VOS_STATUS_SUCCESS == vosStatus)
619 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
620 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
621
622 }
623}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700624#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530625
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700626void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
627{
628 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
629 hdd_config_t *cfg_param;
630
631 if (NULL == pHddCtx)
632 {
633 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
634 "HDD Context is null !!");
635 return ;
636 }
637
638 cfg_param = pHddCtx->cfg_ini;
639
640 if (NULL == cfg_param)
641 {
642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
643 "cfg_params not available !!");
644 return ;
645 }
646
647 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
648 {
649 /*New country doesn't support DFS */
650 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
651 }
652 else
653 {
654 /*New country Supports DFS as well resetting value back from .ini*/
655 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
656 }
657
658}
659
Rajeev79dbe4c2013-10-05 11:03:42 +0530660#ifdef FEATURE_WLAN_BATCH_SCAN
661
662/**---------------------------------------------------------------------------
663
664 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
665 input string
666
667 This function extracts assigned integer from string in below format:
668 "STRING=10" : extracts integer 10 from this string
669
670 \param - pInPtr Pointer to input string
671 \param - base Base for string to int conversion(10 for decimal 16 for hex)
672 \param - pOutPtr Pointer to variable in which extracted integer needs to be
673 assigned
674 \param - pLastArg to tell whether it is last arguement in input string or
675 not
676
677 \return - NULL for failure cases
678 pointer to next arguement in input string for success cases
679 --------------------------------------------------------------------------*/
680static tANI_U8 *
681hdd_extract_assigned_int_from_str
682(
683 tANI_U8 *pInPtr,
684 tANI_U8 base,
685 tANI_U32 *pOutPtr,
686 tANI_U8 *pLastArg
687)
688{
689 int tempInt;
690 int v = 0;
691 char buf[32];
692 int val = 0;
693 *pLastArg = FALSE;
694
695 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
696 if (NULL == pInPtr)
697 {
698 return NULL;
699 }
700
701 pInPtr++;
702
703 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
704
705 val = sscanf(pInPtr, "%32s ", buf);
706 if (val < 0 && val > strlen(pInPtr))
707 {
708 return NULL;
709 }
710 pInPtr += val;
711 v = kstrtos32(buf, base, &tempInt);
712 if (v < 0)
713 {
714 return NULL;
715 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800716 if (tempInt < 0)
717 {
718 tempInt = 0;
719 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530720 *pOutPtr = tempInt;
721
722 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
723 if (NULL == pInPtr)
724 {
725 *pLastArg = TRUE;
726 return NULL;
727 }
728 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
729
730 return pInPtr;
731}
732
733/**---------------------------------------------------------------------------
734
735 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
736 input string
737
738 This function extracts assigned character from string in below format:
739 "STRING=A" : extracts char 'A' from this string
740
741 \param - pInPtr Pointer to input string
742 \param - pOutPtr Pointer to variable in which extracted char needs to be
743 assigned
744 \param - pLastArg to tell whether it is last arguement in input string or
745 not
746
747 \return - NULL for failure cases
748 pointer to next arguement in input string for success cases
749 --------------------------------------------------------------------------*/
750static tANI_U8 *
751hdd_extract_assigned_char_from_str
752(
753 tANI_U8 *pInPtr,
754 tANI_U8 *pOutPtr,
755 tANI_U8 *pLastArg
756)
757{
758 *pLastArg = FALSE;
759
760 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
761 if (NULL == pInPtr)
762 {
763 return NULL;
764 }
765
766 pInPtr++;
767
768 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
769
770 *pOutPtr = *pInPtr;
771
772 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
773 if (NULL == pInPtr)
774 {
775 *pLastArg = TRUE;
776 return NULL;
777 }
778 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
779
780 return pInPtr;
781}
782
783
784/**---------------------------------------------------------------------------
785
786 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
787
788 This function parses set batch scan command in below format:
789 WLS_BATCHING_SET <space> followed by below arguements
790 "SCANFREQ=XX" : Optional defaults to 30 sec
791 "MSCAN=XX" : Required number of scans to attempt to batch
792 "BESTN=XX" : Best Network (RSSI) defaults to 16
793 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
794 A. implies only 5 GHz , B. implies only 2.4GHz
795 "RTT=X" : optional defaults to 0
796 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
797 error
798
799 For example input commands:
800 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
801 translated into set batch scan with following parameters:
802 a) Frequence 60 seconds
803 b) Batch 10 scans together
804 c) Best RSSI to be 20
805 d) 5GHz band only
806 e) RTT is equal to 0
807
808 \param - pValue Pointer to input channel list
809 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
810
811 \return - 0 for success non-zero for failure
812
813 --------------------------------------------------------------------------*/
814static int
815hdd_parse_set_batchscan_command
816(
817 tANI_U8 *pValue,
818 tSirSetBatchScanReq *pHddSetBatchScanReq
819)
820{
821 tANI_U8 *inPtr = pValue;
822 tANI_U8 val = 0;
823 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800824 tANI_U32 nScanFreq;
825 tANI_U32 nMscan;
826 tANI_U32 nBestN;
827 tANI_U8 ucRfBand;
828 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800829 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530830
831 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800832 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
833 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
834 nRtt = 0;
835 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530836
837 /*go to space after WLS_BATCHING_SET command*/
838 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
839 /*no argument after the command*/
840 if (NULL == inPtr)
841 {
842 return -EINVAL;
843 }
844
845 /*no space after the command*/
846 else if (SPACE_ASCII_VALUE != *inPtr)
847 {
848 return -EINVAL;
849 }
850
851 /*removing empty spaces*/
852 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
853
854 /*no argument followed by spaces*/
855 if ('\0' == *inPtr)
856 {
857 return -EINVAL;
858 }
859
860 /*check and parse SCANFREQ*/
861 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
862 {
863 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800864 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800865
Rajeev Kumarc933d982013-11-18 20:04:20 -0800866 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800867 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800868 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800869 }
870
Rajeev79dbe4c2013-10-05 11:03:42 +0530871 if ( (NULL == inPtr) || (TRUE == lastArg))
872 {
873 return -EINVAL;
874 }
875 }
876
877 /*check and parse MSCAN*/
878 if ((strncmp(inPtr, "MSCAN", 5) == 0))
879 {
880 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800881 &nMscan, &lastArg);
882
883 if (0 == nMscan)
884 {
885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
886 "invalid MSCAN=%d", nMscan);
887 return -EINVAL;
888 }
889
Rajeev79dbe4c2013-10-05 11:03:42 +0530890 if (TRUE == lastArg)
891 {
892 goto done;
893 }
894 else if (NULL == inPtr)
895 {
896 return -EINVAL;
897 }
898 }
899 else
900 {
901 return -EINVAL;
902 }
903
904 /*check and parse BESTN*/
905 if ((strncmp(inPtr, "BESTN", 5) == 0))
906 {
907 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800908 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800909
Rajeev Kumarc933d982013-11-18 20:04:20 -0800910 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800911 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800912 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800913 }
914
Rajeev79dbe4c2013-10-05 11:03:42 +0530915 if (TRUE == lastArg)
916 {
917 goto done;
918 }
919 else if (NULL == inPtr)
920 {
921 return -EINVAL;
922 }
923 }
924
925 /*check and parse CHANNEL*/
926 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
927 {
928 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800929
Rajeev79dbe4c2013-10-05 11:03:42 +0530930 if (('A' == val) || ('a' == val))
931 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800932 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530933 }
934 else if (('B' == val) || ('b' == val))
935 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800936 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 }
938 else
939 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800940 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
941 }
942
943 if (TRUE == lastArg)
944 {
945 goto done;
946 }
947 else if (NULL == inPtr)
948 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530949 return -EINVAL;
950 }
951 }
952
953 /*check and parse RTT*/
954 if ((strncmp(inPtr, "RTT", 3) == 0))
955 {
956 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800957 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530958 if (TRUE == lastArg)
959 {
960 goto done;
961 }
962 if (NULL == inPtr)
963 {
964 return -EINVAL;
965 }
966 }
967
968
969done:
970
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800971 pHddSetBatchScanReq->scanFrequency = nScanFreq;
972 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
973 pHddSetBatchScanReq->bestNetwork = nBestN;
974 pHddSetBatchScanReq->rfBand = ucRfBand;
975 pHddSetBatchScanReq->rtt = nRtt;
976
Rajeev79dbe4c2013-10-05 11:03:42 +0530977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
978 "Received WLS_BATCHING_SET with SCANFREQ=%d "
979 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
980 pHddSetBatchScanReq->scanFrequency,
981 pHddSetBatchScanReq->numberOfScansToBatch,
982 pHddSetBatchScanReq->bestNetwork,
983 pHddSetBatchScanReq->rfBand,
984 pHddSetBatchScanReq->rtt);
985
986 return 0;
987}/*End of hdd_parse_set_batchscan_command*/
988
989/**---------------------------------------------------------------------------
990
991 \brief hdd_set_batch_scan_req_callback () - This function is called after
992 receiving set batch scan response from FW and it saves set batch scan
993 response data FW to HDD context and sets the completion event on
994 which hdd_ioctl is waiting
995
996 \param - callbackContext Pointer to HDD adapter
997 \param - pRsp Pointer to set batch scan response data received from FW
998
999 \return - nothing
1000
1001 --------------------------------------------------------------------------*/
1002static void hdd_set_batch_scan_req_callback
1003(
1004 void *callbackContext,
1005 tSirSetBatchScanRsp *pRsp
1006)
1007{
1008 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1009 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1010
1011 /*sanity check*/
1012 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1013 {
1014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: Invalid pAdapter magic", __func__);
1016 VOS_ASSERT(0);
1017 return;
1018 }
1019 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1020
1021 /*save set batch scan response*/
1022 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1023
1024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1025 "Received set batch scan rsp from FW with nScansToBatch=%d",
1026 pHddSetBatchScanRsp->nScansToBatch);
1027
1028 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1029 complete(&pAdapter->hdd_set_batch_scan_req_var);
1030
1031 return;
1032}/*End of hdd_set_batch_scan_req_callback*/
1033
1034
1035/**---------------------------------------------------------------------------
1036
1037 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1038 info in hdd batch scan response queue
1039
1040 \param - pAdapter Pointer to hdd adapter
1041 \param - pAPMetaInfo Pointer to access point meta info
1042 \param - scanId scan ID of batch scan response
1043 \param - isLastAp tells whether AP is last AP in batch scan response or not
1044
1045 \return - nothing
1046
1047 --------------------------------------------------------------------------*/
1048static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1049 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1050{
1051 tHddBatchScanRsp *pHead;
1052 tHddBatchScanRsp *pNode;
1053 tHddBatchScanRsp *pPrev;
1054 tHddBatchScanRsp *pTemp;
1055 tANI_U8 ssidLen;
1056
1057 /*head of hdd batch scan response queue*/
1058 pHead = pAdapter->pBatchScanRsp;
1059
1060 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1061 if (NULL == pNode)
1062 {
1063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1064 "%s: Could not allocate memory", __func__);
1065 VOS_ASSERT(0);
1066 return;
1067 }
1068
1069 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1070 sizeof(pNode->ApInfo.bssid));
1071 ssidLen = strlen(pApMetaInfo->ssid);
1072 if (SIR_MAX_SSID_SIZE < ssidLen)
1073 {
1074 /*invalid scan result*/
1075 vos_mem_free(pNode);
1076 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1077 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1078 return;
1079 }
1080 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1081 /*null terminate ssid*/
1082 pNode->ApInfo.ssid[ssidLen] = '\0';
1083 pNode->ApInfo.ch = pApMetaInfo->ch;
1084 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1085 pNode->ApInfo.age = pApMetaInfo->timestamp;
1086 pNode->ApInfo.batchId = scanId;
1087 pNode->ApInfo.isLastAp = isLastAp;
1088
1089 pNode->pNext = NULL;
1090 if (NULL == pHead)
1091 {
1092 pAdapter->pBatchScanRsp = pNode;
1093 }
1094 else
1095 {
1096 pTemp = pHead;
1097 while (NULL != pTemp)
1098 {
1099 pPrev = pTemp;
1100 pTemp = pTemp->pNext;
1101 }
1102 pPrev->pNext = pNode;
1103 }
1104
1105 return;
1106}/*End of hdd_populate_batch_scan_rsp_queue*/
1107
1108/**---------------------------------------------------------------------------
1109
1110 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1111 receiving batch scan response indication from FW. It saves get batch scan
1112 response data in HDD batch scan response queue. This callback sets the
1113 completion event on which hdd_ioctl is waiting only after getting complete
1114 batch scan response data from FW
1115
1116 \param - callbackContext Pointer to HDD adapter
1117 \param - pRsp Pointer to get batch scan response data received from FW
1118
1119 \return - nothing
1120
1121 --------------------------------------------------------------------------*/
1122static void hdd_batch_scan_result_ind_callback
1123(
1124 void *callbackContext,
1125 void *pRsp
1126)
1127{
1128 v_BOOL_t isLastAp;
1129 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001130 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301131 tANI_U32 numberScanList;
1132 tANI_U32 nextScanListOffset;
1133 tANI_U32 nextApMetaInfoOffset;
1134 hdd_adapter_t* pAdapter;
1135 tpSirBatchScanList pScanList;
1136 tpSirBatchScanNetworkInfo pApMetaInfo;
1137 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1138 tSirSetBatchScanReq *pReq;
1139
1140 pAdapter = (hdd_adapter_t *)callbackContext;
1141 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001142 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301143 {
1144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1145 "%s: Invalid pAdapter magic", __func__);
1146 VOS_ASSERT(0);
1147 return;
1148 }
1149
1150 /*initialize locals*/
1151 pReq = &pAdapter->hddSetBatchScanReq;
1152 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1153 isLastAp = FALSE;
1154 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001155 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301156 numberScanList = 0;
1157 nextScanListOffset = 0;
1158 nextApMetaInfoOffset = 0;
1159 pScanList = NULL;
1160 pApMetaInfo = NULL;
1161
1162 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1163 {
1164 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1166 isLastAp = TRUE;
1167 goto done;
1168 }
1169
1170 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1171 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1172 "Batch scan rsp: numberScalList %d", numberScanList);
1173
1174 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1175 {
1176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: numberScanList %d", __func__, numberScanList);
1178 isLastAp = TRUE;
1179 goto done;
1180 }
1181
1182 while (numberScanList)
1183 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001184 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301185 nextScanListOffset);
1186 if (NULL == pScanList)
1187 {
1188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1189 "%s: pScanList is %p", __func__, pScanList);
1190 isLastAp = TRUE;
1191 goto done;
1192 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001193 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001195 "Batch scan rsp: numApMetaInfo %d scanId %d",
1196 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301197
1198 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1199 {
1200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1201 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1202 isLastAp = TRUE;
1203 goto done;
1204 }
1205
Rajeev Kumarce651e42013-10-21 18:57:15 -07001206 /*Initialize next AP meta info offset for next scan list*/
1207 nextApMetaInfoOffset = 0;
1208
Rajeev79dbe4c2013-10-05 11:03:42 +05301209 while (numApMetaInfo)
1210 {
1211 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1212 nextApMetaInfoOffset);
1213 if (NULL == pApMetaInfo)
1214 {
1215 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1216 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1217 isLastAp = TRUE;
1218 goto done;
1219 }
1220 /*calculate AP age*/
1221 pApMetaInfo->timestamp =
1222 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1223
1224 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001225 "%s: bssId "MAC_ADDRESS_STR
1226 " ch %d rssi %d timestamp %d", __func__,
1227 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1228 pApMetaInfo->ch, pApMetaInfo->rssi,
1229 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301230
1231 /*mark last AP in batch scan response*/
1232 if ((TRUE == pBatchScanRsp->isLastResult) &&
1233 (1 == numberScanList) && (1 == numApMetaInfo))
1234 {
1235 isLastAp = TRUE;
1236 }
1237
1238 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1239 /*store batch scan repsonse in hdd queue*/
1240 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1241 pScanList->scanId, isLastAp);
1242 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1243
1244 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1245 numApMetaInfo--;
1246 }
1247
Rajeev Kumarce651e42013-10-21 18:57:15 -07001248 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1249 + (sizeof(tSirBatchScanNetworkInfo)
1250 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301251 numberScanList--;
1252 }
1253
1254done:
1255
1256 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1257 requested from hdd_ioctl*/
1258 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1259 (TRUE == isLastAp))
1260 {
1261 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1262 complete(&pAdapter->hdd_get_batch_scan_req_var);
1263 }
1264
1265 return;
1266}/*End of hdd_batch_scan_result_ind_callback*/
1267
1268/**---------------------------------------------------------------------------
1269
1270 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1271 response as per batch scan FR request format by putting proper markers
1272
1273 \param - pDest pointer to destination buffer
1274 \param - cur_len current length
1275 \param - tot_len total remaining size which can be written to user space
1276 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1277 \param - pAdapter Pointer to HDD adapter
1278
1279 \return - ret no of characters written
1280
1281 --------------------------------------------------------------------------*/
1282static tANI_U32
1283hdd_format_batch_scan_rsp
1284(
1285 tANI_U8 *pDest,
1286 tANI_U32 cur_len,
1287 tANI_U32 tot_len,
1288 tHddBatchScanRsp *pApMetaInfo,
1289 hdd_adapter_t* pAdapter
1290)
1291{
1292 tANI_U32 ret = 0;
1293 tANI_U32 rem_len = 0;
1294 tANI_U8 temp_len = 0;
1295 tANI_U8 temp_total_len = 0;
1296 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1297 tANI_U8 *pTemp = temp;
1298
1299 /*Batch scan reponse needs to be returned to user space in
1300 following format:
1301 "scancount=X\n" where X is the number of scans in current batch
1302 batch
1303 "trunc\n" optional present if current scan truncated
1304 "bssid=XX:XX:XX:XX:XX:XX\n"
1305 "ssid=XXXX\n"
1306 "freq=X\n" frequency in Mhz
1307 "level=XX\n"
1308 "age=X\n" ms
1309 "dist=X\n" cm (-1 if not available)
1310 "errror=X\n" (-1if not available)
1311 "====\n" (end of ap marker)
1312 "####\n" (end of scan marker)
1313 "----\n" (end of results)*/
1314 /*send scan result in above format to user space based on
1315 available length*/
1316 /*The GET response may have more data than the driver can return in its
1317 buffer. In that case the buffer should be filled to the nearest complete
1318 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1319 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1320 The final buffer should end with "----\n"*/
1321
1322 /*sanity*/
1323 if (cur_len > tot_len)
1324 {
1325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1326 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1327 return 0;
1328 }
1329 else
1330 {
1331 rem_len = (tot_len - cur_len);
1332 }
1333
1334 /*end scan marker*/
1335 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1336 {
1337 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1338 pTemp += temp_len;
1339 temp_total_len += temp_len;
1340 }
1341
1342 /*bssid*/
1343 temp_len = snprintf(pTemp, sizeof(temp),
1344 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1345 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1346 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1347 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1348 pTemp += temp_len;
1349 temp_total_len += temp_len;
1350
1351 /*ssid*/
1352 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1353 pApMetaInfo->ApInfo.ssid);
1354 pTemp += temp_len;
1355 temp_total_len += temp_len;
1356
1357 /*freq*/
1358 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001359 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362
1363 /*level*/
1364 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1365 pApMetaInfo->ApInfo.rssi);
1366 pTemp += temp_len;
1367 temp_total_len += temp_len;
1368
1369 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001370 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301371 pApMetaInfo->ApInfo.age);
1372 pTemp += temp_len;
1373 temp_total_len += temp_len;
1374
1375 /*dist*/
1376 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1377 pTemp += temp_len;
1378 temp_total_len += temp_len;
1379
1380 /*error*/
1381 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1382 pTemp += temp_len;
1383 temp_total_len += temp_len;
1384
1385 /*end AP marker*/
1386 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1387 pTemp += temp_len;
1388 temp_total_len += temp_len;
1389
1390 /*last AP in batch scan response*/
1391 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1392 {
1393 /*end scan marker*/
1394 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1395 pTemp += temp_len;
1396 temp_total_len += temp_len;
1397
1398 /*end batch scan result marker*/
1399 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001402
Rajeev79dbe4c2013-10-05 11:03:42 +05301403 }
1404
1405 if (temp_total_len < rem_len)
1406 {
1407 ret = temp_total_len + 1;
1408 strlcpy(pDest, temp, ret);
1409 pAdapter->isTruncated = FALSE;
1410 }
1411 else
1412 {
1413 pAdapter->isTruncated = TRUE;
1414 if (rem_len >= strlen("%%%%"))
1415 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001416 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301417 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001418 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301419 {
1420 ret = 0;
1421 }
1422 }
1423
1424 return ret;
1425
1426}/*End of hdd_format_batch_scan_rsp*/
1427
1428/**---------------------------------------------------------------------------
1429
1430 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1431 buffer starting with head of hdd batch scan response queue
1432
1433 \param - pAdapter Pointer to HDD adapter
1434 \param - pDest Pointer to user data buffer
1435 \param - cur_len current offset in user buffer
1436 \param - rem_len remaining no of bytes in user buffer
1437
1438 \return - number of bytes written in user buffer
1439
1440 --------------------------------------------------------------------------*/
1441
1442tANI_U32 hdd_populate_user_batch_scan_rsp
1443(
1444 hdd_adapter_t* pAdapter,
1445 tANI_U8 *pDest,
1446 tANI_U32 cur_len,
1447 tANI_U32 rem_len
1448)
1449{
1450 tHddBatchScanRsp *pHead;
1451 tHddBatchScanRsp *pPrev;
1452 tANI_U32 len;
1453
Rajeev79dbe4c2013-10-05 11:03:42 +05301454 pAdapter->isTruncated = FALSE;
1455
1456 /*head of hdd batch scan response queue*/
1457 pHead = pAdapter->pBatchScanRsp;
1458 while (pHead)
1459 {
1460 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1461 pAdapter);
1462 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001463 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301464 cur_len += len;
1465 if(TRUE == pAdapter->isTruncated)
1466 {
1467 /*result is truncated return rest of scan rsp in next req*/
1468 cur_len = rem_len;
1469 break;
1470 }
1471 pPrev = pHead;
1472 pHead = pHead->pNext;
1473 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001474 if (TRUE == pPrev->ApInfo.isLastAp)
1475 {
1476 pAdapter->prev_batch_id = 0;
1477 }
1478 else
1479 {
1480 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1481 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301482 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001483 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301484 }
1485
1486 return cur_len;
1487}/*End of hdd_populate_user_batch_scan_rsp*/
1488
1489/**---------------------------------------------------------------------------
1490
1491 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1492 scan response data from HDD queue to user space
1493 It does following in detail:
1494 a) if HDD has enough data in its queue then it 1st copies data to user
1495 space and then send get batch scan indication message to FW. In this
1496 case it does not wait on any event and batch scan response data will
1497 be populated in HDD response queue in MC thread context after receiving
1498 indication from FW
1499 b) else send get batch scan indication message to FW and wait on an event
1500 which will be set once HDD receives complete batch scan response from
1501 FW and then this function returns batch scan response to user space
1502
1503 \param - pAdapter Pointer to HDD adapter
1504 \param - pPrivData Pointer to priv_data
1505
1506 \return - 0 for success -EFAULT for failure
1507
1508 --------------------------------------------------------------------------*/
1509
1510int hdd_return_batch_scan_rsp_to_user
1511(
1512 hdd_adapter_t* pAdapter,
1513 hdd_priv_data_t *pPrivData,
1514 tANI_U8 *command
1515)
1516{
1517 tANI_U8 *pDest;
1518 tANI_U32 count = 0;
1519 tANI_U32 len = 0;
1520 tANI_U32 cur_len = 0;
1521 tANI_U32 rem_len = 0;
1522 eHalStatus halStatus;
1523 unsigned long rc;
1524 tSirTriggerBatchScanResultInd *pReq;
1525
1526 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1527 pReq->param = 0;/*batch scan client*/
1528 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1529 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1530
1531 cur_len = pPrivData->used_len;
1532 if (pPrivData->total_len > pPrivData->used_len)
1533 {
1534 rem_len = pPrivData->total_len - pPrivData->used_len;
1535 }
1536 else
1537 {
1538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1539 "%s: Invalid user data buffer total_len %d used_len %d",
1540 __func__, pPrivData->total_len, pPrivData->used_len);
1541 return -EFAULT;
1542 }
1543
1544 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1545 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1546 cur_len, rem_len);
1547 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1548
1549 /*enough scan result available in cache to return to user space or
1550 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001551 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301552 {
1553 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1554 halStatus = sme_TriggerBatchScanResultInd(
1555 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1556 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1557 pAdapter);
1558 if ( eHAL_STATUS_SUCCESS == halStatus )
1559 {
1560 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1561 {
1562 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1563 rc = wait_for_completion_timeout(
1564 &pAdapter->hdd_get_batch_scan_req_var,
1565 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1566 if (0 == rc)
1567 {
1568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1569 "%s: Timeout waiting to fetch batch scan rsp from fw",
1570 __func__);
1571 return -EFAULT;
1572 }
1573 }
1574
1575 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001576 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301577 pDest += len;
1578 cur_len += len;
1579
1580 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1581 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1582 cur_len, rem_len);
1583 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1584
1585 count = 0;
1586 len = (len - pPrivData->used_len);
1587 pDest = (command + pPrivData->used_len);
1588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001589 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301590 while(count < len)
1591 {
1592 printk("%c", *(pDest + count));
1593 count++;
1594 }
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1596 "%s: copy %d data to user buffer", __func__, len);
1597 if (copy_to_user(pPrivData->buf, pDest, len))
1598 {
1599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1600 "%s: failed to copy data to user buffer", __func__);
1601 return -EFAULT;
1602 }
1603 }
1604 else
1605 {
1606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "sme_GetBatchScanScan returned failure halStatus %d",
1608 halStatus);
1609 return -EINVAL;
1610 }
1611 }
1612 else
1613 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301614 count = 0;
1615 len = (len - pPrivData->used_len);
1616 pDest = (command + pPrivData->used_len);
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001618 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301619 while(count < len)
1620 {
1621 printk("%c", *(pDest + count));
1622 count++;
1623 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1625 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301626 if (copy_to_user(pPrivData->buf, pDest, len))
1627 {
1628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1629 "%s: failed to copy data to user buffer", __func__);
1630 return -EFAULT;
1631 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301632 }
1633
1634 return 0;
1635} /*End of hdd_return_batch_scan_rsp_to_user*/
1636
Rajeev Kumar8b373292014-01-08 20:36:55 -08001637
1638/**---------------------------------------------------------------------------
1639
1640 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1641 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1642 WLS_BATCHING VERSION
1643 WLS_BATCHING SET
1644 WLS_BATCHING GET
1645 WLS_BATCHING STOP
1646
1647 \param - pAdapter Pointer to HDD adapter
1648 \param - pPrivdata Pointer to priv_data
1649 \param - command Pointer to command
1650
1651 \return - 0 for success -EFAULT for failure
1652
1653 --------------------------------------------------------------------------*/
1654
1655int hdd_handle_batch_scan_ioctl
1656(
1657 hdd_adapter_t *pAdapter,
1658 hdd_priv_data_t *pPrivdata,
1659 tANI_U8 *command
1660)
1661{
1662 int ret = 0;
1663
1664 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1665 {
1666 char extra[32];
1667 tANI_U8 len = 0;
1668 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1669
1670 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1671 {
1672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1673 "%s: Batch scan feature is not supported by FW", __func__);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
1678 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1679 version);
1680 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1681 {
1682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1683 "%s: failed to copy data to user buffer", __func__);
1684 ret = -EFAULT;
1685 goto exit;
1686 }
1687 ret = HDD_BATCH_SCAN_VERSION;
1688 }
1689 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1690 {
1691 int status;
1692 tANI_U8 *value = (command + 16);
1693 eHalStatus halStatus;
1694 unsigned long rc;
1695 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1696 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1697
1698 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1699 {
1700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1701 "%s: Batch scan feature is not supported by FW", __func__);
1702 ret = -EINVAL;
1703 goto exit;
1704 }
1705
1706 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1707 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1708 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1709 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1710 {
1711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1712 "Received WLS_BATCHING SET command in invalid mode %d "
1713 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1714 pAdapter->device_mode);
1715 ret = -EINVAL;
1716 goto exit;
1717 }
1718
1719 status = hdd_parse_set_batchscan_command(value, pReq);
1720 if (status)
1721 {
1722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1723 "Invalid WLS_BATCHING SET command");
1724 ret = -EINVAL;
1725 goto exit;
1726 }
1727
1728
1729 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1730 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1731 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1732 pAdapter);
1733
1734 if ( eHAL_STATUS_SUCCESS == halStatus )
1735 {
1736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1737 "sme_SetBatchScanReq returned success halStatus %d",
1738 halStatus);
1739 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1740 {
1741 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1742 rc = wait_for_completion_timeout(
1743 &pAdapter->hdd_set_batch_scan_req_var,
1744 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1745 if (0 == rc)
1746 {
1747 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1748 "%s: Timeout waiting for set batch scan to complete",
1749 __func__);
1750 ret = -EINVAL;
1751 goto exit;
1752 }
1753 }
1754 if ( !pRsp->nScansToBatch )
1755 {
1756 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "%s: Received set batch scan failure response from FW",
1758 __func__);
1759 ret = -EINVAL;
1760 goto exit;
1761 }
1762 /*As per the Batch Scan Framework API we should return the MIN of
1763 either MSCAN or the max # of scans firmware can cache*/
1764 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1765
1766 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1767
1768 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1769 "%s: request MSCAN %d response MSCAN %d ret %d",
1770 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1771 }
1772 else
1773 {
1774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 "sme_SetBatchScanReq returned failure halStatus %d",
1776 halStatus);
1777 ret = -EINVAL;
1778 goto exit;
1779 }
1780 }
1781 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1782 {
1783 eHalStatus halStatus;
1784 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1785 pInd->param = 0;
1786
1787 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1788 {
1789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1790 "%s: Batch scan feature is not supported by FW", __func__);
1791 ret = -EINVAL;
1792 goto exit;
1793 }
1794
1795 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1796 {
1797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1798 "Batch scan is not yet enabled batch scan state %d",
1799 pAdapter->batchScanState);
1800 ret = -EINVAL;
1801 goto exit;
1802 }
1803
1804 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1805
1806 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1807 pAdapter->sessionId);
1808 if ( eHAL_STATUS_SUCCESS == halStatus )
1809 {
1810 ret = 0;
1811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1812 "sme_StopBatchScanInd returned success halStatus %d",
1813 halStatus);
1814 }
1815 else
1816 {
1817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1818 "sme_StopBatchScanInd returned failure halStatus %d",
1819 halStatus);
1820 ret = -EINVAL;
1821 goto exit;
1822 }
1823 }
1824 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1825 {
1826 tANI_U32 remain_len;
1827
1828 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1829 {
1830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1831 "%s: Batch scan feature is not supported by FW", __func__);
1832 ret = -EINVAL;
1833 goto exit;
1834 }
1835
1836 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1837 {
1838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1839 "Batch scan is not yet enabled could not return results"
1840 "Batch Scan state %d",
1841 pAdapter->batchScanState);
1842 ret = -EINVAL;
1843 goto exit;
1844 }
1845
1846 pPrivdata->used_len = 16;
1847 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1848 if (remain_len < pPrivdata->total_len)
1849 {
1850 /*Clear previous batch scan response data if any*/
1851 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1852 }
1853 else
1854 {
1855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1856 "Invalid total length from user space can't fetch batch"
1857 " scan response total_len %d used_len %d remain len %d",
1858 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1859 ret = -EINVAL;
1860 goto exit;
1861 }
1862 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1863 }
1864
1865exit:
1866
1867 return ret;
1868}
1869
1870
Rajeev79dbe4c2013-10-05 11:03:42 +05301871#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1872
Jeff Johnson295189b2012-06-20 16:38:30 -07001873int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1874{
1875 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1876 hdd_priv_data_t priv_data;
1877 tANI_U8 *command = NULL;
1878 int ret = 0;
1879
1880 if (NULL == pAdapter)
1881 {
1882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001883 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001884 ret = -ENODEV;
1885 goto exit;
1886 }
1887
Jeff Johnsone7245742012-09-05 17:12:55 -07001888 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001889 {
1890 ret = -EINVAL;
1891 goto exit;
1892 }
1893
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001894 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1895 {
1896 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1897 "%s:LOGP in Progress. Ignore!!!", __func__);
1898 ret = -EBUSY;
1899 goto exit;
1900 }
1901
Jeff Johnson295189b2012-06-20 16:38:30 -07001902 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1903 {
1904 ret = -EFAULT;
1905 goto exit;
1906 }
1907
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08001908 if (priv_data.total_len <= 0 ||
1909 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001910 {
1911 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1912 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1913 priv_data.total_len);
1914 ret = -EINVAL;
1915 goto exit;
1916 }
1917
1918 /* Allocate +1 for '\0' */
1919 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001920 if (!command)
1921 {
1922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001923 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001924 ret = -ENOMEM;
1925 goto exit;
1926 }
1927
1928 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1929 {
1930 ret = -EFAULT;
1931 goto exit;
1932 }
1933
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001934 /* Making sure the command is NUL-terminated */
1935 command[priv_data.total_len] = '\0';
1936
Jeff Johnson295189b2012-06-20 16:38:30 -07001937 if ((SIOCDEVPRIVATE + 1) == cmd)
1938 {
1939 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1940
1941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001942 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001943
1944 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1945 {
1946 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1947 sizeof(tSirMacAddr)))
1948 {
1949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001950 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001951 ret = -EFAULT;
1952 }
1953 }
Amar Singhal0974e402013-02-12 14:27:46 -08001954 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 {
Amar Singhal0974e402013-02-12 14:27:46 -08001956 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001958
Jeff Johnson295189b2012-06-20 16:38:30 -07001959 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001960
1961 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001962 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001963 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001964 "%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 -07001965 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001966 ret = hdd_setBand_helper(dev, ptr);
1967 }
Kiet Lamf040f472013-11-20 21:15:23 +05301968 else if(strncmp(command, "SETWMMPS", 8) == 0)
1969 {
1970 tANI_U8 *ptr = command;
1971 ret = hdd_wmmps_helper(pAdapter, ptr);
1972 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001973 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1974 {
1975 char *country_code;
1976
1977 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001978
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001979 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001980 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001981#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301982 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001983#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001984 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1985 (void *)(tSmeChangeCountryCallback)
1986 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301987 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001988 if (eHAL_STATUS_SUCCESS == ret)
1989 {
1990 ret = wait_for_completion_interruptible_timeout(
1991 &pAdapter->change_country_code,
1992 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1993 if (0 >= ret)
1994 {
1995 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1996 __func__);
1997 }
1998 }
1999 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002000 {
2001 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002002 "%s: SME Change Country code fail ret=%d", __func__, ret);
2003 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002004 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002005
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002006 }
2007 /*
2008 command should be a string having format
2009 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2010 */
Amar Singhal0974e402013-02-12 14:27:46 -08002011 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002012 {
Amar Singhal0974e402013-02-12 14:27:46 -08002013 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002014
2015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002016 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002017
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002018 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002019 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002020 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2021 {
2022 int suspend = 0;
2023 tANI_U8 *ptr = (tANI_U8*)command + 15;
2024
2025 suspend = *ptr - '0';
2026 hdd_set_wlan_suspend_mode(suspend);
2027 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002028#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2029 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2030 {
2031 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002032 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002033 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2034 eHalStatus status = eHAL_STATUS_SUCCESS;
2035
2036 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2037 value = value + 15;
2038
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002039 /* Convert the value from ascii to integer */
2040 ret = kstrtos8(value, 10, &rssi);
2041 if (ret < 0)
2042 {
2043 /* If the input value is greater than max value of datatype, then also
2044 kstrtou8 fails */
2045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2046 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002047 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002048 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2049 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2050 ret = -EINVAL;
2051 goto exit;
2052 }
2053
Srinivas Girigowdade697412013-02-14 16:31:48 -08002054 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002055
Srinivas Girigowdade697412013-02-14 16:31:48 -08002056 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2057 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2058 {
2059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2060 "Neighbor lookup threshold value %d is out of range"
2061 " (Min: %d Max: %d)", lookUpThreshold,
2062 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2063 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2064 ret = -EINVAL;
2065 goto exit;
2066 }
2067
2068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2069 "%s: Received Command to Set Roam trigger"
2070 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2071
2072 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2073 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2074 if (eHAL_STATUS_SUCCESS != status)
2075 {
2076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2077 "%s: Failed to set roam trigger, try again", __func__);
2078 ret = -EPERM;
2079 goto exit;
2080 }
2081
2082 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2083 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2084 }
2085 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2086 {
2087 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2088 int rssi = (-1) * lookUpThreshold;
2089 char extra[32];
2090 tANI_U8 len = 0;
2091
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002092 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002093 if (copy_to_user(priv_data.buf, &extra, len + 1))
2094 {
2095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2096 "%s: failed to copy data to user buffer", __func__);
2097 ret = -EFAULT;
2098 goto exit;
2099 }
2100 }
2101 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2102 {
2103 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002104 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002105 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002106
Srinivas Girigowdade697412013-02-14 16:31:48 -08002107 /* input refresh period is in terms of seconds */
2108 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2109 value = value + 18;
2110 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002111 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002112 if (ret < 0)
2113 {
2114 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002115 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002117 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002118 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002119 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2120 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002121 ret = -EINVAL;
2122 goto exit;
2123 }
2124
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002125 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2126 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002127 {
2128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002129 "Roam scan period value %d is out of range"
2130 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002131 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2132 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002133 ret = -EINVAL;
2134 goto exit;
2135 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002136 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002137
2138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2139 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002140 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002141
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002142 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2143 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002144 }
2145 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2146 {
2147 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2148 char extra[32];
2149 tANI_U8 len = 0;
2150
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002151 len = scnprintf(extra, sizeof(extra), "%s %d",
2152 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002153 /* Returned value is in units of seconds */
2154 if (copy_to_user(priv_data.buf, &extra, len + 1))
2155 {
2156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2157 "%s: failed to copy data to user buffer", __func__);
2158 ret = -EFAULT;
2159 goto exit;
2160 }
2161 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002162 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2163 {
2164 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002165 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002166 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002167
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002168 /* input refresh period is in terms of seconds */
2169 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2170 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002171
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002172 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002173 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002174 if (ret < 0)
2175 {
2176 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002177 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002179 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002180 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002181 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2182 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2183 ret = -EINVAL;
2184 goto exit;
2185 }
2186
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002187 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2188 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2189 {
2190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2191 "Neighbor scan results refresh period value %d is out of range"
2192 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2193 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2194 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2195 ret = -EINVAL;
2196 goto exit;
2197 }
2198 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2199
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2201 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002202 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002203
2204 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2205 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2206 }
2207 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2208 {
2209 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2210 char extra[32];
2211 tANI_U8 len = 0;
2212
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002213 len = scnprintf(extra, sizeof(extra), "%s %d",
2214 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002215 /* Returned value is in units of seconds */
2216 if (copy_to_user(priv_data.buf, &extra, len + 1))
2217 {
2218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2219 "%s: failed to copy data to user buffer", __func__);
2220 ret = -EFAULT;
2221 goto exit;
2222 }
2223 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002224#ifdef FEATURE_WLAN_LFR
2225 /* SETROAMMODE */
2226 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2227 {
2228 tANI_U8 *value = command;
2229 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2230
2231 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2232 value = value + SIZE_OF_SETROAMMODE + 1;
2233
2234 /* Convert the value from ascii to integer */
2235 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2236 if (ret < 0)
2237 {
2238 /* If the input value is greater than max value of datatype, then also
2239 kstrtou8 fails */
2240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2241 "%s: kstrtou8 failed range [%d - %d]", __func__,
2242 CFG_LFR_FEATURE_ENABLED_MIN,
2243 CFG_LFR_FEATURE_ENABLED_MAX);
2244 ret = -EINVAL;
2245 goto exit;
2246 }
2247 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2248 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2249 {
2250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2251 "Roam Mode value %d is out of range"
2252 " (Min: %d Max: %d)", roamMode,
2253 CFG_LFR_FEATURE_ENABLED_MIN,
2254 CFG_LFR_FEATURE_ENABLED_MAX);
2255 ret = -EINVAL;
2256 goto exit;
2257 }
2258
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2260 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2261 /*
2262 * Note that
2263 * SETROAMMODE 0 is to enable LFR while
2264 * SETROAMMODE 1 is to disable LFR, but
2265 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2266 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2267 */
2268 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2269 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2270 else
2271 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2272
2273 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2274 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2275 }
2276 /* GETROAMMODE */
2277 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2278 {
2279 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2280 char extra[32];
2281 tANI_U8 len = 0;
2282
2283 /*
2284 * roamMode value shall be inverted because the sementics is different.
2285 */
2286 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2287 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2288 else
2289 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2290
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002291 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002292 if (copy_to_user(priv_data.buf, &extra, len + 1))
2293 {
2294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2295 "%s: failed to copy data to user buffer", __func__);
2296 ret = -EFAULT;
2297 goto exit;
2298 }
2299 }
2300#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002301#endif
2302#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2303 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2304 {
2305 tANI_U8 *value = command;
2306 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2307
2308 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2309 value = value + 13;
2310 /* Convert the value from ascii to integer */
2311 ret = kstrtou8(value, 10, &roamRssiDiff);
2312 if (ret < 0)
2313 {
2314 /* If the input value is greater than max value of datatype, then also
2315 kstrtou8 fails */
2316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2317 "%s: kstrtou8 failed range [%d - %d]", __func__,
2318 CFG_ROAM_RSSI_DIFF_MIN,
2319 CFG_ROAM_RSSI_DIFF_MAX);
2320 ret = -EINVAL;
2321 goto exit;
2322 }
2323
2324 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2325 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2326 {
2327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2328 "Roam rssi diff value %d is out of range"
2329 " (Min: %d Max: %d)", roamRssiDiff,
2330 CFG_ROAM_RSSI_DIFF_MIN,
2331 CFG_ROAM_RSSI_DIFF_MAX);
2332 ret = -EINVAL;
2333 goto exit;
2334 }
2335
2336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2337 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2338
2339 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2340 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2341 }
2342 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2343 {
2344 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2345 char extra[32];
2346 tANI_U8 len = 0;
2347
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002348 len = scnprintf(extra, sizeof(extra), "%s %d",
2349 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350 if (copy_to_user(priv_data.buf, &extra, len + 1))
2351 {
2352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2353 "%s: failed to copy data to user buffer", __func__);
2354 ret = -EFAULT;
2355 goto exit;
2356 }
2357 }
2358#endif
2359#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2360 else if (strncmp(command, "GETBAND", 7) == 0)
2361 {
2362 int band = -1;
2363 char extra[32];
2364 tANI_U8 len = 0;
2365 hdd_getBand_helper(pHddCtx, &band);
2366
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002367 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368 if (copy_to_user(priv_data.buf, &extra, len + 1))
2369 {
2370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2371 "%s: failed to copy data to user buffer", __func__);
2372 ret = -EFAULT;
2373 goto exit;
2374 }
2375 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2377 {
2378 tANI_U8 *value = command;
2379 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2380 tANI_U8 numChannels = 0;
2381 eHalStatus status = eHAL_STATUS_SUCCESS;
2382
2383 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2384 if (eHAL_STATUS_SUCCESS != status)
2385 {
2386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2387 "%s: Failed to parse channel list information", __func__);
2388 ret = -EINVAL;
2389 goto exit;
2390 }
2391
2392 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2393 {
2394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2395 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2396 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2397 ret = -EINVAL;
2398 goto exit;
2399 }
2400 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2401 numChannels);
2402 if (eHAL_STATUS_SUCCESS != status)
2403 {
2404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2405 "%s: Failed to update channel list information", __func__);
2406 ret = -EINVAL;
2407 goto exit;
2408 }
2409 }
2410 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2411 {
2412 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2413 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002414 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002415 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002416 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002417
2418 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2419 ChannelList, &numChannels ))
2420 {
2421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2422 "%s: failed to get roam scan channel list", __func__);
2423 ret = -EFAULT;
2424 goto exit;
2425 }
2426 /* output channel list is of the format
2427 [Number of roam scan channels][Channel1][Channel2]... */
2428 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002429 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002430 for (j = 0; (j < numChannels); j++)
2431 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002432 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2433 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002434 }
2435
2436 if (copy_to_user(priv_data.buf, &extra, len + 1))
2437 {
2438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2439 "%s: failed to copy data to user buffer", __func__);
2440 ret = -EFAULT;
2441 goto exit;
2442 }
2443 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002444 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2445 {
2446 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2447 char extra[32];
2448 tANI_U8 len = 0;
2449
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002450 /* Check if the features OKC/CCX/11R are supported simultaneously,
2451 then this operation is not permitted (return FAILURE) */
2452 if (ccxMode &&
2453 hdd_is_okc_mode_enabled(pHddCtx) &&
2454 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2455 {
2456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2457 "%s: OKC/CCX/11R are supported simultaneously"
2458 " hence this operation is not permitted!", __func__);
2459 ret = -EPERM;
2460 goto exit;
2461 }
2462
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002463 len = scnprintf(extra, sizeof(extra), "%s %d",
2464 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002465 if (copy_to_user(priv_data.buf, &extra, len + 1))
2466 {
2467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2468 "%s: failed to copy data to user buffer", __func__);
2469 ret = -EFAULT;
2470 goto exit;
2471 }
2472 }
2473 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2474 {
2475 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2476 char extra[32];
2477 tANI_U8 len = 0;
2478
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002479 /* Check if the features OKC/CCX/11R are supported simultaneously,
2480 then this operation is not permitted (return FAILURE) */
2481 if (okcMode &&
2482 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2483 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2484 {
2485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2486 "%s: OKC/CCX/11R are supported simultaneously"
2487 " hence this operation is not permitted!", __func__);
2488 ret = -EPERM;
2489 goto exit;
2490 }
2491
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002492 len = scnprintf(extra, sizeof(extra), "%s %d",
2493 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002494 if (copy_to_user(priv_data.buf, &extra, len + 1))
2495 {
2496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2497 "%s: failed to copy data to user buffer", __func__);
2498 ret = -EFAULT;
2499 goto exit;
2500 }
2501 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002502 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002503 {
2504 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2505 char extra[32];
2506 tANI_U8 len = 0;
2507
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002508 len = scnprintf(extra, sizeof(extra), "%s %d",
2509 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002510 if (copy_to_user(priv_data.buf, &extra, len + 1))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "%s: failed to copy data to user buffer", __func__);
2514 ret = -EFAULT;
2515 goto exit;
2516 }
2517 }
2518 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2519 {
2520 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2521 char extra[32];
2522 tANI_U8 len = 0;
2523
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002524 len = scnprintf(extra, sizeof(extra), "%s %d",
2525 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002526 if (copy_to_user(priv_data.buf, &extra, len + 1))
2527 {
2528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2529 "%s: failed to copy data to user buffer", __func__);
2530 ret = -EFAULT;
2531 goto exit;
2532 }
2533 }
2534 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2535 {
2536 tANI_U8 *value = command;
2537 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2538
2539 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2540 value = value + 26;
2541 /* Convert the value from ascii to integer */
2542 ret = kstrtou8(value, 10, &minTime);
2543 if (ret < 0)
2544 {
2545 /* If the input value is greater than max value of datatype, then also
2546 kstrtou8 fails */
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2548 "%s: kstrtou8 failed range [%d - %d]", __func__,
2549 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2550 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2551 ret = -EINVAL;
2552 goto exit;
2553 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002554 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2555 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2556 {
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "scan min channel time value %d is out of range"
2559 " (Min: %d Max: %d)", minTime,
2560 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2561 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2562 ret = -EINVAL;
2563 goto exit;
2564 }
2565
2566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2567 "%s: Received Command to change channel min time = %d", __func__, minTime);
2568
2569 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2570 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2571 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002572 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2573 {
2574 tANI_U8 *value = command;
2575 tANI_U8 channel = 0;
2576 tANI_U8 dwellTime = 0;
2577 tANI_U8 bufLen = 0;
2578 tANI_U8 *buf = NULL;
2579 tSirMacAddr targetApBssid;
2580 eHalStatus status = eHAL_STATUS_SUCCESS;
2581 struct ieee80211_channel chan;
2582 tANI_U8 finalLen = 0;
2583 tANI_U8 *finalBuf = NULL;
2584 tANI_U8 temp = 0;
2585 u64 cookie;
2586 hdd_station_ctx_t *pHddStaCtx = NULL;
2587 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2588
2589 /* if not associated, no need to send action frame */
2590 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2591 {
2592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2593 ret = -EINVAL;
2594 goto exit;
2595 }
2596
2597 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2598 &dwellTime, &buf, &bufLen);
2599 if (eHAL_STATUS_SUCCESS != status)
2600 {
2601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2602 "%s: Failed to parse send action frame data", __func__);
2603 ret = -EINVAL;
2604 goto exit;
2605 }
2606
2607 /* if the target bssid is different from currently associated AP,
2608 then no need to send action frame */
2609 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2610 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2611 {
2612 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2613 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002614 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002615 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002616 goto exit;
2617 }
2618
2619 /* if the channel number is different from operating channel then
2620 no need to send action frame */
2621 if (channel != pHddStaCtx->conn_info.operationChannel)
2622 {
2623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2624 "%s: channel(%d) is different from operating channel(%d)",
2625 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2626 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002627 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002628 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002629 goto exit;
2630 }
2631 chan.center_freq = sme_ChnToFreq(channel);
2632
2633 finalLen = bufLen + 24;
2634 finalBuf = vos_mem_malloc(finalLen);
2635 if (NULL == finalBuf)
2636 {
2637 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2638 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002639 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002640 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002641 goto exit;
2642 }
2643 vos_mem_zero(finalBuf, finalLen);
2644
2645 /* Fill subtype */
2646 temp = SIR_MAC_MGMT_ACTION << 4;
2647 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2648
2649 /* Fill type */
2650 temp = SIR_MAC_MGMT_FRAME;
2651 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2652
2653 /* Fill destination address (bssid of the AP) */
2654 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2655
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002656 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002657 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2658
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002659 /* Fill BSSID (AP mac address) */
2660 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002661
2662 /* Fill received buffer from 24th address */
2663 vos_mem_copy(finalBuf + 24, buf, bufLen);
2664
Jeff Johnson11c33152013-04-16 17:52:40 -07002665 /* done with the parsed buffer */
2666 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002667 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002668
Yue Maf49ba872013-08-19 12:04:25 -07002669 wlan_hdd_action( NULL,
2670#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2671 &(pAdapter->wdev),
2672#else
2673 dev,
2674#endif
2675 &chan, 0,
2676#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2677 NL80211_CHAN_HT20, 1,
2678#endif
2679 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002680 1, &cookie );
2681 vos_mem_free(finalBuf);
2682 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002683 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2684 {
2685 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2686 char extra[32];
2687 tANI_U8 len = 0;
2688
2689 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002690 len = scnprintf(extra, sizeof(extra), "%s %d",
2691 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002692 if (copy_to_user(priv_data.buf, &extra, len + 1))
2693 {
2694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2695 "%s: failed to copy data to user buffer", __func__);
2696 ret = -EFAULT;
2697 goto exit;
2698 }
2699 }
2700 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2701 {
2702 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002703 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002704
2705 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2706 value = value + 19;
2707 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002708 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002709 if (ret < 0)
2710 {
2711 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002712 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002714 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002715 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2716 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2717 ret = -EINVAL;
2718 goto exit;
2719 }
2720
2721 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2722 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2723 {
2724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2725 "lfr mode value %d is out of range"
2726 " (Min: %d Max: %d)", maxTime,
2727 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2728 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2729 ret = -EINVAL;
2730 goto exit;
2731 }
2732
2733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2734 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2735
2736 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2737 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2738 }
2739 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2740 {
2741 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2742 char extra[32];
2743 tANI_U8 len = 0;
2744
2745 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002746 len = scnprintf(extra, sizeof(extra), "%s %d",
2747 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002748 if (copy_to_user(priv_data.buf, &extra, len + 1))
2749 {
2750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2751 "%s: failed to copy data to user buffer", __func__);
2752 ret = -EFAULT;
2753 goto exit;
2754 }
2755 }
2756 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2757 {
2758 tANI_U8 *value = command;
2759 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2760
2761 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2762 value = value + 16;
2763 /* Convert the value from ascii to integer */
2764 ret = kstrtou16(value, 10, &val);
2765 if (ret < 0)
2766 {
2767 /* If the input value is greater than max value of datatype, then also
2768 kstrtou16 fails */
2769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2770 "%s: kstrtou16 failed range [%d - %d]", __func__,
2771 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2772 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2773 ret = -EINVAL;
2774 goto exit;
2775 }
2776
2777 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2778 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2779 {
2780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2781 "scan home time value %d is out of range"
2782 " (Min: %d Max: %d)", val,
2783 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2784 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2785 ret = -EINVAL;
2786 goto exit;
2787 }
2788
2789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2790 "%s: Received Command to change scan home time = %d", __func__, val);
2791
2792 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2793 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2794 }
2795 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2796 {
2797 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2798 char extra[32];
2799 tANI_U8 len = 0;
2800
2801 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002802 len = scnprintf(extra, sizeof(extra), "%s %d",
2803 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002804 if (copy_to_user(priv_data.buf, &extra, len + 1))
2805 {
2806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2807 "%s: failed to copy data to user buffer", __func__);
2808 ret = -EFAULT;
2809 goto exit;
2810 }
2811 }
2812 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2813 {
2814 tANI_U8 *value = command;
2815 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2816
2817 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2818 value = value + 17;
2819 /* Convert the value from ascii to integer */
2820 ret = kstrtou8(value, 10, &val);
2821 if (ret < 0)
2822 {
2823 /* If the input value is greater than max value of datatype, then also
2824 kstrtou8 fails */
2825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2826 "%s: kstrtou8 failed range [%d - %d]", __func__,
2827 CFG_ROAM_INTRA_BAND_MIN,
2828 CFG_ROAM_INTRA_BAND_MAX);
2829 ret = -EINVAL;
2830 goto exit;
2831 }
2832
2833 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2834 (val > CFG_ROAM_INTRA_BAND_MAX))
2835 {
2836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2837 "intra band mode value %d is out of range"
2838 " (Min: %d Max: %d)", val,
2839 CFG_ROAM_INTRA_BAND_MIN,
2840 CFG_ROAM_INTRA_BAND_MAX);
2841 ret = -EINVAL;
2842 goto exit;
2843 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2845 "%s: Received Command to change intra band = %d", __func__, val);
2846
2847 pHddCtx->cfg_ini->nRoamIntraBand = val;
2848 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2849 }
2850 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2851 {
2852 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2853 char extra[32];
2854 tANI_U8 len = 0;
2855
2856 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002857 len = scnprintf(extra, sizeof(extra), "%s %d",
2858 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002859 if (copy_to_user(priv_data.buf, &extra, len + 1))
2860 {
2861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2862 "%s: failed to copy data to user buffer", __func__);
2863 ret = -EFAULT;
2864 goto exit;
2865 }
2866 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002867 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2868 {
2869 tANI_U8 *value = command;
2870 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2871
2872 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2873 value = value + 15;
2874 /* Convert the value from ascii to integer */
2875 ret = kstrtou8(value, 10, &nProbes);
2876 if (ret < 0)
2877 {
2878 /* If the input value is greater than max value of datatype, then also
2879 kstrtou8 fails */
2880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2881 "%s: kstrtou8 failed range [%d - %d]", __func__,
2882 CFG_ROAM_SCAN_N_PROBES_MIN,
2883 CFG_ROAM_SCAN_N_PROBES_MAX);
2884 ret = -EINVAL;
2885 goto exit;
2886 }
2887
2888 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2889 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2890 {
2891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2892 "NProbes value %d is out of range"
2893 " (Min: %d Max: %d)", nProbes,
2894 CFG_ROAM_SCAN_N_PROBES_MIN,
2895 CFG_ROAM_SCAN_N_PROBES_MAX);
2896 ret = -EINVAL;
2897 goto exit;
2898 }
2899
2900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2901 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2902
2903 pHddCtx->cfg_ini->nProbes = nProbes;
2904 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2905 }
2906 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2907 {
2908 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2909 char extra[32];
2910 tANI_U8 len = 0;
2911
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002912 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002913 if (copy_to_user(priv_data.buf, &extra, len + 1))
2914 {
2915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2916 "%s: failed to copy data to user buffer", __func__);
2917 ret = -EFAULT;
2918 goto exit;
2919 }
2920 }
2921 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2922 {
2923 tANI_U8 *value = command;
2924 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2925
2926 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2927 /* input value is in units of msec */
2928 value = value + 20;
2929 /* Convert the value from ascii to integer */
2930 ret = kstrtou16(value, 10, &homeAwayTime);
2931 if (ret < 0)
2932 {
2933 /* If the input value is greater than max value of datatype, then also
2934 kstrtou8 fails */
2935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2936 "%s: kstrtou8 failed range [%d - %d]", __func__,
2937 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2938 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2939 ret = -EINVAL;
2940 goto exit;
2941 }
2942
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002943 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2944 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2945 {
2946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2947 "homeAwayTime value %d is out of range"
2948 " (Min: %d Max: %d)", homeAwayTime,
2949 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2950 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2951 ret = -EINVAL;
2952 goto exit;
2953 }
2954
2955 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2956 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002957 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2958 {
2959 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2960 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2961 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002962 }
2963 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2964 {
2965 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2966 char extra[32];
2967 tANI_U8 len = 0;
2968
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002969 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002970 if (copy_to_user(priv_data.buf, &extra, len + 1))
2971 {
2972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2973 "%s: failed to copy data to user buffer", __func__);
2974 ret = -EFAULT;
2975 goto exit;
2976 }
2977 }
2978 else if (strncmp(command, "REASSOC", 7) == 0)
2979 {
2980 tANI_U8 *value = command;
2981 tANI_U8 channel = 0;
2982 tSirMacAddr targetApBssid;
2983 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002984#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2985 tCsrHandoffRequest handoffInfo;
2986#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002987 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002988 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2989
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002990 /* if not associated, no need to proceed with reassoc */
2991 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2992 {
2993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2994 ret = -EINVAL;
2995 goto exit;
2996 }
2997
2998 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2999 if (eHAL_STATUS_SUCCESS != status)
3000 {
3001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3002 "%s: Failed to parse reassoc command data", __func__);
3003 ret = -EINVAL;
3004 goto exit;
3005 }
3006
3007 /* if the target bssid is same as currently associated AP,
3008 then no need to proceed with reassoc */
3009 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3010 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3011 {
3012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3013 ret = -EINVAL;
3014 goto exit;
3015 }
3016
3017 /* Check channel number is a valid channel number */
3018 if(VOS_STATUS_SUCCESS !=
3019 wlan_hdd_validate_operation_channel(pAdapter, channel))
3020 {
3021 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003022 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003023 return -EINVAL;
3024 }
3025
3026 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003027#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3028 handoffInfo.channel = channel;
3029 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3030 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3031#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003032 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003033 else if (strncmp(command, "SETWESMODE", 10) == 0)
3034 {
3035 tANI_U8 *value = command;
3036 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3037
3038 /* Move pointer to ahead of SETWESMODE<delimiter> */
3039 value = value + 11;
3040 /* Convert the value from ascii to integer */
3041 ret = kstrtou8(value, 10, &wesMode);
3042 if (ret < 0)
3043 {
3044 /* If the input value is greater than max value of datatype, then also
3045 kstrtou8 fails */
3046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3047 "%s: kstrtou8 failed range [%d - %d]", __func__,
3048 CFG_ENABLE_WES_MODE_NAME_MIN,
3049 CFG_ENABLE_WES_MODE_NAME_MAX);
3050 ret = -EINVAL;
3051 goto exit;
3052 }
3053
3054 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3055 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3056 {
3057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3058 "WES Mode value %d is out of range"
3059 " (Min: %d Max: %d)", wesMode,
3060 CFG_ENABLE_WES_MODE_NAME_MIN,
3061 CFG_ENABLE_WES_MODE_NAME_MAX);
3062 ret = -EINVAL;
3063 goto exit;
3064 }
3065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3066 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3067
3068 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3069 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3070 }
3071 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3072 {
3073 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3074 char extra[32];
3075 tANI_U8 len = 0;
3076
Arif Hussain826d9412013-11-12 16:44:54 -08003077 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003078 if (copy_to_user(priv_data.buf, &extra, len + 1))
3079 {
3080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3081 "%s: failed to copy data to user buffer", __func__);
3082 ret = -EFAULT;
3083 goto exit;
3084 }
3085 }
3086#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003087#ifdef FEATURE_WLAN_LFR
3088 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3089 {
3090 tANI_U8 *value = command;
3091 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3092
3093 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3094 value = value + 12;
3095 /* Convert the value from ascii to integer */
3096 ret = kstrtou8(value, 10, &lfrMode);
3097 if (ret < 0)
3098 {
3099 /* If the input value is greater than max value of datatype, then also
3100 kstrtou8 fails */
3101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3102 "%s: kstrtou8 failed range [%d - %d]", __func__,
3103 CFG_LFR_FEATURE_ENABLED_MIN,
3104 CFG_LFR_FEATURE_ENABLED_MAX);
3105 ret = -EINVAL;
3106 goto exit;
3107 }
3108
3109 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3110 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3111 {
3112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3113 "lfr mode value %d is out of range"
3114 " (Min: %d Max: %d)", lfrMode,
3115 CFG_LFR_FEATURE_ENABLED_MIN,
3116 CFG_LFR_FEATURE_ENABLED_MAX);
3117 ret = -EINVAL;
3118 goto exit;
3119 }
3120
3121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3122 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3123
3124 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3125 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3126 }
3127#endif
3128#ifdef WLAN_FEATURE_VOWIFI_11R
3129 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3130 {
3131 tANI_U8 *value = command;
3132 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3133
3134 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3135 value = value + 18;
3136 /* Convert the value from ascii to integer */
3137 ret = kstrtou8(value, 10, &ft);
3138 if (ret < 0)
3139 {
3140 /* If the input value is greater than max value of datatype, then also
3141 kstrtou8 fails */
3142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3143 "%s: kstrtou8 failed range [%d - %d]", __func__,
3144 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3145 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3146 ret = -EINVAL;
3147 goto exit;
3148 }
3149
3150 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3151 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3152 {
3153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3154 "ft mode value %d is out of range"
3155 " (Min: %d Max: %d)", ft,
3156 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3157 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3158 ret = -EINVAL;
3159 goto exit;
3160 }
3161
3162 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3163 "%s: Received Command to change ft mode = %d", __func__, ft);
3164
3165 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3166 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3167 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303168
3169 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3170 {
3171 tANI_U8 *value = command;
3172 tSirMacAddr targetApBssid;
3173 tANI_U8 trigger = 0;
3174 eHalStatus status = eHAL_STATUS_SUCCESS;
3175 hdd_station_ctx_t *pHddStaCtx = NULL;
3176 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3177
3178 /* if not associated, no need to proceed with reassoc */
3179 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3180 {
3181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3182 ret = -EINVAL;
3183 goto exit;
3184 }
3185
3186 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3187 if (eHAL_STATUS_SUCCESS != status)
3188 {
3189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3190 "%s: Failed to parse reassoc command data", __func__);
3191 ret = -EINVAL;
3192 goto exit;
3193 }
3194
3195 /* if the target bssid is same as currently associated AP,
3196 then no need to proceed with reassoc */
3197 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3198 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3199 {
3200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3201 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3202 __func__);
3203 ret = -EINVAL;
3204 goto exit;
3205 }
3206
3207 /* Proceed with scan/roam */
3208 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3209 &targetApBssid[0],
3210 (tSmeFastRoamTrigger)(trigger));
3211 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003212#endif
3213#ifdef FEATURE_WLAN_CCX
3214 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3215 {
3216 tANI_U8 *value = command;
3217 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
3218
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003219 /* Check if the features OKC/CCX/11R are supported simultaneously,
3220 then this operation is not permitted (return FAILURE) */
3221 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3222 hdd_is_okc_mode_enabled(pHddCtx) &&
3223 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3224 {
3225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3226 "%s: OKC/CCX/11R are supported simultaneously"
3227 " hence this operation is not permitted!", __func__);
3228 ret = -EPERM;
3229 goto exit;
3230 }
3231
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003232 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3233 value = value + 11;
3234 /* Convert the value from ascii to integer */
3235 ret = kstrtou8(value, 10, &ccxMode);
3236 if (ret < 0)
3237 {
3238 /* If the input value is greater than max value of datatype, then also
3239 kstrtou8 fails */
3240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3241 "%s: kstrtou8 failed range [%d - %d]", __func__,
3242 CFG_CCX_FEATURE_ENABLED_MIN,
3243 CFG_CCX_FEATURE_ENABLED_MAX);
3244 ret = -EINVAL;
3245 goto exit;
3246 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003247 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3248 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3249 {
3250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3251 "Ccx mode value %d is out of range"
3252 " (Min: %d Max: %d)", ccxMode,
3253 CFG_CCX_FEATURE_ENABLED_MIN,
3254 CFG_CCX_FEATURE_ENABLED_MAX);
3255 ret = -EINVAL;
3256 goto exit;
3257 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3259 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3260
3261 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3262 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3263 }
3264#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003265 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3266 {
3267 tANI_U8 *value = command;
3268 tANI_BOOLEAN roamScanControl = 0;
3269
3270 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3271 value = value + 19;
3272 /* Convert the value from ascii to integer */
3273 ret = kstrtou8(value, 10, &roamScanControl);
3274 if (ret < 0)
3275 {
3276 /* If the input value is greater than max value of datatype, then also
3277 kstrtou8 fails */
3278 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3279 "%s: kstrtou8 failed ", __func__);
3280 ret = -EINVAL;
3281 goto exit;
3282 }
3283
3284 if (0 != roamScanControl)
3285 {
3286 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3287 "roam scan control invalid value = %d",
3288 roamScanControl);
3289 ret = -EINVAL;
3290 goto exit;
3291 }
3292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3293 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3294
3295 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3296 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003297#ifdef FEATURE_WLAN_OKC
3298 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3299 {
3300 tANI_U8 *value = command;
3301 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3302
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003303 /* Check if the features OKC/CCX/11R are supported simultaneously,
3304 then this operation is not permitted (return FAILURE) */
3305 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3306 hdd_is_okc_mode_enabled(pHddCtx) &&
3307 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3308 {
3309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3310 "%s: OKC/CCX/11R are supported simultaneously"
3311 " hence this operation is not permitted!", __func__);
3312 ret = -EPERM;
3313 goto exit;
3314 }
3315
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003316 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3317 value = value + 11;
3318 /* Convert the value from ascii to integer */
3319 ret = kstrtou8(value, 10, &okcMode);
3320 if (ret < 0)
3321 {
3322 /* If the input value is greater than max value of datatype, then also
3323 kstrtou8 fails */
3324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3325 "%s: kstrtou8 failed range [%d - %d]", __func__,
3326 CFG_OKC_FEATURE_ENABLED_MIN,
3327 CFG_OKC_FEATURE_ENABLED_MAX);
3328 ret = -EINVAL;
3329 goto exit;
3330 }
3331
3332 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3333 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3334 {
3335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3336 "Okc mode value %d is out of range"
3337 " (Min: %d Max: %d)", okcMode,
3338 CFG_OKC_FEATURE_ENABLED_MIN,
3339 CFG_OKC_FEATURE_ENABLED_MAX);
3340 ret = -EINVAL;
3341 goto exit;
3342 }
3343
3344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3345 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3346
3347 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3348 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003349#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003350 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3351 {
3352 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3353 char extra[32];
3354 tANI_U8 len = 0;
3355
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003356 len = scnprintf(extra, sizeof(extra), "%s %d",
3357 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -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 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303366#ifdef WLAN_FEATURE_PACKET_FILTERING
3367 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3368 {
3369 tANI_U8 filterType = 0;
3370 tANI_U8 *value = command;
3371
3372 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3373 value = value + 22;
3374
3375 /* Convert the value from ascii to integer */
3376 ret = kstrtou8(value, 10, &filterType);
3377 if (ret < 0)
3378 {
3379 /* If the input value is greater than max value of datatype,
3380 * then also kstrtou8 fails
3381 */
3382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3383 "%s: kstrtou8 failed range ", __func__);
3384 ret = -EINVAL;
3385 goto exit;
3386 }
3387
3388 if (filterType != 0 && filterType != 1)
3389 {
3390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3391 "%s: Accepted Values are 0 and 1 ", __func__);
3392 ret = -EINVAL;
3393 goto exit;
3394 }
3395 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3396 pAdapter->sessionId);
3397 }
3398#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303399 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3400 {
3401 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303402 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303403 if ('1' == *dhcpPhase)
3404 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3406 FL("BTCOEXMODE %d"), *dhcpPhase);
3407
3408 pHddCtx->btCoexModeSet = TRUE;
3409
3410 /* Firmware failing to process DHCP START/STOP indications.
3411 * So, for now commentig below code, once issue is resolved,
3412 * follwing will be uncommented.
3413 */
3414 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303415 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3416 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303417 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303418 }
3419 else if ('2' == *dhcpPhase)
3420 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3422 FL("BTCOEXMODE %d"), *dhcpPhase);
3423
3424 pHddCtx->btCoexModeSet = FALSE;
3425
3426 /* Firmware failing to process DHCP START/STOP indications.
3427 * So, for now commentig below code, once issue is resolved,
3428 * follwing will be uncommented.
3429 */
3430 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303431 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3432 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303433 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303434 }
3435 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003436 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3437 {
3438 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3439 }
3440 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3441 {
3442 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3443 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303444 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3445 {
3446 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3447 char extra[32];
3448 tANI_U8 len = 0;
3449
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003450 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303451 (int)pCfg->nActiveMaxChnTime);
3452 if (copy_to_user(priv_data.buf, &extra, len + 1))
3453 {
3454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3455 "%s: failed to copy data to user buffer", __func__);
3456 ret = -EFAULT;
3457 goto exit;
3458 }
3459 ret = len;
3460 }
3461 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3462 {
3463 tANI_U8 *value = command;
3464 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3465 int val = 0, temp;
3466
3467 value = value + 13;
3468 temp = kstrtou32(value, 10, &val);
3469 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3470 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3471 {
3472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3473 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3474 ret = -EFAULT;
3475 goto exit;
3476 }
3477 pCfg->nActiveMaxChnTime = val;
3478 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003479 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3480 {
3481 tANI_U8 filterType = 0;
3482 tANI_U8 *value;
3483 value = command + 9;
3484
3485 /* Convert the value from ascii to integer */
3486 ret = kstrtou8(value, 10, &filterType);
3487 if (ret < 0)
3488 {
3489 /* If the input value is greater than max value of datatype,
3490 * then also kstrtou8 fails
3491 */
3492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3493 "%s: kstrtou8 failed range ", __func__);
3494 ret = -EINVAL;
3495 goto exit;
3496 }
3497 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3498 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3499 {
3500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3501 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3502 " 2-Sink ", __func__);
3503 ret = -EINVAL;
3504 goto exit;
3505 }
3506 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3507 pHddCtx->drvr_miracast = filterType;
3508 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3509 }
Leo Chang614d2072013-08-22 14:59:44 -07003510 else if (strncmp(command, "SETMCRATE", 9) == 0)
3511 {
Leo Chang614d2072013-08-22 14:59:44 -07003512 tANI_U8 *value = command;
3513 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003514 tSirRateUpdateInd *rateUpdate;
3515 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003516
3517 /* Only valid for SAP mode */
3518 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3519 {
3520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3521 "%s: SAP mode is not running", __func__);
3522 ret = -EFAULT;
3523 goto exit;
3524 }
3525
3526 /* Move pointer to ahead of SETMCRATE<delimiter> */
3527 /* input value is in units of hundred kbps */
3528 value = value + 10;
3529 /* Convert the value from ascii to integer, decimal base */
3530 ret = kstrtouint(value, 10, &targetRate);
3531
Leo Chang1f98cbd2013-10-17 15:03:52 -07003532 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3533 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003534 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003535 hddLog(VOS_TRACE_LEVEL_ERROR,
3536 "%s: SETMCRATE indication alloc fail", __func__);
3537 ret = -EFAULT;
3538 goto exit;
3539 }
3540 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3541
3542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3543 "MC Target rate %d", targetRate);
3544 /* Ignore unicast */
3545 rateUpdate->ucastDataRate = -1;
3546 rateUpdate->mcastDataRate24GHz = targetRate;
3547 rateUpdate->mcastDataRate5GHz = targetRate;
3548 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3549 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3550 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3551 if (eHAL_STATUS_SUCCESS != status)
3552 {
3553 hddLog(VOS_TRACE_LEVEL_ERROR,
3554 "%s: SET_MC_RATE failed", __func__);
3555 vos_mem_free(rateUpdate);
3556 ret = -EFAULT;
3557 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003558 }
3559 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303560#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003561 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303562 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003563 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303564 }
3565#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003566#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3567 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3568 {
3569 tANI_U8 *value = command;
3570 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3571 tANI_U8 numChannels = 0;
3572 eHalStatus status = eHAL_STATUS_SUCCESS;
3573
3574 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3575 if (eHAL_STATUS_SUCCESS != status)
3576 {
3577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3578 "%s: Failed to parse channel list information", __func__);
3579 ret = -EINVAL;
3580 goto exit;
3581 }
3582
3583 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3584 {
3585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3586 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3587 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3588 ret = -EINVAL;
3589 goto exit;
3590 }
3591 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3592 ChannelList,
3593 numChannels);
3594 if (eHAL_STATUS_SUCCESS != status)
3595 {
3596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3597 "%s: Failed to update channel list information", __func__);
3598 ret = -EINVAL;
3599 goto exit;
3600 }
3601 }
3602 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3603 {
3604 tANI_U8 *value = command;
3605 char extra[128] = {0};
3606 int len = 0;
3607 tANI_U8 tid = 0;
3608 hdd_station_ctx_t *pHddStaCtx = NULL;
3609 tAniTrafStrmMetrics tsmMetrics;
3610 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3611
3612 /* if not associated, return error */
3613 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3614 {
3615 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3616 ret = -EINVAL;
3617 goto exit;
3618 }
3619
3620 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3621 value = value + 12;
3622 /* Convert the value from ascii to integer */
3623 ret = kstrtou8(value, 10, &tid);
3624 if (ret < 0)
3625 {
3626 /* If the input value is greater than max value of datatype, then also
3627 kstrtou8 fails */
3628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3629 "%s: kstrtou8 failed range [%d - %d]", __func__,
3630 TID_MIN_VALUE,
3631 TID_MAX_VALUE);
3632 ret = -EINVAL;
3633 goto exit;
3634 }
3635
3636 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3637 {
3638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3639 "tid value %d is out of range"
3640 " (Min: %d Max: %d)", tid,
3641 TID_MIN_VALUE,
3642 TID_MAX_VALUE);
3643 ret = -EINVAL;
3644 goto exit;
3645 }
3646
3647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3648 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3649
3650 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3651 {
3652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3653 "%s: failed to get tsm stats", __func__);
3654 ret = -EFAULT;
3655 goto exit;
3656 }
3657
3658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3659 "UplinkPktQueueDly(%d)\n"
3660 "UplinkPktQueueDlyHist[0](%d)\n"
3661 "UplinkPktQueueDlyHist[1](%d)\n"
3662 "UplinkPktQueueDlyHist[2](%d)\n"
3663 "UplinkPktQueueDlyHist[3](%d)\n"
3664 "UplinkPktTxDly(%lu)\n"
3665 "UplinkPktLoss(%d)\n"
3666 "UplinkPktCount(%d)\n"
3667 "RoamingCount(%d)\n"
3668 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3669 tsmMetrics.UplinkPktQueueDlyHist[0],
3670 tsmMetrics.UplinkPktQueueDlyHist[1],
3671 tsmMetrics.UplinkPktQueueDlyHist[2],
3672 tsmMetrics.UplinkPktQueueDlyHist[3],
3673 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3674 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3675
3676 /* Output TSM stats is of the format
3677 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3678 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003679 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003680 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3681 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3682 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3683 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3684 tsmMetrics.RoamingDly);
3685
3686 if (copy_to_user(priv_data.buf, &extra, len + 1))
3687 {
3688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3689 "%s: failed to copy data to user buffer", __func__);
3690 ret = -EFAULT;
3691 goto exit;
3692 }
3693 }
3694 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3695 {
3696 tANI_U8 *value = command;
3697 tANI_U8 *cckmIe = NULL;
3698 tANI_U8 cckmIeLen = 0;
3699 eHalStatus status = eHAL_STATUS_SUCCESS;
3700
3701 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3702 if (eHAL_STATUS_SUCCESS != status)
3703 {
3704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3705 "%s: Failed to parse cckm ie data", __func__);
3706 ret = -EINVAL;
3707 goto exit;
3708 }
3709
3710 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3711 {
3712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3713 "%s: CCKM Ie input length is more than max[%d]", __func__,
3714 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003715 vos_mem_free(cckmIe);
3716 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003717 ret = -EINVAL;
3718 goto exit;
3719 }
3720 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003721 vos_mem_free(cckmIe);
3722 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003723 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003724 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3725 {
3726 tANI_U8 *value = command;
3727 tCsrCcxBeaconReq ccxBcnReq;
3728 eHalStatus status = eHAL_STATUS_SUCCESS;
3729 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3730 if (eHAL_STATUS_SUCCESS != status)
3731 {
3732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3733 "%s: Failed to parse ccx beacon req", __func__);
3734 ret = -EINVAL;
3735 goto exit;
3736 }
3737
3738 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3739 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003740#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003741 else {
3742 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3743 __func__, command);
3744 }
3745
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 }
3747exit:
3748 if (command)
3749 {
3750 kfree(command);
3751 }
3752 return ret;
3753}
3754
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003755
3756
3757#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003758/**---------------------------------------------------------------------------
3759
3760 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3761
3762 This function parses the ccx beacon request passed in the format
3763 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3764 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3765 <space>Scan Mode N<space>Meas Duration N
3766 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3767 then take N.
3768 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3769 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3770 This function does not take care of removing duplicate channels from the list
3771
3772 \param - pValue Pointer to data
3773 \param - pCcxBcnReq output pointer to store parsed ie information
3774
3775 \return - 0 for success non-zero for failure
3776
3777 --------------------------------------------------------------------------*/
3778static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3779 tCsrCcxBeaconReq *pCcxBcnReq)
3780{
3781 tANI_U8 *inPtr = pValue;
3782 int tempInt = 0;
3783 int j = 0, i = 0, v = 0;
3784 char buf[32];
3785
3786 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3787 /*no argument after the command*/
3788 if (NULL == inPtr)
3789 {
3790 return -EINVAL;
3791 }
3792 /*no space after the command*/
3793 else if (SPACE_ASCII_VALUE != *inPtr)
3794 {
3795 return -EINVAL;
3796 }
3797
3798 /*removing empty spaces*/
3799 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3800
3801 /*no argument followed by spaces*/
3802 if ('\0' == *inPtr) return -EINVAL;
3803
3804 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003805 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003806 if (1 != v) return -EINVAL;
3807
3808 v = kstrtos32(buf, 10, &tempInt);
3809 if ( v < 0) return -EINVAL;
3810
3811 pCcxBcnReq->numBcnReqIe = tempInt;
3812
3813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3814 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3815
3816 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3817 {
3818 for (i = 0; i < 4; i++)
3819 {
3820 /*inPtr pointing to the beginning of first space after number of ie fields*/
3821 inPtr = strpbrk( inPtr, " " );
3822 /*no ie data after the number of ie fields argument*/
3823 if (NULL == inPtr) return -EINVAL;
3824
3825 /*removing empty space*/
3826 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3827
3828 /*no ie data after the number of ie fields argument and spaces*/
3829 if ( '\0' == *inPtr ) return -EINVAL;
3830
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003831 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003832 if (1 != v) return -EINVAL;
3833
3834 v = kstrtos32(buf, 10, &tempInt);
3835 if (v < 0) return -EINVAL;
3836
3837 switch (i)
3838 {
3839 case 0: /* Measurement token */
3840 if (tempInt <= 0)
3841 {
3842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3843 "Invalid Measurement Token(%d)", tempInt);
3844 return -EINVAL;
3845 }
3846 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3847 break;
3848
3849 case 1: /* Channel number */
3850 if ((tempInt <= 0) ||
3851 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3852 {
3853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3854 "Invalid Channel Number(%d)", tempInt);
3855 return -EINVAL;
3856 }
3857 pCcxBcnReq->bcnReq[j].channel = tempInt;
3858 break;
3859
3860 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003861 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003862 {
3863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3864 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3865 return -EINVAL;
3866 }
3867 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3868 break;
3869
3870 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003871 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3872 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003873 {
3874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3875 "Invalid Measurement Duration(%d)", tempInt);
3876 return -EINVAL;
3877 }
3878 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3879 break;
3880 }
3881 }
3882 }
3883
3884 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3885 {
3886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3887 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3888 j,
3889 pCcxBcnReq->bcnReq[j].measurementToken,
3890 pCcxBcnReq->bcnReq[j].channel,
3891 pCcxBcnReq->bcnReq[j].scanMode,
3892 pCcxBcnReq->bcnReq[j].measurementDuration);
3893 }
3894
3895 return VOS_STATUS_SUCCESS;
3896}
3897
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003898static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3899{
3900 struct statsContext *pStatsContext = NULL;
3901 hdd_adapter_t *pAdapter = NULL;
3902
3903 if (NULL == pContext)
3904 {
3905 hddLog(VOS_TRACE_LEVEL_ERROR,
3906 "%s: Bad param, pContext [%p]",
3907 __func__, pContext);
3908 return;
3909 }
3910
Jeff Johnson72a40512013-12-19 10:14:15 -08003911 /* there is a race condition that exists between this callback
3912 function and the caller since the caller could time out either
3913 before or while this code is executing. we use a spinlock to
3914 serialize these actions */
3915 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003916
3917 pStatsContext = pContext;
3918 pAdapter = pStatsContext->pAdapter;
3919 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3920 {
3921 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003922 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003923 hddLog(VOS_TRACE_LEVEL_WARN,
3924 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3925 __func__, pAdapter, pStatsContext->magic);
3926 return;
3927 }
3928
Jeff Johnson72a40512013-12-19 10:14:15 -08003929 /* context is valid so caller is still waiting */
3930
3931 /* paranoia: invalidate the magic */
3932 pStatsContext->magic = 0;
3933
3934 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003935 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3936 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3937 tsmMetrics.UplinkPktQueueDlyHist,
3938 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3939 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3940 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3941 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3942 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3943 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3944 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3945
Jeff Johnson72a40512013-12-19 10:14:15 -08003946 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003947 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003948
3949 /* serialization is complete */
3950 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003951}
3952
3953
3954
3955static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3956 tAniTrafStrmMetrics* pTsmMetrics)
3957{
3958 hdd_station_ctx_t *pHddStaCtx = NULL;
3959 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003960 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003961 long lrc;
3962 struct statsContext context;
3963 hdd_context_t *pHddCtx = NULL;
3964
3965 if (NULL == pAdapter)
3966 {
3967 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3968 return VOS_STATUS_E_FAULT;
3969 }
3970
3971 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3972 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3973
3974 /* we are connected prepare our callback context */
3975 init_completion(&context.completion);
3976 context.pAdapter = pAdapter;
3977 context.magic = STATS_CONTEXT_MAGIC;
3978
3979 /* query tsm stats */
3980 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3981 pHddStaCtx->conn_info.staId[ 0 ],
3982 pHddStaCtx->conn_info.bssId,
3983 &context, pHddCtx->pvosContext, tid);
3984
3985 if (eHAL_STATUS_SUCCESS != hstatus)
3986 {
Jeff Johnson72a40512013-12-19 10:14:15 -08003987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
3988 __func__);
3989 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003990 }
3991 else
3992 {
3993 /* request was sent -- wait for the response */
3994 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3995 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003996 if (lrc <= 0)
3997 {
3998 hddLog(VOS_TRACE_LEVEL_ERROR,
3999 "%s: SME %s while retrieving statistics",
4000 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004001 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004002 }
4003 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004004
Jeff Johnson72a40512013-12-19 10:14:15 -08004005 /* either we never sent a request, we sent a request and received a
4006 response or we sent a request and timed out. if we never sent a
4007 request or if we sent a request and got a response, we want to
4008 clear the magic out of paranoia. if we timed out there is a
4009 race condition such that the callback function could be
4010 executing at the same time we are. of primary concern is if the
4011 callback function had already verified the "magic" but had not
4012 yet set the completion variable when a timeout occurred. we
4013 serialize these activities by invalidating the magic while
4014 holding a shared spinlock which will cause us to block if the
4015 callback is currently executing */
4016 spin_lock(&hdd_context_lock);
4017 context.magic = 0;
4018 spin_unlock(&hdd_context_lock);
4019
4020 if (VOS_STATUS_SUCCESS == vstatus)
4021 {
4022 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4023 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4024 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4025 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4026 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4027 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4028 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4029 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4030 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4031 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4032 }
4033 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004034}
4035#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4036
Srinivas Girigowdade697412013-02-14 16:31:48 -08004037#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4038void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4039{
4040 eCsrBand band = -1;
4041 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4042 switch (band)
4043 {
4044 case eCSR_BAND_ALL:
4045 *pBand = WLAN_HDD_UI_BAND_AUTO;
4046 break;
4047
4048 case eCSR_BAND_24:
4049 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4050 break;
4051
4052 case eCSR_BAND_5G:
4053 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4054 break;
4055
4056 default:
4057 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4058 *pBand = -1;
4059 break;
4060 }
4061}
4062
4063/**---------------------------------------------------------------------------
4064
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004065 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4066
4067 This function parses the send action frame data passed in the format
4068 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4069
Srinivas Girigowda56076852013-08-20 14:00:50 -07004070 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004071 \param - pTargetApBssid Pointer to target Ap bssid
4072 \param - pChannel Pointer to the Target AP channel
4073 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4074 \param - pBuf Pointer to data
4075 \param - pBufLen Pointer to data length
4076
4077 \return - 0 for success non-zero for failure
4078
4079 --------------------------------------------------------------------------*/
4080VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4081 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4082{
4083 tANI_U8 *inPtr = pValue;
4084 tANI_U8 *dataEnd;
4085 int tempInt;
4086 int j = 0;
4087 int i = 0;
4088 int v = 0;
4089 tANI_U8 tempBuf[32];
4090 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004091 /* 12 hexa decimal digits, 5 ':' and '\0' */
4092 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004093
4094 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4095 /*no argument after the command*/
4096 if (NULL == inPtr)
4097 {
4098 return -EINVAL;
4099 }
4100
4101 /*no space after the command*/
4102 else if (SPACE_ASCII_VALUE != *inPtr)
4103 {
4104 return -EINVAL;
4105 }
4106
4107 /*removing empty spaces*/
4108 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4109
4110 /*no argument followed by spaces*/
4111 if ('\0' == *inPtr)
4112 {
4113 return -EINVAL;
4114 }
4115
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004116 v = sscanf(inPtr, "%17s", macAddress);
4117 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004118 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4120 "Invalid MAC address or All hex inputs are not read (%d)", v);
4121 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004122 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004123
4124 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4125 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4126 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4127 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4128 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4129 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004130
4131 /* point to the next argument */
4132 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4133 /*no argument after the command*/
4134 if (NULL == inPtr) return -EINVAL;
4135
4136 /*removing empty spaces*/
4137 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4138
4139 /*no argument followed by spaces*/
4140 if ('\0' == *inPtr)
4141 {
4142 return -EINVAL;
4143 }
4144
4145 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004146 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004147 if (1 != v) return -EINVAL;
4148
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004149 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304150 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4151 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004152
4153 *pChannel = tempInt;
4154
4155 /* point to the next argument */
4156 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4157 /*no argument after the command*/
4158 if (NULL == inPtr) return -EINVAL;
4159 /*removing empty spaces*/
4160 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4161
4162 /*no argument followed by spaces*/
4163 if ('\0' == *inPtr)
4164 {
4165 return -EINVAL;
4166 }
4167
4168 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004169 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004170 if (1 != v) return -EINVAL;
4171
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004172 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004173 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004174
4175 *pDwellTime = tempInt;
4176
4177 /* point to the next argument */
4178 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4179 /*no argument after the command*/
4180 if (NULL == inPtr) return -EINVAL;
4181 /*removing empty spaces*/
4182 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4183
4184 /*no argument followed by spaces*/
4185 if ('\0' == *inPtr)
4186 {
4187 return -EINVAL;
4188 }
4189
4190 /* find the length of data */
4191 dataEnd = inPtr;
4192 while(('\0' != *dataEnd) )
4193 {
4194 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004195 }
Kiet Lambe150c22013-11-21 16:30:32 +05304196 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004197 if ( *pBufLen <= 0) return -EINVAL;
4198
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004199 /* Allocate the number of bytes based on the number of input characters
4200 whether it is even or odd.
4201 if the number of input characters are even, then we need N/2 byte.
4202 if the number of input characters are odd, then we need do (N+1)/2 to
4203 compensate rounding off.
4204 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4205 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4206 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004207 if (NULL == *pBuf)
4208 {
4209 hddLog(VOS_TRACE_LEVEL_FATAL,
4210 "%s: vos_mem_alloc failed ", __func__);
4211 return -EINVAL;
4212 }
4213
4214 /* the buffer received from the upper layer is character buffer,
4215 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4216 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4217 and f0 in 3rd location */
4218 for (i = 0, j = 0; j < *pBufLen; j += 2)
4219 {
Kiet Lambe150c22013-11-21 16:30:32 +05304220 if( j+1 == *pBufLen)
4221 {
4222 tempByte = hdd_parse_hex(inPtr[j]);
4223 }
4224 else
4225 {
4226 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4227 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004228 (*pBuf)[i++] = tempByte;
4229 }
4230 *pBufLen = i;
4231 return VOS_STATUS_SUCCESS;
4232}
4233
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004234/**---------------------------------------------------------------------------
4235
Srinivas Girigowdade697412013-02-14 16:31:48 -08004236 \brief hdd_parse_channellist() - HDD Parse channel list
4237
4238 This function parses the channel list passed in the format
4239 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004240 if the Number of channels (N) does not match with the actual number of channels passed
4241 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4242 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4243 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4244 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004245
4246 \param - pValue Pointer to input channel list
4247 \param - ChannelList Pointer to local output array to record channel list
4248 \param - pNumChannels Pointer to number of roam scan channels
4249
4250 \return - 0 for success non-zero for failure
4251
4252 --------------------------------------------------------------------------*/
4253VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4254{
4255 tANI_U8 *inPtr = pValue;
4256 int tempInt;
4257 int j = 0;
4258 int v = 0;
4259 char buf[32];
4260
4261 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4262 /*no argument after the command*/
4263 if (NULL == inPtr)
4264 {
4265 return -EINVAL;
4266 }
4267
4268 /*no space after the command*/
4269 else if (SPACE_ASCII_VALUE != *inPtr)
4270 {
4271 return -EINVAL;
4272 }
4273
4274 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004275 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004276
4277 /*no argument followed by spaces*/
4278 if ('\0' == *inPtr)
4279 {
4280 return -EINVAL;
4281 }
4282
4283 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004284 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004285 if (1 != v) return -EINVAL;
4286
Srinivas Girigowdade697412013-02-14 16:31:48 -08004287 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004288 if ((v < 0) ||
4289 (tempInt <= 0) ||
4290 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4291 {
4292 return -EINVAL;
4293 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004294
4295 *pNumChannels = tempInt;
4296
4297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4298 "Number of channels are: %d", *pNumChannels);
4299
4300 for (j = 0; j < (*pNumChannels); j++)
4301 {
4302 /*inPtr pointing to the beginning of first space after number of channels*/
4303 inPtr = strpbrk( inPtr, " " );
4304 /*no channel list after the number of channels argument*/
4305 if (NULL == inPtr)
4306 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004307 if (0 != j)
4308 {
4309 *pNumChannels = j;
4310 return VOS_STATUS_SUCCESS;
4311 }
4312 else
4313 {
4314 return -EINVAL;
4315 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004316 }
4317
4318 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004319 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004320
4321 /*no channel list after the number of channels argument and spaces*/
4322 if ( '\0' == *inPtr )
4323 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004324 if (0 != j)
4325 {
4326 *pNumChannels = j;
4327 return VOS_STATUS_SUCCESS;
4328 }
4329 else
4330 {
4331 return -EINVAL;
4332 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004333 }
4334
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004335 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004336 if (1 != v) return -EINVAL;
4337
Srinivas Girigowdade697412013-02-14 16:31:48 -08004338 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004339 if ((v < 0) ||
4340 (tempInt <= 0) ||
4341 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4342 {
4343 return -EINVAL;
4344 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004345 pChannelList[j] = tempInt;
4346
4347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4348 "Channel %d added to preferred channel list",
4349 pChannelList[j] );
4350 }
4351
Srinivas Girigowdade697412013-02-14 16:31:48 -08004352 return VOS_STATUS_SUCCESS;
4353}
4354
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004355
4356/**---------------------------------------------------------------------------
4357
4358 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4359
4360 This function parses the reasoc command data passed in the format
4361 REASSOC<space><bssid><space><channel>
4362
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004363 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004364 \param - pTargetApBssid Pointer to target Ap bssid
4365 \param - pChannel Pointer to the Target AP channel
4366
4367 \return - 0 for success non-zero for failure
4368
4369 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004370VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4371 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004372{
4373 tANI_U8 *inPtr = pValue;
4374 int tempInt;
4375 int v = 0;
4376 tANI_U8 tempBuf[32];
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004377 /* 12 hexa decimal digits, 5 ':' and '\0' */
4378 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004379
4380 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4381 /*no argument after the command*/
4382 if (NULL == inPtr)
4383 {
4384 return -EINVAL;
4385 }
4386
4387 /*no space after the command*/
4388 else if (SPACE_ASCII_VALUE != *inPtr)
4389 {
4390 return -EINVAL;
4391 }
4392
4393 /*removing empty spaces*/
4394 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4395
4396 /*no argument followed by spaces*/
4397 if ('\0' == *inPtr)
4398 {
4399 return -EINVAL;
4400 }
4401
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004402 v = sscanf(inPtr, "%17s", macAddress);
4403 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004404 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4406 "Invalid MAC address or All hex inputs are not read (%d)", v);
4407 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004408 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004409
4410 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4411 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4412 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4413 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4414 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4415 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004416
4417 /* point to the next argument */
4418 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4419 /*no argument after the command*/
4420 if (NULL == inPtr) return -EINVAL;
4421
4422 /*removing empty spaces*/
4423 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4424
4425 /*no argument followed by spaces*/
4426 if ('\0' == *inPtr)
4427 {
4428 return -EINVAL;
4429 }
4430
4431 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004432 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004433 if (1 != v) return -EINVAL;
4434
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004435 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004436 if ((v < 0) ||
4437 (tempInt <= 0) ||
4438 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4439 {
4440 return -EINVAL;
4441 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004442
4443 *pChannel = tempInt;
4444 return VOS_STATUS_SUCCESS;
4445}
4446
4447#endif
4448
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004449#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4450/**---------------------------------------------------------------------------
4451
4452 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4453
4454 This function parses the SETCCKM IE command
4455 SETCCKMIE<space><ie data>
4456
4457 \param - pValue Pointer to input data
4458 \param - pCckmIe Pointer to output cckm Ie
4459 \param - pCckmIeLen Pointer to output cckm ie length
4460
4461 \return - 0 for success non-zero for failure
4462
4463 --------------------------------------------------------------------------*/
4464VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4465 tANI_U8 *pCckmIeLen)
4466{
4467 tANI_U8 *inPtr = pValue;
4468 tANI_U8 *dataEnd;
4469 int j = 0;
4470 int i = 0;
4471 tANI_U8 tempByte = 0;
4472
4473 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4474 /*no argument after the command*/
4475 if (NULL == inPtr)
4476 {
4477 return -EINVAL;
4478 }
4479
4480 /*no space after the command*/
4481 else if (SPACE_ASCII_VALUE != *inPtr)
4482 {
4483 return -EINVAL;
4484 }
4485
4486 /*removing empty spaces*/
4487 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4488
4489 /*no argument followed by spaces*/
4490 if ('\0' == *inPtr)
4491 {
4492 return -EINVAL;
4493 }
4494
4495 /* find the length of data */
4496 dataEnd = inPtr;
4497 while(('\0' != *dataEnd) )
4498 {
4499 dataEnd++;
4500 ++(*pCckmIeLen);
4501 }
4502 if ( *pCckmIeLen <= 0) return -EINVAL;
4503
4504 /* Allocate the number of bytes based on the number of input characters
4505 whether it is even or odd.
4506 if the number of input characters are even, then we need N/2 byte.
4507 if the number of input characters are odd, then we need do (N+1)/2 to
4508 compensate rounding off.
4509 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4510 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4511 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4512 if (NULL == *pCckmIe)
4513 {
4514 hddLog(VOS_TRACE_LEVEL_FATAL,
4515 "%s: vos_mem_alloc failed ", __func__);
4516 return -EINVAL;
4517 }
4518 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4519 /* the buffer received from the upper layer is character buffer,
4520 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4521 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4522 and f0 in 3rd location */
4523 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4524 {
4525 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4526 (*pCckmIe)[i++] = tempByte;
4527 }
4528 *pCckmIeLen = i;
4529
4530 return VOS_STATUS_SUCCESS;
4531}
4532#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4533
Jeff Johnson295189b2012-06-20 16:38:30 -07004534/**---------------------------------------------------------------------------
4535
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004536 \brief hdd_is_valid_mac_address() - Validate MAC address
4537
4538 This function validates whether the given MAC address is valid or not
4539 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4540 where X is the hexa decimal digit character and separated by ':'
4541 This algorithm works even if MAC address is not separated by ':'
4542
4543 This code checks given input string mac contains exactly 12 hexadecimal digits.
4544 and a separator colon : appears in the input string only after
4545 an even number of hex digits.
4546
4547 \param - pMacAddr pointer to the input MAC address
4548 \return - 1 for valid and 0 for invalid
4549
4550 --------------------------------------------------------------------------*/
4551
4552v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4553{
4554 int xdigit = 0;
4555 int separator = 0;
4556 while (*pMacAddr)
4557 {
4558 if (isxdigit(*pMacAddr))
4559 {
4560 xdigit++;
4561 }
4562 else if (':' == *pMacAddr)
4563 {
4564 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4565 break;
4566
4567 ++separator;
4568 }
4569 else
4570 {
4571 separator = -1;
4572 /* Invalid MAC found */
4573 return 0;
4574 }
4575 ++pMacAddr;
4576 }
4577 return (xdigit == 12 && (separator == 5 || separator == 0));
4578}
4579
4580/**---------------------------------------------------------------------------
4581
Jeff Johnson295189b2012-06-20 16:38:30 -07004582 \brief hdd_open() - HDD Open function
4583
4584 This is called in response to ifconfig up
4585
4586 \param - dev Pointer to net_device structure
4587
4588 \return - 0 for success non-zero for failure
4589
4590 --------------------------------------------------------------------------*/
4591int hdd_open (struct net_device *dev)
4592{
4593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4594 hdd_context_t *pHddCtx;
4595 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4596 VOS_STATUS status;
4597 v_BOOL_t in_standby = TRUE;
4598
4599 if (NULL == pAdapter)
4600 {
4601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004602 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004603 return -ENODEV;
4604 }
4605
4606 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4607 if (NULL == pHddCtx)
4608 {
4609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004610 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004611 return -ENODEV;
4612 }
4613
4614 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4615 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4616 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004617 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4618 {
4619 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304620 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004621 in_standby = FALSE;
4622 break;
4623 }
4624 else
4625 {
4626 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4627 pAdapterNode = pNext;
4628 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004629 }
4630
4631 if (TRUE == in_standby)
4632 {
4633 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4634 {
4635 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4636 "wlan out of power save", __func__);
4637 return -EINVAL;
4638 }
4639 }
4640
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004641 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4643 {
4644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004645 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 /* Enable TX queues only when we are connected */
4647 netif_tx_start_all_queues(dev);
4648 }
4649
4650 return 0;
4651}
4652
4653int hdd_mon_open (struct net_device *dev)
4654{
4655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4656
4657 if(pAdapter == NULL) {
4658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004659 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004660 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004661 }
4662
4663 netif_start_queue(dev);
4664
4665 return 0;
4666}
4667/**---------------------------------------------------------------------------
4668
4669 \brief hdd_stop() - HDD stop function
4670
4671 This is called in response to ifconfig down
4672
4673 \param - dev Pointer to net_device structure
4674
4675 \return - 0 for success non-zero for failure
4676
4677 --------------------------------------------------------------------------*/
4678
4679int hdd_stop (struct net_device *dev)
4680{
4681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4682 hdd_context_t *pHddCtx;
4683 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4684 VOS_STATUS status;
4685 v_BOOL_t enter_standby = TRUE;
4686
4687 ENTER();
4688
4689 if (NULL == pAdapter)
4690 {
4691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004692 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 return -ENODEV;
4694 }
4695
4696 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4697 if (NULL == pHddCtx)
4698 {
4699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004700 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004701 return -ENODEV;
4702 }
4703
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004704 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004705 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4706 netif_tx_disable(pAdapter->dev);
4707 netif_carrier_off(pAdapter->dev);
4708
4709
4710 /* SoftAP ifaces should never go in power save mode
4711 making sure same here. */
4712 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4713 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004714 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004715 )
4716 {
4717 /* SoftAP mode, so return from here */
4718 EXIT();
4719 return 0;
4720 }
4721
4722 /* Find if any iface is up then
4723 if any iface is up then can't put device to sleep/ power save mode. */
4724 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4725 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4726 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004727 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4728 {
4729 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304730 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004731 enter_standby = FALSE;
4732 break;
4733 }
4734 else
4735 {
4736 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4737 pAdapterNode = pNext;
4738 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 }
4740
4741 if (TRUE == enter_standby)
4742 {
4743 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4744 "entering standby", __func__);
4745 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4746 {
4747 /*log and return success*/
4748 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4749 "wlan in power save", __func__);
4750 }
4751 }
4752
4753 EXIT();
4754 return 0;
4755}
4756
4757/**---------------------------------------------------------------------------
4758
4759 \brief hdd_uninit() - HDD uninit function
4760
4761 This is called during the netdev unregister to uninitialize all data
4762associated with the device
4763
4764 \param - dev Pointer to net_device structure
4765
4766 \return - void
4767
4768 --------------------------------------------------------------------------*/
4769static void hdd_uninit (struct net_device *dev)
4770{
4771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4772
4773 ENTER();
4774
4775 do
4776 {
4777 if (NULL == pAdapter)
4778 {
4779 hddLog(VOS_TRACE_LEVEL_FATAL,
4780 "%s: NULL pAdapter", __func__);
4781 break;
4782 }
4783
4784 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4785 {
4786 hddLog(VOS_TRACE_LEVEL_FATAL,
4787 "%s: Invalid magic", __func__);
4788 break;
4789 }
4790
4791 if (NULL == pAdapter->pHddCtx)
4792 {
4793 hddLog(VOS_TRACE_LEVEL_FATAL,
4794 "%s: NULL pHddCtx", __func__);
4795 break;
4796 }
4797
4798 if (dev != pAdapter->dev)
4799 {
4800 hddLog(VOS_TRACE_LEVEL_FATAL,
4801 "%s: Invalid device reference", __func__);
4802 /* we haven't validated all cases so let this go for now */
4803 }
4804
4805 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4806
4807 /* after uninit our adapter structure will no longer be valid */
4808 pAdapter->dev = NULL;
4809 pAdapter->magic = 0;
4810 } while (0);
4811
4812 EXIT();
4813}
4814
4815/**---------------------------------------------------------------------------
4816
4817 \brief hdd_release_firmware() -
4818
4819 This function calls the release firmware API to free the firmware buffer.
4820
4821 \param - pFileName Pointer to the File Name.
4822 pCtx - Pointer to the adapter .
4823
4824
4825 \return - 0 for success, non zero for failure
4826
4827 --------------------------------------------------------------------------*/
4828
4829VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4830{
4831 VOS_STATUS status = VOS_STATUS_SUCCESS;
4832 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4833 ENTER();
4834
4835
4836 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4837
4838 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4839
4840 if(pHddCtx->fw) {
4841 release_firmware(pHddCtx->fw);
4842 pHddCtx->fw = NULL;
4843 }
4844 else
4845 status = VOS_STATUS_E_FAILURE;
4846 }
4847 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4848 if(pHddCtx->nv) {
4849 release_firmware(pHddCtx->nv);
4850 pHddCtx->nv = NULL;
4851 }
4852 else
4853 status = VOS_STATUS_E_FAILURE;
4854
4855 }
4856
4857 EXIT();
4858 return status;
4859}
4860
4861/**---------------------------------------------------------------------------
4862
4863 \brief hdd_request_firmware() -
4864
4865 This function reads the firmware file using the request firmware
4866 API and returns the the firmware data and the firmware file size.
4867
4868 \param - pfileName - Pointer to the file name.
4869 - pCtx - Pointer to the adapter .
4870 - ppfw_data - Pointer to the pointer of the firmware data.
4871 - pSize - Pointer to the file size.
4872
4873 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4874
4875 --------------------------------------------------------------------------*/
4876
4877
4878VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4879{
4880 int status;
4881 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4882 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4883 ENTER();
4884
4885 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4886
4887 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4888
4889 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4890 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4891 __func__, pfileName);
4892 retval = VOS_STATUS_E_FAILURE;
4893 }
4894
4895 else {
4896 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4897 *pSize = pHddCtx->fw->size;
4898 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4899 __func__, *pSize);
4900 }
4901 }
4902 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4903
4904 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4905
4906 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4907 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4908 __func__, pfileName);
4909 retval = VOS_STATUS_E_FAILURE;
4910 }
4911
4912 else {
4913 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4914 *pSize = pHddCtx->nv->size;
4915 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4916 __func__, *pSize);
4917 }
4918 }
4919
4920 EXIT();
4921 return retval;
4922}
4923/**---------------------------------------------------------------------------
4924 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4925
4926 This is the function invoked by SME to inform the result of a full power
4927 request issued by HDD
4928
4929 \param - callbackcontext - Pointer to cookie
4930 status - result of request
4931
4932 \return - None
4933
4934--------------------------------------------------------------------------*/
4935void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4936{
4937 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4938
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004939 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004940 if(&pHddCtx->full_pwr_comp_var)
4941 {
4942 complete(&pHddCtx->full_pwr_comp_var);
4943 }
4944}
4945
4946/**---------------------------------------------------------------------------
4947
4948 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4949
4950 This is the function invoked by SME to inform the result of BMPS
4951 request issued by HDD
4952
4953 \param - callbackcontext - Pointer to cookie
4954 status - result of request
4955
4956 \return - None
4957
4958--------------------------------------------------------------------------*/
4959void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4960{
4961
4962 struct completion *completion_var = (struct completion*) callbackContext;
4963
Arif Hussain6d2a3322013-11-17 19:50:10 -08004964 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004965 if(completion_var != NULL)
4966 {
4967 complete(completion_var);
4968 }
4969}
4970
4971/**---------------------------------------------------------------------------
4972
4973 \brief hdd_get_cfg_file_size() -
4974
4975 This function reads the configuration file using the request firmware
4976 API and returns the configuration file size.
4977
4978 \param - pCtx - Pointer to the adapter .
4979 - pFileName - Pointer to the file name.
4980 - pBufSize - Pointer to the buffer size.
4981
4982 \return - 0 for success, non zero for failure
4983
4984 --------------------------------------------------------------------------*/
4985
4986VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4987{
4988 int status;
4989 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4990
4991 ENTER();
4992
4993 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4994
4995 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4996 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4997 status = VOS_STATUS_E_FAILURE;
4998 }
4999 else {
5000 *pBufSize = pHddCtx->fw->size;
5001 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5002 release_firmware(pHddCtx->fw);
5003 pHddCtx->fw = NULL;
5004 }
5005
5006 EXIT();
5007 return VOS_STATUS_SUCCESS;
5008}
5009
5010/**---------------------------------------------------------------------------
5011
5012 \brief hdd_read_cfg_file() -
5013
5014 This function reads the configuration file using the request firmware
5015 API and returns the cfg data and the buffer size of the configuration file.
5016
5017 \param - pCtx - Pointer to the adapter .
5018 - pFileName - Pointer to the file name.
5019 - pBuffer - Pointer to the data buffer.
5020 - pBufSize - Pointer to the buffer size.
5021
5022 \return - 0 for success, non zero for failure
5023
5024 --------------------------------------------------------------------------*/
5025
5026VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5027 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5028{
5029 int status;
5030 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5031
5032 ENTER();
5033
5034 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5035
5036 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5037 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5038 return VOS_STATUS_E_FAILURE;
5039 }
5040 else {
5041 if(*pBufSize != pHddCtx->fw->size) {
5042 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5043 "file size", __func__);
5044 release_firmware(pHddCtx->fw);
5045 pHddCtx->fw = NULL;
5046 return VOS_STATUS_E_FAILURE;
5047 }
5048 else {
5049 if(pBuffer) {
5050 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5051 }
5052 release_firmware(pHddCtx->fw);
5053 pHddCtx->fw = NULL;
5054 }
5055 }
5056
5057 EXIT();
5058
5059 return VOS_STATUS_SUCCESS;
5060}
5061
5062/**---------------------------------------------------------------------------
5063
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 \brief hdd_set_mac_address() -
5065
5066 This function sets the user specified mac address using
5067 the command ifconfig wlanX hw ether <mac adress>.
5068
5069 \param - dev - Pointer to the net device.
5070 - addr - Pointer to the sockaddr.
5071 \return - 0 for success, non zero for failure
5072
5073 --------------------------------------------------------------------------*/
5074
5075static int hdd_set_mac_address(struct net_device *dev, void *addr)
5076{
5077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5078 struct sockaddr *psta_mac_addr = addr;
5079 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5080
5081 ENTER();
5082
5083 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5084
5085#ifdef HDD_SESSIONIZE
5086 // set the MAC address though the STA ID CFG.
5087 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5088 (v_U8_t *)&pAdapter->macAddressCurrent,
5089 sizeof( pAdapter->macAddressCurrent ),
5090 hdd_set_mac_addr_cb, VOS_FALSE );
5091#endif
5092
5093 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5094
5095 EXIT();
5096 return halStatus;
5097}
5098
5099tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5100{
5101 int i;
5102 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5103 {
5104 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5105 break;
5106 }
5107
5108 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5109 return NULL;
5110
5111 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5112 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5113}
5114
5115void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5116{
5117 int i;
5118 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5119 {
5120 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5121 {
5122 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5123 break;
5124 }
5125 }
5126 return;
5127}
5128
5129#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5130 static struct net_device_ops wlan_drv_ops = {
5131 .ndo_open = hdd_open,
5132 .ndo_stop = hdd_stop,
5133 .ndo_uninit = hdd_uninit,
5134 .ndo_start_xmit = hdd_hard_start_xmit,
5135 .ndo_tx_timeout = hdd_tx_timeout,
5136 .ndo_get_stats = hdd_stats,
5137 .ndo_do_ioctl = hdd_ioctl,
5138 .ndo_set_mac_address = hdd_set_mac_address,
5139 .ndo_select_queue = hdd_select_queue,
5140#ifdef WLAN_FEATURE_PACKET_FILTERING
5141#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5142 .ndo_set_rx_mode = hdd_set_multicast_list,
5143#else
5144 .ndo_set_multicast_list = hdd_set_multicast_list,
5145#endif //LINUX_VERSION_CODE
5146#endif
5147 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005148 static struct net_device_ops wlan_mon_drv_ops = {
5149 .ndo_open = hdd_mon_open,
5150 .ndo_stop = hdd_stop,
5151 .ndo_uninit = hdd_uninit,
5152 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5153 .ndo_tx_timeout = hdd_tx_timeout,
5154 .ndo_get_stats = hdd_stats,
5155 .ndo_do_ioctl = hdd_ioctl,
5156 .ndo_set_mac_address = hdd_set_mac_address,
5157 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005158
5159#endif
5160
5161void hdd_set_station_ops( struct net_device *pWlanDev )
5162{
5163#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005164 pWlanDev->netdev_ops = &wlan_drv_ops;
5165#else
5166 pWlanDev->open = hdd_open;
5167 pWlanDev->stop = hdd_stop;
5168 pWlanDev->uninit = hdd_uninit;
5169 pWlanDev->hard_start_xmit = NULL;
5170 pWlanDev->tx_timeout = hdd_tx_timeout;
5171 pWlanDev->get_stats = hdd_stats;
5172 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005173 pWlanDev->set_mac_address = hdd_set_mac_address;
5174#endif
5175}
5176
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005177static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005178{
5179 struct net_device *pWlanDev = NULL;
5180 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 /*
5182 * cfg80211 initialization and registration....
5183 */
5184 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5185
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 if(pWlanDev != NULL)
5187 {
5188
5189 //Save the pointer to the net_device in the HDD adapter
5190 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5191
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5193
5194 pAdapter->dev = pWlanDev;
5195 pAdapter->pHddCtx = pHddCtx;
5196 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5197
5198 init_completion(&pAdapter->session_open_comp_var);
5199 init_completion(&pAdapter->session_close_comp_var);
5200 init_completion(&pAdapter->disconnect_comp_var);
5201 init_completion(&pAdapter->linkup_event_var);
5202 init_completion(&pAdapter->cancel_rem_on_chan_var);
5203 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005204#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5205 init_completion(&pAdapter->offchannel_tx_event);
5206#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005207 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005208#ifdef FEATURE_WLAN_TDLS
5209 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005210 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005211 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305212 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005213#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 init_completion(&pHddCtx->mc_sus_event_var);
5215 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305216 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005217 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005218 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005219
Rajeev79dbe4c2013-10-05 11:03:42 +05305220#ifdef FEATURE_WLAN_BATCH_SCAN
5221 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5222 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5223 pAdapter->pBatchScanRsp = NULL;
5224 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005225 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005226 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305227 mutex_init(&pAdapter->hdd_batch_scan_lock);
5228#endif
5229
Jeff Johnson295189b2012-06-20 16:38:30 -07005230 pAdapter->isLinkUpSvcNeeded = FALSE;
5231 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5232 //Init the net_device structure
5233 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5234
5235 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5236 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5237 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5238 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5239
5240 hdd_set_station_ops( pAdapter->dev );
5241
5242 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5244 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5245 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 /* set pWlanDev's parent to underlying device */
5247 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5248 }
5249
5250 return pAdapter;
5251}
5252
5253VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5254{
5255 struct net_device *pWlanDev = pAdapter->dev;
5256 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5257 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5258 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5259
5260 if( rtnl_lock_held )
5261 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005262 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005263 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5264 {
5265 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5266 return VOS_STATUS_E_FAILURE;
5267 }
5268 }
5269 if (register_netdevice(pWlanDev))
5270 {
5271 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5272 return VOS_STATUS_E_FAILURE;
5273 }
5274 }
5275 else
5276 {
5277 if(register_netdev(pWlanDev))
5278 {
5279 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5280 return VOS_STATUS_E_FAILURE;
5281 }
5282 }
5283 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5284
5285 return VOS_STATUS_SUCCESS;
5286}
5287
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005288static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005289{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005290 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005291
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005292 if (NULL == pAdapter)
5293 {
5294 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5295 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005296 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005297
5298 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5301 return eHAL_STATUS_NOT_INITIALIZED;
5302 }
5303
5304 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5305
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005306#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005307 /* need to make sure all of our scheduled work has completed.
5308 * This callback is called from MC thread context, so it is safe to
5309 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005310 *
5311 * Even though this is called from MC thread context, if there is a faulty
5312 * work item in the system, that can hang this call forever. So flushing
5313 * this global work queue is not safe; and now we make sure that
5314 * individual work queues are stopped correctly. But the cancel work queue
5315 * is a GPL only API, so the proprietary version of the driver would still
5316 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005317 */
5318 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005319#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005320
5321 /* We can be blocked while waiting for scheduled work to be
5322 * flushed, and the adapter structure can potentially be freed, in
5323 * which case the magic will have been reset. So make sure the
5324 * magic is still good, and hence the adapter structure is still
5325 * valid, before signaling completion */
5326 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5327 {
5328 complete(&pAdapter->session_close_comp_var);
5329 }
5330
Jeff Johnson295189b2012-06-20 16:38:30 -07005331 return eHAL_STATUS_SUCCESS;
5332}
5333
5334VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5335{
5336 struct net_device *pWlanDev = pAdapter->dev;
5337 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5338 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5339 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5340 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5341 int rc = 0;
5342
5343 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005344 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005345 //Open a SME session for future operation
5346 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005347 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5349 {
5350 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005351 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005352 halStatus, halStatus );
5353 status = VOS_STATUS_E_FAILURE;
5354 goto error_sme_open;
5355 }
5356
5357 //Block on a completion variable. Can't wait forever though.
5358 rc = wait_for_completion_interruptible_timeout(
5359 &pAdapter->session_open_comp_var,
5360 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5361 if (!rc)
5362 {
5363 hddLog(VOS_TRACE_LEVEL_FATAL,
5364 "Session is not opened within timeout period code %08d", rc );
5365 status = VOS_STATUS_E_FAILURE;
5366 goto error_sme_open;
5367 }
5368
5369 // Register wireless extensions
5370 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5371 {
5372 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005373 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 halStatus, halStatus );
5375 status = VOS_STATUS_E_FAILURE;
5376 goto error_register_wext;
5377 }
5378 //Safe to register the hard_start_xmit function again
5379#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5380 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5381#else
5382 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5383#endif
5384
5385 //Set the Connection State to Not Connected
5386 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5387
5388 //Set the default operation channel
5389 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5390
5391 /* Make the default Auth Type as OPEN*/
5392 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5393
5394 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5395 {
5396 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005397 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005398 status, status );
5399 goto error_init_txrx;
5400 }
5401
5402 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5403
5404 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5405 {
5406 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005407 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 status, status );
5409 goto error_wmm_init;
5410 }
5411
5412 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5413
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005414#ifdef FEATURE_WLAN_TDLS
5415 if(0 != wlan_hdd_tdls_init(pAdapter))
5416 {
5417 status = VOS_STATUS_E_FAILURE;
5418 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5419 goto error_tdls_init;
5420 }
5421 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5422#endif
5423
Jeff Johnson295189b2012-06-20 16:38:30 -07005424 return VOS_STATUS_SUCCESS;
5425
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005426#ifdef FEATURE_WLAN_TDLS
5427error_tdls_init:
5428 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5429 hdd_wmm_adapter_close(pAdapter);
5430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005431error_wmm_init:
5432 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5433 hdd_deinit_tx_rx(pAdapter);
5434error_init_txrx:
5435 hdd_UnregisterWext(pWlanDev);
5436error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005437 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 {
5439 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005440 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005441 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005442 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 {
5444 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005445 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005447 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 }
5449}
5450error_sme_open:
5451 return status;
5452}
5453
Jeff Johnson295189b2012-06-20 16:38:30 -07005454void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5455{
5456 hdd_cfg80211_state_t *cfgState;
5457
5458 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5459
5460 if( NULL != cfgState->buf )
5461 {
5462 int rc;
5463 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5464 rc = wait_for_completion_interruptible_timeout(
5465 &pAdapter->tx_action_cnf_event,
5466 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5467 if(!rc)
5468 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005470 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 }
5472 }
5473 return;
5474}
Jeff Johnson295189b2012-06-20 16:38:30 -07005475
5476void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5477{
5478 ENTER();
5479 switch ( pAdapter->device_mode )
5480 {
5481 case WLAN_HDD_INFRA_STATION:
5482 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005483 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 {
5485 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5486 {
5487 hdd_deinit_tx_rx( pAdapter );
5488 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5489 }
5490
5491 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5492 {
5493 hdd_wmm_adapter_close( pAdapter );
5494 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5495 }
5496
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005498#ifdef FEATURE_WLAN_TDLS
5499 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5500 {
5501 wlan_hdd_tdls_exit(pAdapter);
5502 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5503 }
5504#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005505
5506 break;
5507 }
5508
5509 case WLAN_HDD_SOFTAP:
5510 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305512
5513 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5514 {
5515 hdd_wmm_adapter_close( pAdapter );
5516 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5517 }
5518
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005520
5521 hdd_unregister_hostapd(pAdapter);
5522 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 break;
5525 }
5526
5527 case WLAN_HDD_MONITOR:
5528 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5531 {
5532 hdd_deinit_tx_rx( pAdapter );
5533 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5534 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005535 if(NULL != pAdapterforTx)
5536 {
5537 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5538 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 break;
5540 }
5541
5542
5543 default:
5544 break;
5545 }
5546
5547 EXIT();
5548}
5549
5550void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5551{
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305552 struct net_device *pWlanDev;
5553
5554 ENTER();
5555 if (NULL == pAdapter)
5556 {
5557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5558 "%s: HDD adapter is Null", __func__);
5559 return;
5560 }
5561
5562 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005563
Rajeev79dbe4c2013-10-05 11:03:42 +05305564#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305565 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5566 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005567 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305568 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5569 )
5570 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005571 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305572 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005573 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5574 {
5575 hdd_deinit_batch_scan(pAdapter);
5576 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305577 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005578 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305579#endif
5580
Jeff Johnson295189b2012-06-20 16:38:30 -07005581 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5582 if( rtnl_held )
5583 {
5584 unregister_netdevice(pWlanDev);
5585 }
5586 else
5587 {
5588 unregister_netdev(pWlanDev);
5589 }
5590 // note that the pAdapter is no longer valid at this point
5591 // since the memory has been reclaimed
5592 }
5593
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305594 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005595}
5596
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005597void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5598{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305599 VOS_STATUS status;
5600 hdd_adapter_t *pAdapter = NULL;
5601 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005602
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305603 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005604
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305605 /*loop through all adapters.*/
5606 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005607 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305608 pAdapter = pAdapterNode->pAdapter;
5609 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5610 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005611
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305612 { // we skip this registration for modes other than STA and P2P client modes.
5613 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5614 pAdapterNode = pNext;
5615 continue;
5616 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005617
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305618 //Apply Dynamic DTIM For P2P
5619 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5620 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5621 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5622 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5623 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5624 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5625 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5626 (eConnectionState_Associated ==
5627 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5628 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5629 {
5630 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005631
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305632 powerRequest.uIgnoreDTIM = 1;
5633 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5634
5635 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5636 {
5637 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5638 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5639 }
5640 else
5641 {
5642 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5643 }
5644
5645 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5646 * specified during Enter/Exit BMPS when LCD off*/
5647 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5648 NULL, eANI_BOOLEAN_FALSE);
5649 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5650 NULL, eANI_BOOLEAN_FALSE);
5651
5652 /* switch to the DTIM specified in cfg.ini */
5653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5654 "Switch to DTIM %d", powerRequest.uListenInterval);
5655 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5656 break;
5657
5658 }
5659
5660 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5661 pAdapterNode = pNext;
5662 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005663}
5664
5665void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5666{
5667 /*Switch back to DTIM 1*/
5668 tSirSetPowerParamsReq powerRequest = { 0 };
5669
5670 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5671 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005672 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005673
5674 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5675 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5676 NULL, eANI_BOOLEAN_FALSE);
5677 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5678 NULL, eANI_BOOLEAN_FALSE);
5679
5680 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5681 "Switch to DTIM%d",powerRequest.uListenInterval);
5682 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5683
5684}
5685
Jeff Johnson295189b2012-06-20 16:38:30 -07005686VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5687{
5688 VOS_STATUS status = VOS_STATUS_SUCCESS;
5689
5690 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5691 {
5692 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5693 }
5694
5695 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5696 {
5697 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5698 }
5699
5700 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5701 {
5702 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5703 }
5704
5705 return status;
5706}
5707
5708VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5709{
5710 hdd_adapter_t *pAdapter = NULL;
5711 eHalStatus halStatus;
5712 VOS_STATUS status = VOS_STATUS_E_INVAL;
5713 v_BOOL_t disableBmps = FALSE;
5714 v_BOOL_t disableImps = FALSE;
5715
5716 switch(session_type)
5717 {
5718 case WLAN_HDD_INFRA_STATION:
5719 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005720 case WLAN_HDD_P2P_CLIENT:
5721 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 //Exit BMPS -> Is Sta/P2P Client is already connected
5723 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5724 if((NULL != pAdapter)&&
5725 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5726 {
5727 disableBmps = TRUE;
5728 }
5729
5730 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5731 if((NULL != pAdapter)&&
5732 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5733 {
5734 disableBmps = TRUE;
5735 }
5736
5737 //Exit both Bmps and Imps incase of Go/SAP Mode
5738 if((WLAN_HDD_SOFTAP == session_type) ||
5739 (WLAN_HDD_P2P_GO == session_type))
5740 {
5741 disableBmps = TRUE;
5742 disableImps = TRUE;
5743 }
5744
5745 if(TRUE == disableImps)
5746 {
5747 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5748 {
5749 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5750 }
5751 }
5752
5753 if(TRUE == disableBmps)
5754 {
5755 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5756 {
5757 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5758
5759 if(eHAL_STATUS_SUCCESS != halStatus)
5760 {
5761 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005762 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 VOS_ASSERT(0);
5764 return status;
5765 }
5766 }
5767
5768 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5769 {
5770 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5771
5772 if(eHAL_STATUS_SUCCESS != halStatus)
5773 {
5774 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005775 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 VOS_ASSERT(0);
5777 return status;
5778 }
5779 }
5780 }
5781
5782 if((TRUE == disableBmps) ||
5783 (TRUE == disableImps))
5784 {
5785 /* Now, get the chip into Full Power now */
5786 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5787 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5788 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5789
5790 if(halStatus != eHAL_STATUS_SUCCESS)
5791 {
5792 if(halStatus == eHAL_STATUS_PMC_PENDING)
5793 {
5794 //Block on a completion variable. Can't wait forever though
5795 wait_for_completion_interruptible_timeout(
5796 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5797 }
5798 else
5799 {
5800 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005801 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 VOS_ASSERT(0);
5803 return status;
5804 }
5805 }
5806
5807 status = VOS_STATUS_SUCCESS;
5808 }
5809
5810 break;
5811 }
5812 return status;
5813}
5814
5815hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005816 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 tANI_U8 rtnl_held )
5818{
5819 hdd_adapter_t *pAdapter = NULL;
5820 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5821 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5822 VOS_STATUS exitbmpsStatus;
5823
Arif Hussain6d2a3322013-11-17 19:50:10 -08005824 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005825
5826 //Disable BMPS incase of Concurrency
5827 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5828
5829 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5830 {
5831 //Fail to Exit BMPS
5832 VOS_ASSERT(0);
5833 return NULL;
5834 }
5835
5836 switch(session_type)
5837 {
5838 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005840 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005841 {
5842 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5843
5844 if( NULL == pAdapter )
5845 return NULL;
5846
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305847#ifdef FEATURE_WLAN_TDLS
5848 /* A Mutex Lock is introduced while changing/initializing the mode to
5849 * protect the concurrent access for the Adapters by TDLS module.
5850 */
5851 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5852 {
5853 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5854 "%s: unable to lock list", __func__);
5855 return NULL;
5856 }
5857#endif
5858
Jeff Johnsone7245742012-09-05 17:12:55 -07005859 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5860 NL80211_IFTYPE_P2P_CLIENT:
5861 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005862
Jeff Johnson295189b2012-06-20 16:38:30 -07005863 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305864#ifdef FEATURE_WLAN_TDLS
5865 mutex_unlock(&pHddCtx->tdls_lock);
5866#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305867
5868 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 if( VOS_STATUS_SUCCESS != status )
5870 goto err_free_netdev;
5871
5872 status = hdd_register_interface( pAdapter, rtnl_held );
5873 if( VOS_STATUS_SUCCESS != status )
5874 {
5875 hdd_deinit_adapter(pHddCtx, pAdapter);
5876 goto err_free_netdev;
5877 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305878
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305879 // Workqueue which gets scheduled in IPv4 notification callback.
5880 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5881
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305882#ifdef WLAN_NS_OFFLOAD
5883 // Workqueue which gets scheduled in IPv6 notification callback.
5884 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5885#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 //Stop the Interface TX queue.
5887 netif_tx_disable(pAdapter->dev);
5888 //netif_tx_disable(pWlanDev);
5889 netif_carrier_off(pAdapter->dev);
5890
5891 break;
5892 }
5893
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 case WLAN_HDD_SOFTAP:
5896 {
5897 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5898 if( NULL == pAdapter )
5899 return NULL;
5900
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5902 NL80211_IFTYPE_AP:
5903 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 pAdapter->device_mode = session_type;
5905
5906 status = hdd_init_ap_mode(pAdapter);
5907 if( VOS_STATUS_SUCCESS != status )
5908 goto err_free_netdev;
5909
5910 status = hdd_register_hostapd( pAdapter, rtnl_held );
5911 if( VOS_STATUS_SUCCESS != status )
5912 {
5913 hdd_deinit_adapter(pHddCtx, pAdapter);
5914 goto err_free_netdev;
5915 }
5916
5917 netif_tx_disable(pAdapter->dev);
5918 netif_carrier_off(pAdapter->dev);
5919
5920 hdd_set_conparam( 1 );
5921 break;
5922 }
5923 case WLAN_HDD_MONITOR:
5924 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5926 if( NULL == pAdapter )
5927 return NULL;
5928
5929 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5930 pAdapter->device_mode = session_type;
5931 status = hdd_register_interface( pAdapter, rtnl_held );
5932#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5933 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5934#else
5935 pAdapter->dev->open = hdd_mon_open;
5936 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5937#endif
5938 hdd_init_tx_rx( pAdapter );
5939 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5940 //Set adapter to be used for data tx. It will use either GO or softap.
5941 pAdapter->sessionCtx.monitor.pAdapterForTx =
5942 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5944 {
5945 pAdapter->sessionCtx.monitor.pAdapterForTx =
5946 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 /* This workqueue will be used to transmit management packet over
5949 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005950 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5951 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5952 return NULL;
5953 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005954
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5956 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005957 }
5958 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005959 case WLAN_HDD_FTM:
5960 {
5961 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5962
5963 if( NULL == pAdapter )
5964 return NULL;
5965 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5966 * message while loading driver in FTM mode. */
5967 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5968 pAdapter->device_mode = session_type;
5969 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305970
5971 hdd_init_tx_rx( pAdapter );
5972
5973 //Stop the Interface TX queue.
5974 netif_tx_disable(pAdapter->dev);
5975 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 }
5977 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 default:
5979 {
5980 VOS_ASSERT(0);
5981 return NULL;
5982 }
5983 }
5984
Jeff Johnson295189b2012-06-20 16:38:30 -07005985 if( VOS_STATUS_SUCCESS == status )
5986 {
5987 //Add it to the hdd's session list.
5988 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5989 if( NULL == pHddAdapterNode )
5990 {
5991 status = VOS_STATUS_E_NOMEM;
5992 }
5993 else
5994 {
5995 pHddAdapterNode->pAdapter = pAdapter;
5996 status = hdd_add_adapter_back ( pHddCtx,
5997 pHddAdapterNode );
5998 }
5999 }
6000
6001 if( VOS_STATUS_SUCCESS != status )
6002 {
6003 if( NULL != pAdapter )
6004 {
6005 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6006 pAdapter = NULL;
6007 }
6008 if( NULL != pHddAdapterNode )
6009 {
6010 vos_mem_free( pHddAdapterNode );
6011 }
6012
6013 goto resume_bmps;
6014 }
6015
6016 if(VOS_STATUS_SUCCESS == status)
6017 {
6018 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6019
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006020 //Initialize the WoWL service
6021 if(!hdd_init_wowl(pAdapter))
6022 {
6023 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6024 goto err_free_netdev;
6025 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 return pAdapter;
6028
6029err_free_netdev:
6030 free_netdev(pAdapter->dev);
6031 wlan_hdd_release_intf_addr( pHddCtx,
6032 pAdapter->macAddressCurrent.bytes );
6033
6034resume_bmps:
6035 //If bmps disabled enable it
6036 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6037 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306038 if (pHddCtx->hdd_wlan_suspended)
6039 {
6040 hdd_set_pwrparams(pHddCtx);
6041 }
6042 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 }
6044 return NULL;
6045}
6046
6047VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6048 tANI_U8 rtnl_held )
6049{
6050 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6051 VOS_STATUS status;
6052
6053 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6054 if( VOS_STATUS_SUCCESS != status )
6055 return status;
6056
6057 while ( pCurrent->pAdapter != pAdapter )
6058 {
6059 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6060 if( VOS_STATUS_SUCCESS != status )
6061 break;
6062
6063 pCurrent = pNext;
6064 }
6065 pAdapterNode = pCurrent;
6066 if( VOS_STATUS_SUCCESS == status )
6067 {
6068 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6069 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306070
6071#ifdef FEATURE_WLAN_TDLS
6072
6073 /* A Mutex Lock is introduced while changing/initializing the mode to
6074 * protect the concurrent access for the Adapters by TDLS module.
6075 */
6076 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6077 {
6078 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6079 "%s: unable to lock list", __func__);
6080 return VOS_STATUS_E_FAILURE;
6081 }
6082#endif
6083
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 hdd_remove_adapter( pHddCtx, pAdapterNode );
6085 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006086 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006087
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306088#ifdef FEATURE_WLAN_TDLS
6089 mutex_unlock(&pHddCtx->tdls_lock);
6090#endif
6091
Jeff Johnson295189b2012-06-20 16:38:30 -07006092
6093 /* If there is a single session of STA/P2P client, re-enable BMPS */
6094 if ((!vos_concurrent_sessions_running()) &&
6095 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6096 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6097 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306098 if (pHddCtx->hdd_wlan_suspended)
6099 {
6100 hdd_set_pwrparams(pHddCtx);
6101 }
6102 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006103 }
6104
6105 return VOS_STATUS_SUCCESS;
6106 }
6107
6108 return VOS_STATUS_E_FAILURE;
6109}
6110
6111VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6112{
6113 hdd_adapter_list_node_t *pHddAdapterNode;
6114 VOS_STATUS status;
6115
6116 ENTER();
6117
6118 do
6119 {
6120 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6121 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6122 {
6123 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6124 vos_mem_free( pHddAdapterNode );
6125 }
6126 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6127
6128 EXIT();
6129
6130 return VOS_STATUS_SUCCESS;
6131}
6132
6133void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6134{
6135 v_U8_t addIE[1] = {0};
6136
6137 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6138 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6139 eANI_BOOLEAN_FALSE) )
6140 {
6141 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006142 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006143 }
6144
6145 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6146 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6147 eANI_BOOLEAN_FALSE) )
6148 {
6149 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006150 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 }
6152
6153 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6154 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6155 eANI_BOOLEAN_FALSE) )
6156 {
6157 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006158 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 }
6160}
6161
6162VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6163{
6164 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6165 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6166 union iwreq_data wrqu;
6167
6168 ENTER();
6169
6170 switch(pAdapter->device_mode)
6171 {
6172 case WLAN_HDD_INFRA_STATION:
6173 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006174 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6176 {
6177 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6178 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6179 pAdapter->sessionId,
6180 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6181 else
6182 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6183 pAdapter->sessionId,
6184 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6185 //success implies disconnect command got queued up successfully
6186 if(halStatus == eHAL_STATUS_SUCCESS)
6187 {
6188 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6189 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6190 }
6191 memset(&wrqu, '\0', sizeof(wrqu));
6192 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6193 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6194 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6195 }
6196 else
6197 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306198 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306200#ifdef WLAN_OPEN_SOURCE
6201#ifdef WLAN_NS_OFFLOAD
6202 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6203#endif
6204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006205
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306206#ifdef WLAN_OPEN_SOURCE
6207 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6210 {
6211 INIT_COMPLETION(pAdapter->session_close_comp_var);
6212 if (eHAL_STATUS_SUCCESS ==
6213 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6214 hdd_smeCloseSessionCallback, pAdapter))
6215 {
6216 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006217 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006218 &pAdapter->session_close_comp_var,
6219 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6220 }
6221 }
6222
6223 break;
6224
6225 case WLAN_HDD_SOFTAP:
6226 case WLAN_HDD_P2P_GO:
6227 //Any softap specific cleanup here...
6228 mutex_lock(&pHddCtx->sap_lock);
6229 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6230 {
6231 VOS_STATUS status;
6232 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6233
6234 //Stop Bss.
6235 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6236 if (VOS_IS_STATUS_SUCCESS(status))
6237 {
6238 hdd_hostapd_state_t *pHostapdState =
6239 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6240
6241 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6242
6243 if (!VOS_IS_STATUS_SUCCESS(status))
6244 {
6245 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006246 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006247 }
6248 }
6249 else
6250 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006251 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 }
6253 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6254
6255 if (eHAL_STATUS_FAILURE ==
6256 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6257 0, NULL, eANI_BOOLEAN_FALSE))
6258 {
6259 hddLog(LOGE,
6260 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006261 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006262 }
6263
6264 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6265 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6266 eANI_BOOLEAN_FALSE) )
6267 {
6268 hddLog(LOGE,
6269 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6270 }
6271
6272 // Reset WNI_CFG_PROBE_RSP Flags
6273 wlan_hdd_reset_prob_rspies(pAdapter);
6274 kfree(pAdapter->sessionCtx.ap.beacon);
6275 pAdapter->sessionCtx.ap.beacon = NULL;
6276 }
6277 mutex_unlock(&pHddCtx->sap_lock);
6278 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006279
Jeff Johnson295189b2012-06-20 16:38:30 -07006280 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006281#ifdef WLAN_OPEN_SOURCE
6282 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6283#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006285
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 default:
6287 break;
6288 }
6289
6290 EXIT();
6291 return VOS_STATUS_SUCCESS;
6292}
6293
6294VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6295{
6296 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6297 VOS_STATUS status;
6298 hdd_adapter_t *pAdapter;
6299
6300 ENTER();
6301
6302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6303
6304 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6305 {
6306 pAdapter = pAdapterNode->pAdapter;
6307 netif_tx_disable(pAdapter->dev);
6308 netif_carrier_off(pAdapter->dev);
6309
6310 hdd_stop_adapter( pHddCtx, pAdapter );
6311
6312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6313 pAdapterNode = pNext;
6314 }
6315
6316 EXIT();
6317
6318 return VOS_STATUS_SUCCESS;
6319}
6320
Rajeev Kumarf999e582014-01-09 17:33:29 -08006321
6322#ifdef FEATURE_WLAN_BATCH_SCAN
6323/**---------------------------------------------------------------------------
6324
6325 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6326 structures
6327
6328 \param - pAdapter Pointer to HDD adapter
6329
6330 \return - None
6331
6332 --------------------------------------------------------------------------*/
6333void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6334{
6335 tHddBatchScanRsp *pNode;
6336 tHddBatchScanRsp *pPrev;
6337
6338 if (pAdapter)
6339 {
6340 pNode = pAdapter->pBatchScanRsp;
6341 while (pNode)
6342 {
6343 pPrev = pNode;
6344 pNode = pNode->pNext;
6345 vos_mem_free((v_VOID_t * )pPrev);
6346 }
6347 pAdapter->pBatchScanRsp = NULL;
6348 }
6349
6350 pAdapter->pBatchScanRsp = NULL;
6351 pAdapter->numScanList = 0;
6352 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6353 pAdapter->prev_batch_id = 0;
6354
6355 return;
6356}
6357#endif
6358
6359
Jeff Johnson295189b2012-06-20 16:38:30 -07006360VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6361{
6362 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6363 VOS_STATUS status;
6364 hdd_adapter_t *pAdapter;
6365
6366 ENTER();
6367
6368 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6369
6370 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6371 {
6372 pAdapter = pAdapterNode->pAdapter;
6373 netif_tx_disable(pAdapter->dev);
6374 netif_carrier_off(pAdapter->dev);
6375
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006376 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6377
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306379 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6380 {
6381 hdd_wmm_adapter_close( pAdapter );
6382 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006384
Rajeev Kumarf999e582014-01-09 17:33:29 -08006385#ifdef FEATURE_WLAN_BATCH_SCAN
6386 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6387 {
6388 hdd_deinit_batch_scan(pAdapter);
6389 }
6390#endif
6391
Jeff Johnson295189b2012-06-20 16:38:30 -07006392 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6393 pAdapterNode = pNext;
6394 }
6395
6396 EXIT();
6397
6398 return VOS_STATUS_SUCCESS;
6399}
6400
6401VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6402{
6403 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6404 VOS_STATUS status;
6405 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306406 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006407
6408 ENTER();
6409
6410 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6411
6412 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6413 {
6414 pAdapter = pAdapterNode->pAdapter;
6415
6416 switch(pAdapter->device_mode)
6417 {
6418 case WLAN_HDD_INFRA_STATION:
6419 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006420 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306421
6422 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6423
Jeff Johnson295189b2012-06-20 16:38:30 -07006424 hdd_init_station_mode(pAdapter);
6425 /* Open the gates for HDD to receive Wext commands */
6426 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006427 pHddCtx->scan_info.mScanPending = FALSE;
6428 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006429
6430 //Trigger the initial scan
6431 hdd_wlan_initial_scan(pAdapter);
6432
6433 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306434 if (eConnectionState_Associated == connState ||
6435 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 {
6437 union iwreq_data wrqu;
6438 memset(&wrqu, '\0', sizeof(wrqu));
6439 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6440 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6441 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006442 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006443
Jeff Johnson295189b2012-06-20 16:38:30 -07006444 /* indicate disconnected event to nl80211 */
6445 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6446 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306448 else if (eConnectionState_Connecting == connState)
6449 {
6450 /*
6451 * Indicate connect failure to supplicant if we were in the
6452 * process of connecting
6453 */
6454 cfg80211_connect_result(pAdapter->dev, NULL,
6455 NULL, 0, NULL, 0,
6456 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6457 GFP_KERNEL);
6458 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 break;
6460
6461 case WLAN_HDD_SOFTAP:
6462 /* softAP can handle SSR */
6463 break;
6464
6465 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006466 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006468 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006469 break;
6470
6471 case WLAN_HDD_MONITOR:
6472 /* monitor interface start */
6473 break;
6474 default:
6475 break;
6476 }
6477
6478 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6479 pAdapterNode = pNext;
6480 }
6481
6482 EXIT();
6483
6484 return VOS_STATUS_SUCCESS;
6485}
6486
6487VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6488{
6489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6490 hdd_adapter_t *pAdapter;
6491 VOS_STATUS status;
6492 v_U32_t roamId;
6493
6494 ENTER();
6495
6496 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6497
6498 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6499 {
6500 pAdapter = pAdapterNode->pAdapter;
6501
6502 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6503 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6504 {
6505 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6507
6508 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6509 init_completion(&pAdapter->disconnect_comp_var);
6510 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6511 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6512
6513 wait_for_completion_interruptible_timeout(
6514 &pAdapter->disconnect_comp_var,
6515 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6516
6517 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6518 pHddCtx->isAmpAllowed = VOS_FALSE;
6519 sme_RoamConnect(pHddCtx->hHal,
6520 pAdapter->sessionId, &(pWextState->roamProfile),
6521 &roamId);
6522 }
6523
6524 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6525 pAdapterNode = pNext;
6526 }
6527
6528 EXIT();
6529
6530 return VOS_STATUS_SUCCESS;
6531}
6532
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006533void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6534{
6535 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6536 VOS_STATUS status;
6537 hdd_adapter_t *pAdapter;
6538 hdd_station_ctx_t *pHddStaCtx;
6539 hdd_ap_ctx_t *pHddApCtx;
6540 hdd_hostapd_state_t * pHostapdState;
6541 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6542 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6543 const char *p2pMode = "DEV";
6544 const char *ccMode = "Standalone";
6545 int n;
6546
6547 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6548 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6549 {
6550 pAdapter = pAdapterNode->pAdapter;
6551 switch (pAdapter->device_mode) {
6552 case WLAN_HDD_INFRA_STATION:
6553 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6554 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6555 staChannel = pHddStaCtx->conn_info.operationChannel;
6556 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6557 }
6558 break;
6559 case WLAN_HDD_P2P_CLIENT:
6560 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6561 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6562 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6563 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6564 p2pMode = "CLI";
6565 }
6566 break;
6567 case WLAN_HDD_P2P_GO:
6568 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6569 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6570 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6571 p2pChannel = pHddApCtx->operatingChannel;
6572 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6573 }
6574 p2pMode = "GO";
6575 break;
6576 case WLAN_HDD_SOFTAP:
6577 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6578 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6579 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6580 apChannel = pHddApCtx->operatingChannel;
6581 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6582 }
6583 break;
6584 default:
6585 break;
6586 }
6587 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6588 pAdapterNode = pNext;
6589 }
6590 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6591 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6592 }
6593 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6594 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6595 if (p2pChannel > 0) {
6596 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6597 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6598 }
6599 if (apChannel > 0) {
6600 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6601 apChannel, MAC_ADDR_ARRAY(apBssid));
6602 }
6603
6604 if (p2pChannel > 0 && apChannel > 0) {
6605 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6606 }
6607}
6608
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006609bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006610{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006611 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006612}
6613
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006614/* Once SSR is disabled then it cannot be set. */
6615void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006616{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006617 if (HDD_SSR_DISABLED == isSsrRequired)
6618 return;
6619
Jeff Johnson295189b2012-06-20 16:38:30 -07006620 isSsrRequired = value;
6621}
6622
6623VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6624 hdd_adapter_list_node_t** ppAdapterNode)
6625{
6626 VOS_STATUS status;
6627 spin_lock(&pHddCtx->hddAdapters.lock);
6628 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6629 (hdd_list_node_t**) ppAdapterNode );
6630 spin_unlock(&pHddCtx->hddAdapters.lock);
6631 return status;
6632}
6633
6634VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6635 hdd_adapter_list_node_t* pAdapterNode,
6636 hdd_adapter_list_node_t** pNextAdapterNode)
6637{
6638 VOS_STATUS status;
6639 spin_lock(&pHddCtx->hddAdapters.lock);
6640 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6641 (hdd_list_node_t*) pAdapterNode,
6642 (hdd_list_node_t**)pNextAdapterNode );
6643
6644 spin_unlock(&pHddCtx->hddAdapters.lock);
6645 return status;
6646}
6647
6648VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6649 hdd_adapter_list_node_t* pAdapterNode)
6650{
6651 VOS_STATUS status;
6652 spin_lock(&pHddCtx->hddAdapters.lock);
6653 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6654 &pAdapterNode->node );
6655 spin_unlock(&pHddCtx->hddAdapters.lock);
6656 return status;
6657}
6658
6659VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6660 hdd_adapter_list_node_t** ppAdapterNode)
6661{
6662 VOS_STATUS status;
6663 spin_lock(&pHddCtx->hddAdapters.lock);
6664 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6665 (hdd_list_node_t**) ppAdapterNode );
6666 spin_unlock(&pHddCtx->hddAdapters.lock);
6667 return status;
6668}
6669
6670VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6671 hdd_adapter_list_node_t* pAdapterNode)
6672{
6673 VOS_STATUS status;
6674 spin_lock(&pHddCtx->hddAdapters.lock);
6675 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6676 (hdd_list_node_t*) pAdapterNode );
6677 spin_unlock(&pHddCtx->hddAdapters.lock);
6678 return status;
6679}
6680
6681VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6682 hdd_adapter_list_node_t* pAdapterNode)
6683{
6684 VOS_STATUS status;
6685 spin_lock(&pHddCtx->hddAdapters.lock);
6686 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6687 (hdd_list_node_t*) pAdapterNode );
6688 spin_unlock(&pHddCtx->hddAdapters.lock);
6689 return status;
6690}
6691
6692hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6693 tSirMacAddr macAddr )
6694{
6695 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6696 hdd_adapter_t *pAdapter;
6697 VOS_STATUS status;
6698
6699 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6700
6701 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6702 {
6703 pAdapter = pAdapterNode->pAdapter;
6704
6705 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6706 macAddr, sizeof(tSirMacAddr) ) )
6707 {
6708 return pAdapter;
6709 }
6710 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6711 pAdapterNode = pNext;
6712 }
6713
6714 return NULL;
6715
6716}
6717
6718hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6719{
6720 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6721 hdd_adapter_t *pAdapter;
6722 VOS_STATUS status;
6723
6724 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6725
6726 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6727 {
6728 pAdapter = pAdapterNode->pAdapter;
6729
6730 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6731 IFNAMSIZ ) )
6732 {
6733 return pAdapter;
6734 }
6735 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6736 pAdapterNode = pNext;
6737 }
6738
6739 return NULL;
6740
6741}
6742
6743hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6744{
6745 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6746 hdd_adapter_t *pAdapter;
6747 VOS_STATUS status;
6748
6749 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6750
6751 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6752 {
6753 pAdapter = pAdapterNode->pAdapter;
6754
6755 if( pAdapter && (mode == pAdapter->device_mode) )
6756 {
6757 return pAdapter;
6758 }
6759 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6760 pAdapterNode = pNext;
6761 }
6762
6763 return NULL;
6764
6765}
6766
6767//Remove this function later
6768hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6769{
6770 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6771 hdd_adapter_t *pAdapter;
6772 VOS_STATUS status;
6773
6774 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6775
6776 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6777 {
6778 pAdapter = pAdapterNode->pAdapter;
6779
6780 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6781 {
6782 return pAdapter;
6783 }
6784
6785 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6786 pAdapterNode = pNext;
6787 }
6788
6789 return NULL;
6790
6791}
6792
Jeff Johnson295189b2012-06-20 16:38:30 -07006793/**---------------------------------------------------------------------------
6794
6795 \brief hdd_set_monitor_tx_adapter() -
6796
6797 This API initializes the adapter to be used while transmitting on monitor
6798 adapter.
6799
6800 \param - pHddCtx - Pointer to the HDD context.
6801 pAdapter - Adapter that will used for TX. This can be NULL.
6802 \return - None.
6803 --------------------------------------------------------------------------*/
6804void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6805{
6806 hdd_adapter_t *pMonAdapter;
6807
6808 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6809
6810 if( NULL != pMonAdapter )
6811 {
6812 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6813 }
6814}
Jeff Johnson295189b2012-06-20 16:38:30 -07006815/**---------------------------------------------------------------------------
6816
6817 \brief hdd_select_queue() -
6818
6819 This API returns the operating channel of the requested device mode
6820
6821 \param - pHddCtx - Pointer to the HDD context.
6822 - mode - Device mode for which operating channel is required
6823 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6824 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6825 \return - channel number. "0" id the requested device is not found OR it is not connected.
6826 --------------------------------------------------------------------------*/
6827v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6828{
6829 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6830 VOS_STATUS status;
6831 hdd_adapter_t *pAdapter;
6832 v_U8_t operatingChannel = 0;
6833
6834 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6835
6836 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6837 {
6838 pAdapter = pAdapterNode->pAdapter;
6839
6840 if( mode == pAdapter->device_mode )
6841 {
6842 switch(pAdapter->device_mode)
6843 {
6844 case WLAN_HDD_INFRA_STATION:
6845 case WLAN_HDD_P2P_CLIENT:
6846 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6847 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6848 break;
6849 case WLAN_HDD_SOFTAP:
6850 case WLAN_HDD_P2P_GO:
6851 /*softap connection info */
6852 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6853 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6854 break;
6855 default:
6856 break;
6857 }
6858
6859 break; //Found the device of interest. break the loop
6860 }
6861
6862 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6863 pAdapterNode = pNext;
6864 }
6865 return operatingChannel;
6866}
6867
6868#ifdef WLAN_FEATURE_PACKET_FILTERING
6869/**---------------------------------------------------------------------------
6870
6871 \brief hdd_set_multicast_list() -
6872
6873 This used to set the multicast address list.
6874
6875 \param - dev - Pointer to the WLAN device.
6876 - skb - Pointer to OS packet (sk_buff).
6877 \return - success/fail
6878
6879 --------------------------------------------------------------------------*/
6880static void hdd_set_multicast_list(struct net_device *dev)
6881{
6882 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006883 int mc_count;
6884 int i = 0;
6885 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306886
6887 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006888 {
6889 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306890 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006891 return;
6892 }
6893
6894 if (dev->flags & IFF_ALLMULTI)
6895 {
6896 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006897 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306898 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006899 }
6900 else
6901 {
6902 mc_count = netdev_mc_count(dev);
6903 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006904 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006905 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6906 {
6907 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006908 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306909 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006910 return;
6911 }
6912
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306913 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006914
6915 netdev_for_each_mc_addr(ha, dev) {
6916 if (i == mc_count)
6917 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306918 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6919 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006920 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006921 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306922 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006923 i++;
6924 }
6925 }
6926 return;
6927}
6928#endif
6929
6930/**---------------------------------------------------------------------------
6931
6932 \brief hdd_select_queue() -
6933
6934 This function is registered with the Linux OS for network
6935 core to decide which queue to use first.
6936
6937 \param - dev - Pointer to the WLAN device.
6938 - skb - Pointer to OS packet (sk_buff).
6939 \return - ac, Queue Index/access category corresponding to UP in IP header
6940
6941 --------------------------------------------------------------------------*/
6942v_U16_t hdd_select_queue(struct net_device *dev,
6943 struct sk_buff *skb)
6944{
6945 return hdd_wmm_select_queue(dev, skb);
6946}
6947
6948
6949/**---------------------------------------------------------------------------
6950
6951 \brief hdd_wlan_initial_scan() -
6952
6953 This function triggers the initial scan
6954
6955 \param - pAdapter - Pointer to the HDD adapter.
6956
6957 --------------------------------------------------------------------------*/
6958void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6959{
6960 tCsrScanRequest scanReq;
6961 tCsrChannelInfo channelInfo;
6962 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006963 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006964 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6965
6966 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6967 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6968 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6969
6970 if(sme_Is11dSupported(pHddCtx->hHal))
6971 {
6972 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6973 if ( HAL_STATUS_SUCCESS( halStatus ) )
6974 {
6975 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6976 if( !scanReq.ChannelInfo.ChannelList )
6977 {
6978 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6979 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006980 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 return;
6982 }
6983 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6984 channelInfo.numOfChannels);
6985 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6986 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006987 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006988 }
6989
6990 scanReq.scanType = eSIR_PASSIVE_SCAN;
6991 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6992 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6993 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6994 }
6995 else
6996 {
6997 scanReq.scanType = eSIR_ACTIVE_SCAN;
6998 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6999 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7000 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7001 }
7002
7003 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7004 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7005 {
7006 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7007 __func__, halStatus );
7008 }
7009
7010 if(sme_Is11dSupported(pHddCtx->hHal))
7011 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7012}
7013
Jeff Johnson295189b2012-06-20 16:38:30 -07007014/**---------------------------------------------------------------------------
7015
7016 \brief hdd_full_power_callback() - HDD full power callback function
7017
7018 This is the function invoked by SME to inform the result of a full power
7019 request issued by HDD
7020
7021 \param - callbackcontext - Pointer to cookie
7022 \param - status - result of request
7023
7024 \return - None
7025
7026 --------------------------------------------------------------------------*/
7027static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7028{
Jeff Johnson72a40512013-12-19 10:14:15 -08007029 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007030
7031 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307032 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007033
7034 if (NULL == callbackContext)
7035 {
7036 hddLog(VOS_TRACE_LEVEL_ERROR,
7037 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007038 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007039 return;
7040 }
7041
Jeff Johnson72a40512013-12-19 10:14:15 -08007042 /* there is a race condition that exists between this callback
7043 function and the caller since the caller could time out either
7044 before or while this code is executing. we use a spinlock to
7045 serialize these actions */
7046 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007047
7048 if (POWER_CONTEXT_MAGIC != pContext->magic)
7049 {
7050 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007051 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007052 hddLog(VOS_TRACE_LEVEL_WARN,
7053 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007054 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007055 return;
7056 }
7057
Jeff Johnson72a40512013-12-19 10:14:15 -08007058 /* context is valid so caller is still waiting */
7059
7060 /* paranoia: invalidate the magic */
7061 pContext->magic = 0;
7062
7063 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007064 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007065
7066 /* serialization is complete */
7067 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007068}
7069
7070/**---------------------------------------------------------------------------
7071
7072 \brief hdd_wlan_exit() - HDD WLAN exit function
7073
7074 This is the driver exit point (invoked during rmmod)
7075
7076 \param - pHddCtx - Pointer to the HDD Context
7077
7078 \return - None
7079
7080 --------------------------------------------------------------------------*/
7081void hdd_wlan_exit(hdd_context_t *pHddCtx)
7082{
7083 eHalStatus halStatus;
7084 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7085 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307086 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007087 hdd_adapter_t* pAdapter;
Jeff Johnson72a40512013-12-19 10:14:15 -08007088 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007089 long lrc;
7090
7091 ENTER();
7092
Jeff Johnson88ba7742013-02-27 14:36:02 -08007093 if (VOS_FTM_MODE != hdd_get_conparam())
7094 {
7095 // Unloading, restart logic is no more required.
7096 wlan_hdd_restart_deinit(pHddCtx);
7097 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007098
Jeff Johnson295189b2012-06-20 16:38:30 -07007099 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007100 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007101 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007102 {
7103 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7104 WLAN_HDD_INFRA_STATION);
7105 if (pAdapter == NULL)
7106 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7107
7108 if (pAdapter != NULL)
7109 {
7110 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7111 hdd_UnregisterWext(pAdapter->dev);
7112 }
7113 }
7114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007115
Jeff Johnson295189b2012-06-20 16:38:30 -07007116 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007117 {
7118 wlan_hdd_ftm_close(pHddCtx);
7119 goto free_hdd_ctx;
7120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007121 //Stop the Interface TX queue.
7122 //netif_tx_disable(pWlanDev);
7123 //netif_carrier_off(pWlanDev);
7124
Jeff Johnson295189b2012-06-20 16:38:30 -07007125 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7126 {
7127 pAdapter = hdd_get_adapter(pHddCtx,
7128 WLAN_HDD_SOFTAP);
7129 }
7130 else
7131 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007132 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007133 {
7134 pAdapter = hdd_get_adapter(pHddCtx,
7135 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007136 if (pAdapter == NULL)
7137 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007139 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007140 /* DeRegister with platform driver as client for Suspend/Resume */
7141 vosStatus = hddDeregisterPmOps(pHddCtx);
7142 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7143 {
7144 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7145 VOS_ASSERT(0);
7146 }
7147
7148 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7149 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7150 {
7151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7152 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007153
7154 // Cancel any outstanding scan requests. We are about to close all
7155 // of our adapters, but an adapter structure is what SME passes back
7156 // to our callback function. Hence if there are any outstanding scan
7157 // requests then there is a race condition between when the adapter
7158 // is closed and when the callback is invoked. We try to resolve that
7159 // race condition here by canceling any outstanding scans before we
7160 // close the adapters.
7161 // Note that the scans may be cancelled in an asynchronous manner, so
7162 // ideally there needs to be some kind of synchronization. Rather than
7163 // introduce a new synchronization here, we will utilize the fact that
7164 // we are about to Request Full Power, and since that is synchronized,
7165 // the expectation is that by the time Request Full Power has completed,
7166 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007167 if (NULL != pAdapter)
7168 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7169 else
7170 hddLog(VOS_TRACE_LEVEL_ERROR,
7171 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007172
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007173 //Stop the traffic monitor timer
7174 if ( VOS_TIMER_STATE_RUNNING ==
7175 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7176 {
7177 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7178 }
7179
7180 // Destroy the traffic monitor timer
7181 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7182 &pHddCtx->tx_rx_trafficTmr)))
7183 {
7184 hddLog(VOS_TRACE_LEVEL_ERROR,
7185 "%s: Cannot deallocate Traffic monitor timer", __func__);
7186 }
7187
Jeff Johnson295189b2012-06-20 16:38:30 -07007188 //Disable IMPS/BMPS as we do not want the device to enter any power
7189 //save mode during shutdown
7190 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7191 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7192 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7193
7194 //Ensure that device is in full power as we will touch H/W during vos_Stop
7195 init_completion(&powerContext.completion);
7196 powerContext.magic = POWER_CONTEXT_MAGIC;
7197
7198 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7199 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7200
7201 if (eHAL_STATUS_SUCCESS != halStatus)
7202 {
7203 if (eHAL_STATUS_PMC_PENDING == halStatus)
7204 {
7205 /* request was sent -- wait for the response */
7206 lrc = wait_for_completion_interruptible_timeout(
7207 &powerContext.completion,
7208 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 if (lrc <= 0)
7210 {
7211 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007212 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 }
7214 }
7215 else
7216 {
7217 hddLog(VOS_TRACE_LEVEL_ERROR,
7218 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007219 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007220 /* continue -- need to clean up as much as possible */
7221 }
7222 }
7223
Jeff Johnson72a40512013-12-19 10:14:15 -08007224 /* either we never sent a request, we sent a request and received a
7225 response or we sent a request and timed out. if we never sent a
7226 request or if we sent a request and got a response, we want to
7227 clear the magic out of paranoia. if we timed out there is a
7228 race condition such that the callback function could be
7229 executing at the same time we are. of primary concern is if the
7230 callback function had already verified the "magic" but had not
7231 yet set the completion variable when a timeout occurred. we
7232 serialize these activities by invalidating the magic while
7233 holding a shared spinlock which will cause us to block if the
7234 callback is currently executing */
7235 spin_lock(&hdd_context_lock);
7236 powerContext.magic = 0;
7237 spin_unlock(&hdd_context_lock);
7238
Yue Ma0d4891e2013-08-06 17:01:45 -07007239 hdd_debugfs_exit(pHddCtx);
7240
Jeff Johnson295189b2012-06-20 16:38:30 -07007241 // Unregister the Net Device Notifier
7242 unregister_netdevice_notifier(&hdd_netdev_notifier);
7243
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 hdd_stop_all_adapters( pHddCtx );
7245
Jeff Johnson295189b2012-06-20 16:38:30 -07007246#ifdef WLAN_BTAMP_FEATURE
7247 vosStatus = WLANBAP_Stop(pVosContext);
7248 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7249 {
7250 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7251 "%s: Failed to stop BAP",__func__);
7252 }
7253#endif //WLAN_BTAMP_FEATURE
7254
7255 //Stop all the modules
7256 vosStatus = vos_stop( pVosContext );
7257 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7258 {
7259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7260 "%s: Failed to stop VOSS",__func__);
7261 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7262 }
7263
Jeff Johnson295189b2012-06-20 16:38:30 -07007264 //Assert Deep sleep signal now to put Libra HW in lowest power state
7265 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7266 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7267
7268 //Vote off any PMIC voltage supplies
7269 vos_chipPowerDown(NULL, NULL, NULL);
7270
7271 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7272
Leo Chang59cdc7e2013-07-10 10:08:21 -07007273
Jeff Johnson295189b2012-06-20 16:38:30 -07007274 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007275 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007276
7277 //Close the scheduler before calling vos_close to make sure no thread is
7278 // scheduled after the each module close is called i.e after all the data
7279 // structures are freed.
7280 vosStatus = vos_sched_close( pVosContext );
7281 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7282 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7283 "%s: Failed to close VOSS Scheduler",__func__);
7284 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7285 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007286#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007287#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7288 /* Destroy the wake lock */
7289 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7290#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007291 /* Destroy the wake lock */
7292 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007293#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007294
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307295#ifdef CONFIG_ENABLE_LINUX_REG
7296 vosStatus = vos_nv_close();
7297 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7298 {
7299 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7300 "%s: Failed to close NV", __func__);
7301 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7302 }
7303#endif
7304
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 //Close VOSS
7306 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7307 vos_close(pVosContext);
7308
Jeff Johnson295189b2012-06-20 16:38:30 -07007309 //Close Watchdog
7310 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7311 vos_watchdog_close(pVosContext);
7312
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307313 //Clean up HDD Nlink Service
7314 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007315#ifdef WLAN_KD_READY_NOTIFIER
7316 nl_srv_exit(pHddCtx->ptt_pid);
7317#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307318 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007319#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307320
Jeff Johnson295189b2012-06-20 16:38:30 -07007321 /* Cancel the vote for XO Core ON.
7322 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7323 * exited at this point
7324 */
7325 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007326 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007327 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7328 {
7329 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7330 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007331 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 }
7333
7334 hdd_close_all_adapters( pHddCtx );
7335
7336
7337 //Free up dynamically allocated members inside HDD Adapter
7338 kfree(pHddCtx->cfg_ini);
7339 pHddCtx->cfg_ini= NULL;
7340
7341 /* free the power on lock from platform driver */
7342 if (free_riva_power_on_lock("wlan"))
7343 {
7344 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7345 __func__);
7346 }
7347
Jeff Johnson88ba7742013-02-27 14:36:02 -08007348free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007349 /* FTM mode, WIPHY did not registered
7350 If un-register here, system crash will happen */
7351 if (VOS_FTM_MODE != hdd_get_conparam())
7352 {
7353 wiphy_unregister(wiphy) ;
7354 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007355 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007356 if (hdd_is_ssr_required())
7357 {
7358 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007359 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007360 msleep(5000);
7361 }
7362 hdd_set_ssr_required (VOS_FALSE);
7363}
7364
7365
7366/**---------------------------------------------------------------------------
7367
7368 \brief hdd_update_config_from_nv() - Function to update the contents of
7369 the running configuration with parameters taken from NV storage
7370
7371 \param - pHddCtx - Pointer to the HDD global context
7372
7373 \return - VOS_STATUS_SUCCESS if successful
7374
7375 --------------------------------------------------------------------------*/
7376static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7377{
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 v_BOOL_t itemIsValid = VOS_FALSE;
7379 VOS_STATUS status;
7380 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7381 v_U8_t macLoop;
7382
7383 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7384 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7385 if(status != VOS_STATUS_SUCCESS)
7386 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007387 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 return VOS_STATUS_E_FAILURE;
7389 }
7390
7391 if (itemIsValid == VOS_TRUE)
7392 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007393 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007394 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7395 VOS_MAX_CONCURRENCY_PERSONA);
7396 if(status != VOS_STATUS_SUCCESS)
7397 {
7398 /* Get MAC from NV fail, not update CFG info
7399 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007400 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007401 return VOS_STATUS_E_FAILURE;
7402 }
7403
7404 /* If first MAC is not valid, treat all others are not valid
7405 * Then all MACs will be got from ini file */
7406 if(vos_is_macaddr_zero(&macFromNV[0]))
7407 {
7408 /* MAC address in NV file is not configured yet */
7409 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7410 return VOS_STATUS_E_INVAL;
7411 }
7412
7413 /* Get MAC address from NV, update CFG info */
7414 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7415 {
7416 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7417 {
7418 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7419 /* This MAC is not valid, skip it
7420 * This MAC will be got from ini file */
7421 }
7422 else
7423 {
7424 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7425 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7426 VOS_MAC_ADDR_SIZE);
7427 }
7428 }
7429 }
7430 else
7431 {
7432 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7433 return VOS_STATUS_E_FAILURE;
7434 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007435
Jeff Johnson295189b2012-06-20 16:38:30 -07007436
7437 return VOS_STATUS_SUCCESS;
7438}
7439
7440/**---------------------------------------------------------------------------
7441
7442 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7443
7444 \param - pAdapter - Pointer to the HDD
7445
7446 \return - None
7447
7448 --------------------------------------------------------------------------*/
7449VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7450{
7451 eHalStatus halStatus;
7452 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307453 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007454
Jeff Johnson295189b2012-06-20 16:38:30 -07007455
7456 // Send ready indication to the HDD. This will kick off the MAC
7457 // into a 'running' state and should kick off an initial scan.
7458 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7459 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7460 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307461 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 "code %08d [x%08x]",__func__, halStatus, halStatus );
7463 return VOS_STATUS_E_FAILURE;
7464 }
7465
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307466 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007467 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7468 // And RIVA will crash
7469 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7470 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307471 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7472 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7473
7474
Jeff Johnson295189b2012-06-20 16:38:30 -07007475 return VOS_STATUS_SUCCESS;
7476}
7477
Jeff Johnson295189b2012-06-20 16:38:30 -07007478/* wake lock APIs for HDD */
7479void hdd_prevent_suspend(void)
7480{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007481#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007482 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007483#else
7484 wcnss_prevent_suspend();
7485#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007486}
7487
7488void hdd_allow_suspend(void)
7489{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007490#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007491 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007492#else
7493 wcnss_allow_suspend();
7494#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007495}
7496
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007497void hdd_allow_suspend_timeout(v_U32_t timeout)
7498{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007499#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007500 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007501#else
7502 /* Do nothing as there is no API in wcnss for timeout*/
7503#endif
7504}
7505
Jeff Johnson295189b2012-06-20 16:38:30 -07007506/**---------------------------------------------------------------------------
7507
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007508 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7509 information between Host and Riva
7510
7511 This function gets reported version of FW
7512 It also finds the version of Riva headers used to compile the host
7513 It compares the above two and prints a warning if they are different
7514 It gets the SW and HW version string
7515 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7516 indicating the features they support through a bitmap
7517
7518 \param - pHddCtx - Pointer to HDD context
7519
7520 \return - void
7521
7522 --------------------------------------------------------------------------*/
7523
7524void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7525{
7526
7527 tSirVersionType versionCompiled;
7528 tSirVersionType versionReported;
7529 tSirVersionString versionString;
7530 tANI_U8 fwFeatCapsMsgSupported = 0;
7531 VOS_STATUS vstatus;
7532
7533 /* retrieve and display WCNSS version information */
7534 do {
7535
7536 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7537 &versionCompiled);
7538 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7539 {
7540 hddLog(VOS_TRACE_LEVEL_FATAL,
7541 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007542 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007543 break;
7544 }
7545
7546 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7547 &versionReported);
7548 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7549 {
7550 hddLog(VOS_TRACE_LEVEL_FATAL,
7551 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007552 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007553 break;
7554 }
7555
7556 if ((versionCompiled.major != versionReported.major) ||
7557 (versionCompiled.minor != versionReported.minor) ||
7558 (versionCompiled.version != versionReported.version) ||
7559 (versionCompiled.revision != versionReported.revision))
7560 {
7561 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7562 "Host expected %u.%u.%u.%u\n",
7563 WLAN_MODULE_NAME,
7564 (int)versionReported.major,
7565 (int)versionReported.minor,
7566 (int)versionReported.version,
7567 (int)versionReported.revision,
7568 (int)versionCompiled.major,
7569 (int)versionCompiled.minor,
7570 (int)versionCompiled.version,
7571 (int)versionCompiled.revision);
7572 }
7573 else
7574 {
7575 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7576 WLAN_MODULE_NAME,
7577 (int)versionReported.major,
7578 (int)versionReported.minor,
7579 (int)versionReported.version,
7580 (int)versionReported.revision);
7581 }
7582
7583 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7584 versionString,
7585 sizeof(versionString));
7586 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7587 {
7588 hddLog(VOS_TRACE_LEVEL_FATAL,
7589 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007590 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007591 break;
7592 }
7593
7594 pr_info("%s: WCNSS software version %s\n",
7595 WLAN_MODULE_NAME, versionString);
7596
7597 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7598 versionString,
7599 sizeof(versionString));
7600 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7601 {
7602 hddLog(VOS_TRACE_LEVEL_FATAL,
7603 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007604 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007605 break;
7606 }
7607
7608 pr_info("%s: WCNSS hardware version %s\n",
7609 WLAN_MODULE_NAME, versionString);
7610
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007611 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7612 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007613 send the message only if it the riva is 1.1
7614 minor numbers for different riva branches:
7615 0 -> (1.0)Mainline Build
7616 1 -> (1.1)Mainline Build
7617 2->(1.04) Stability Build
7618 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007619 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007620 ((versionReported.minor>=1) && (versionReported.version>=1)))
7621 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7622 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007623
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007624 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007625 {
7626#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7627 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7628 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7629#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007630 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7631 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7632 {
7633 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7634 }
7635
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007636 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007637 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007638
7639 } while (0);
7640
7641}
7642
7643/**---------------------------------------------------------------------------
7644
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307645 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7646
7647 \param - pHddCtx - Pointer to the hdd context
7648
7649 \return - true if hardware supports 5GHz
7650
7651 --------------------------------------------------------------------------*/
7652static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7653{
7654 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7655 * then hardware support 5Ghz.
7656 */
7657 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7658 {
7659 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7660 return true;
7661 }
7662 else
7663 {
7664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7665 __func__);
7666 return false;
7667 }
7668}
7669
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307670/**---------------------------------------------------------------------------
7671
7672 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7673 generate function
7674
7675 This is generate the random mac address for WLAN interface
7676
7677 \param - pHddCtx - Pointer to HDD context
7678 idx - Start interface index to get auto
7679 generated mac addr.
7680 mac_addr - Mac address
7681
7682 \return - 0 for success, < 0 for failure
7683
7684 --------------------------------------------------------------------------*/
7685
7686static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7687 int idx, v_MACADDR_t mac_addr)
7688{
7689 int i;
7690 unsigned int serialno;
7691 serialno = wcnss_get_serial_number();
7692
7693 if (0 != serialno)
7694 {
7695 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7696 bytes of the serial number that can be used to generate
7697 the other 3 bytes of the MAC address. Mask off all but
7698 the lower 3 bytes (this will also make sure we don't
7699 overflow in the next step) */
7700 serialno &= 0x00FFFFFF;
7701
7702 /* we need a unique address for each session */
7703 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7704
7705 /* autogen other Mac addresses */
7706 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7707 {
7708 /* start with the entire default address */
7709 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7710 /* then replace the lower 3 bytes */
7711 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7712 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7713 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7714
7715 serialno++;
7716 hddLog(VOS_TRACE_LEVEL_ERROR,
7717 "%s: Derived Mac Addr: "
7718 MAC_ADDRESS_STR, __func__,
7719 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7720 }
7721
7722 }
7723 else
7724 {
7725 hddLog(LOGE, FL("Failed to Get Serial NO"));
7726 return -1;
7727 }
7728 return 0;
7729}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307730
7731/**---------------------------------------------------------------------------
7732
Jeff Johnson295189b2012-06-20 16:38:30 -07007733 \brief hdd_wlan_startup() - HDD init function
7734
7735 This is the driver startup code executed once a WLAN device has been detected
7736
7737 \param - dev - Pointer to the underlying device
7738
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007739 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007740
7741 --------------------------------------------------------------------------*/
7742
7743int hdd_wlan_startup(struct device *dev )
7744{
7745 VOS_STATUS status;
7746 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007747 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007748 hdd_context_t *pHddCtx = NULL;
7749 v_CONTEXT_t pVosContext= NULL;
7750#ifdef WLAN_BTAMP_FEATURE
7751 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7752 WLANBAP_ConfigType btAmpConfig;
7753 hdd_config_t *pConfig;
7754#endif
7755 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007756 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307757 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007758
7759 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007760 /*
7761 * cfg80211: wiphy allocation
7762 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307763 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007764
7765 if(wiphy == NULL)
7766 {
7767 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007768 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 }
7770
7771 pHddCtx = wiphy_priv(wiphy);
7772
Jeff Johnson295189b2012-06-20 16:38:30 -07007773 //Initialize the adapter context to zeros.
7774 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007777 hdd_prevent_suspend();
7778 pHddCtx->isLoadUnloadInProgress = TRUE;
7779
7780 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7781
7782 /*Get vos context here bcoz vos_open requires it*/
7783 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7784
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007785 if(pVosContext == NULL)
7786 {
7787 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7788 goto err_free_hdd_context;
7789 }
7790
Jeff Johnson295189b2012-06-20 16:38:30 -07007791 //Save the Global VOSS context in adapter context for future.
7792 pHddCtx->pvosContext = pVosContext;
7793
7794 //Save the adapter context in global context for future.
7795 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7796
Jeff Johnson295189b2012-06-20 16:38:30 -07007797 pHddCtx->parent_dev = dev;
7798
7799 init_completion(&pHddCtx->full_pwr_comp_var);
7800 init_completion(&pHddCtx->standby_comp_var);
7801 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007802 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007803 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307804 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007805
7806#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007807 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007808#else
7809 init_completion(&pHddCtx->driver_crda_req);
7810#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007811
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307812 spin_lock_init(&pHddCtx->schedScan_lock);
7813
Jeff Johnson295189b2012-06-20 16:38:30 -07007814 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7815
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307816#ifdef FEATURE_WLAN_TDLS
7817 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7818 * invoked by other instances also) to protect the concurrent
7819 * access for the Adapters by TDLS module.
7820 */
7821 mutex_init(&pHddCtx->tdls_lock);
7822#endif
7823
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307824 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007825 // Load all config first as TL config is needed during vos_open
7826 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7827 if(pHddCtx->cfg_ini == NULL)
7828 {
7829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7830 goto err_free_hdd_context;
7831 }
7832
7833 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7834
7835 // Read and parse the qcom_cfg.ini file
7836 status = hdd_parse_config_ini( pHddCtx );
7837 if ( VOS_STATUS_SUCCESS != status )
7838 {
7839 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7840 __func__, WLAN_INI_FILE);
7841 goto err_config;
7842 }
Arif Hussaind5218912013-12-05 01:10:55 -08007843#ifdef MEMORY_DEBUG
7844 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7845 vos_mem_init();
7846
7847 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7848 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007850
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307851 /* INI has been read, initialise the configuredMcastBcastFilter with
7852 * INI value as this will serve as the default value
7853 */
7854 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7855 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7856 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307857
7858 if (false == hdd_is_5g_supported(pHddCtx))
7859 {
7860 //5Ghz is not supported.
7861 if (1 != pHddCtx->cfg_ini->nBandCapability)
7862 {
7863 hddLog(VOS_TRACE_LEVEL_INFO,
7864 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7865 pHddCtx->cfg_ini->nBandCapability = 1;
7866 }
7867 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307868
7869 /* If SNR Monitoring is enabled, FW has to parse all beacons
7870 * for calcaluting and storing the average SNR, so set Nth beacon
7871 * filter to 1 to enable FW to parse all the beaocons
7872 */
7873 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7874 {
7875 /* The log level is deliberately set to WARN as overriding
7876 * nthBeaconFilter to 1 will increase power cosumption and this
7877 * might just prove helpful to detect the power issue.
7878 */
7879 hddLog(VOS_TRACE_LEVEL_WARN,
7880 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7881 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007883 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307884 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007885 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08007886 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007887 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08007888 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
7889 {
7890 hddLog(VOS_TRACE_LEVEL_FATAL,
7891 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7892 goto err_config;
7893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007894 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007895
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007896 // Update VOS trace levels based upon the cfg.ini
7897 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7898 pHddCtx->cfg_ini->vosTraceEnableBAP);
7899 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7900 pHddCtx->cfg_ini->vosTraceEnableTL);
7901 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7902 pHddCtx->cfg_ini->vosTraceEnableWDI);
7903 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7904 pHddCtx->cfg_ini->vosTraceEnableHDD);
7905 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7906 pHddCtx->cfg_ini->vosTraceEnableSME);
7907 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7908 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307909 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7910 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007911 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7912 pHddCtx->cfg_ini->vosTraceEnableWDA);
7913 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7914 pHddCtx->cfg_ini->vosTraceEnableSYS);
7915 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7916 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007917 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7918 pHddCtx->cfg_ini->vosTraceEnableSAP);
7919 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7920 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007921
Jeff Johnson295189b2012-06-20 16:38:30 -07007922 // Update WDI trace levels based upon the cfg.ini
7923 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7924 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7925 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7926 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7927 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7928 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7929 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7930 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007931
Jeff Johnson88ba7742013-02-27 14:36:02 -08007932 if (VOS_FTM_MODE == hdd_get_conparam())
7933 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007934 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7935 {
7936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7937 goto err_free_hdd_context;
7938 }
7939 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7940 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007941 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007942
Jeff Johnson88ba7742013-02-27 14:36:02 -08007943 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007944 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7945 {
7946 status = vos_watchdog_open(pVosContext,
7947 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7948
7949 if(!VOS_IS_STATUS_SUCCESS( status ))
7950 {
7951 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307952 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007953 }
7954 }
7955
7956 pHddCtx->isLogpInProgress = FALSE;
7957 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7958
Jeff Johnson295189b2012-06-20 16:38:30 -07007959 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7960 if(!VOS_IS_STATUS_SUCCESS(status))
7961 {
7962 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007963 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007964 }
7965
Amar Singhala49cbc52013-10-08 18:37:44 -07007966#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007967 /* initialize the NV module. This is required so that
7968 we can initialize the channel information in wiphy
7969 from the NV.bin data. The channel information in
7970 wiphy needs to be initialized before wiphy registration */
7971
7972 status = vos_nv_open();
7973 if (!VOS_IS_STATUS_SUCCESS(status))
7974 {
7975 /* NV module cannot be initialized */
7976 hddLog( VOS_TRACE_LEVEL_FATAL,
7977 "%s: vos_nv_open failed", __func__);
7978 goto err_clkvote;
7979 }
7980
7981 status = vos_init_wiphy_from_nv_bin();
7982 if (!VOS_IS_STATUS_SUCCESS(status))
7983 {
7984 /* NV module cannot be initialized */
7985 hddLog( VOS_TRACE_LEVEL_FATAL,
7986 "%s: vos_init_wiphy failed", __func__);
7987 goto err_vos_nv_close;
7988 }
7989
Amar Singhala49cbc52013-10-08 18:37:44 -07007990 /* registration of wiphy dev with cfg80211 */
7991 if (0 > wlan_hdd_cfg80211_register(wiphy))
7992 {
7993 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007994 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007995 }
7996#endif
7997
Jeff Johnson295189b2012-06-20 16:38:30 -07007998 status = vos_open( &pVosContext, 0);
7999 if ( !VOS_IS_STATUS_SUCCESS( status ))
8000 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008001 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07008002 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008003 }
8004
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8006
8007 if ( NULL == pHddCtx->hHal )
8008 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008009 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008010 goto err_vosclose;
8011 }
8012
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008013 status = vos_preStart( pHddCtx->pvosContext );
8014 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8015 {
8016 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
8017 goto err_vosclose;
8018 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008019
Arif Hussaineaf68602013-12-30 23:10:44 -08008020 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8021 {
8022 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8023 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8024 __func__, enable_dfs_chan_scan);
8025 }
8026 if (0 == enable_11d || 1 == enable_11d)
8027 {
8028 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8030 __func__, enable_11d);
8031 }
8032
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008033 /* Note that the vos_preStart() sequence triggers the cfg download.
8034 The cfg download must occur before we update the SME config
8035 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 status = hdd_set_sme_config( pHddCtx );
8037
8038 if ( VOS_STATUS_SUCCESS != status )
8039 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008040 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
8041 goto err_vosclose;
8042 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008043
8044 //Initialize the WMM module
8045 status = hdd_wmm_init(pHddCtx);
8046 if (!VOS_IS_STATUS_SUCCESS(status))
8047 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008049 goto err_vosclose;
8050 }
8051
Jeff Johnson295189b2012-06-20 16:38:30 -07008052 /* In the integrated architecture we update the configuration from
8053 the INI file and from NV before vOSS has been started so that
8054 the final contents are available to send down to the cCPU */
8055
8056 // Apply the cfg.ini to cfg.dat
8057 if (FALSE == hdd_update_config_dat(pHddCtx))
8058 {
8059 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
8060 goto err_vosclose;
8061 }
8062
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308063 // Get mac addr from platform driver
8064 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8065
8066 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308068 /* Store the mac addr for first interface */
8069 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8070
8071 hddLog(VOS_TRACE_LEVEL_ERROR,
8072 "%s: WLAN Mac Addr: "
8073 MAC_ADDRESS_STR, __func__,
8074 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8075
8076 /* Here, passing Arg2 as 1 because we do not want to change the
8077 last 3 bytes (means non OUI bytes) of first interface mac
8078 addr.
8079 */
8080 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8081 {
8082 hddLog(VOS_TRACE_LEVEL_ERROR,
8083 "%s: Failed to generate wlan interface mac addr "
8084 "using MAC from ini file ", __func__);
8085 }
8086 }
8087 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8088 {
8089 // Apply the NV to cfg.dat
8090 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008091#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8092 /* There was not a valid set of MAC Addresses in NV. See if the
8093 default addresses were modified by the cfg.ini settings. If so,
8094 we'll use them, but if not, we'll autogenerate a set of MAC
8095 addresses based upon the device serial number */
8096
8097 static const v_MACADDR_t default_address =
8098 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008099
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308100 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8101 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008102 {
8103 /* cfg.ini has the default address, invoke autogen logic */
8104
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308105 /* Here, passing Arg2 as 0 because we want to change the
8106 last 3 bytes (means non OUI bytes) of all the interfaces
8107 mac addr.
8108 */
8109 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8110 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008111 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308112 hddLog(VOS_TRACE_LEVEL_ERROR,
8113 "%s: Failed to generate wlan interface mac addr "
8114 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8115 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008116 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 }
8118 else
8119#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8120 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008121 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008122 "%s: Invalid MAC address in NV, using MAC from ini file "
8123 MAC_ADDRESS_STR, __func__,
8124 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8125 }
8126 }
8127 {
8128 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308129
8130 /* Set the MAC Address Currently this is used by HAL to
8131 * add self sta. Remove this once self sta is added as
8132 * part of session open.
8133 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008134 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8135 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8136 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308137
Jeff Johnson295189b2012-06-20 16:38:30 -07008138 if (!HAL_STATUS_SUCCESS( halStatus ))
8139 {
8140 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8141 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08008142 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 }
8144 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008145
8146 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8147 Note: Firmware image will be read and downloaded inside vos_start API */
8148 status = vos_start( pHddCtx->pvosContext );
8149 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8150 {
8151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
8152 goto err_vosclose;
8153 }
8154
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008155 /* Exchange capability info between Host and FW and also get versioning info from FW */
8156 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008157
8158 status = hdd_post_voss_start_config( pHddCtx );
8159 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8160 {
8161 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8162 __func__);
8163 goto err_vosstop;
8164 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008165
8166#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308167 wlan_hdd_cfg80211_update_reg_info( wiphy );
8168
8169 /* registration of wiphy dev with cfg80211 */
8170 if (0 > wlan_hdd_cfg80211_register(wiphy))
8171 {
8172 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8173 goto err_vosstop;
8174 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008175#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008176
Jeff Johnson295189b2012-06-20 16:38:30 -07008177 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8178 {
8179 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8180 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8181 }
8182 else
8183 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008184 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8185 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8186 if (pAdapter != NULL)
8187 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308188 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008189 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308190 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8191 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8192 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008193
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308194 /* Generate the P2P Device Address. This consists of the device's
8195 * primary MAC address with the locally administered bit set.
8196 */
8197 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008198 }
8199 else
8200 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308201 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8202 if (p2p_dev_addr != NULL)
8203 {
8204 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8205 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8206 }
8207 else
8208 {
8209 hddLog(VOS_TRACE_LEVEL_FATAL,
8210 "%s: Failed to allocate mac_address for p2p_device",
8211 __func__);
8212 goto err_close_adapter;
8213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008215
8216 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8217 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8218 if ( NULL == pP2pAdapter )
8219 {
8220 hddLog(VOS_TRACE_LEVEL_FATAL,
8221 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008222 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008223 goto err_close_adapter;
8224 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008225 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008226 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008227
8228 if( pAdapter == NULL )
8229 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008230 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8231 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008232 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008233
Arif Hussain66559122013-11-21 10:11:40 -08008234 if (country_code)
8235 {
8236 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008237 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008238 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8239#ifndef CONFIG_ENABLE_LINUX_REG
8240 hdd_checkandupdate_phymode(pAdapter, country_code);
8241#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008242 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8243 (void *)(tSmeChangeCountryCallback)
8244 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008245 country_code,
8246 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308247 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008248 if (eHAL_STATUS_SUCCESS == ret)
8249 {
Arif Hussaincb607082013-12-20 11:57:42 -08008250 ret = wait_for_completion_interruptible_timeout(
8251 &pAdapter->change_country_code,
8252 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8253
8254 if (0 >= ret)
8255 {
8256 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8257 "%s: SME while setting country code timed out", __func__);
8258 }
Arif Hussain66559122013-11-21 10:11:40 -08008259 }
8260 else
8261 {
Arif Hussaincb607082013-12-20 11:57:42 -08008262 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8263 "%s: SME Change Country code from module param fail ret=%d",
8264 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008265 }
8266 }
8267
Jeff Johnson295189b2012-06-20 16:38:30 -07008268#ifdef WLAN_BTAMP_FEATURE
8269 vStatus = WLANBAP_Open(pVosContext);
8270 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8271 {
8272 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8273 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008274 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008275 }
8276
8277 vStatus = BSL_Init(pVosContext);
8278 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8279 {
8280 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8281 "%s: Failed to Init BSL",__func__);
8282 goto err_bap_close;
8283 }
8284 vStatus = WLANBAP_Start(pVosContext);
8285 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8286 {
8287 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8288 "%s: Failed to start TL",__func__);
8289 goto err_bap_close;
8290 }
8291
8292 pConfig = pHddCtx->cfg_ini;
8293 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8294 status = WLANBAP_SetConfig(&btAmpConfig);
8295
8296#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008297
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008298#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8299 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8300 {
8301 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8302 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8303 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8304 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8305 }
8306#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008307#ifdef FEATURE_WLAN_SCAN_PNO
8308 /*SME must send channel update configuration to RIVA*/
8309 sme_UpdateChannelConfig(pHddCtx->hHal);
8310#endif
8311
Jeff Johnson295189b2012-06-20 16:38:30 -07008312 /* Register with platform driver as client for Suspend/Resume */
8313 status = hddRegisterPmOps(pHddCtx);
8314 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8315 {
8316 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8317#ifdef WLAN_BTAMP_FEATURE
8318 goto err_bap_stop;
8319#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008320 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008321#endif //WLAN_BTAMP_FEATURE
8322 }
8323
Yue Ma0d4891e2013-08-06 17:01:45 -07008324 /* Open debugfs interface */
8325 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8326 {
8327 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8328 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008329 }
8330
Jeff Johnson295189b2012-06-20 16:38:30 -07008331 /* Register TM level change handler function to the platform */
8332 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8333 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8334 {
8335 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8336 goto err_unregister_pmops;
8337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008338
8339 /* register for riva power on lock to platform driver */
8340 if (req_riva_power_on_lock("wlan"))
8341 {
8342 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8343 __func__);
8344 goto err_unregister_pmops;
8345 }
8346
Jeff Johnson295189b2012-06-20 16:38:30 -07008347 // register net device notifier for device change notification
8348 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8349
8350 if(ret < 0)
8351 {
8352 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8353 goto err_free_power_on_lock;
8354 }
8355
8356 //Initialize the nlink service
8357 if(nl_srv_init() != 0)
8358 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308359 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008360 goto err_reg_netdev;
8361 }
8362
Leo Chang4ce1cc52013-10-21 18:27:15 -07008363#ifdef WLAN_KD_READY_NOTIFIER
8364 pHddCtx->kd_nl_init = 1;
8365#endif /* WLAN_KD_READY_NOTIFIER */
8366
Jeff Johnson295189b2012-06-20 16:38:30 -07008367 //Initialize the BTC service
8368 if(btc_activate_service(pHddCtx) != 0)
8369 {
8370 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8371 goto err_nl_srv;
8372 }
8373
8374#ifdef PTT_SOCK_SVC_ENABLE
8375 //Initialize the PTT service
8376 if(ptt_sock_activate_svc(pHddCtx) != 0)
8377 {
8378 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8379 goto err_nl_srv;
8380 }
8381#endif
8382
Jeff Johnson295189b2012-06-20 16:38:30 -07008383 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008384 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008385 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008386 /* Action frame registered in one adapter which will
8387 * applicable to all interfaces
8388 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008389 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008390 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008391
8392 mutex_init(&pHddCtx->sap_lock);
8393
8394 pHddCtx->isLoadUnloadInProgress = FALSE;
8395
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008396#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008397#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8398 /* Initialize the wake lcok */
8399 wake_lock_init(&pHddCtx->rx_wake_lock,
8400 WAKE_LOCK_SUSPEND,
8401 "qcom_rx_wakelock");
8402#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008403 /* Initialize the wake lcok */
8404 wake_lock_init(&pHddCtx->sap_wake_lock,
8405 WAKE_LOCK_SUSPEND,
8406 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008407#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008408
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008409 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8410 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008411
8412 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8413 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308414#ifndef CONFIG_ENABLE_LINUX_REG
8415 /*updating wiphy so that regulatory user hints can be processed*/
8416 if (wiphy)
8417 {
8418 regulatory_hint(wiphy, "00");
8419 }
8420#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008421 // Initialize the restart logic
8422 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308423
Leo Chang0b0e45a2013-12-15 15:18:55 -08008424#ifdef FEATURE_WLAN_CH_AVOID
8425 /* Plug in avoid channel notification callback */
8426 sme_AddChAvoidCallback(pHddCtx->hHal,
8427 hdd_hostapd_ch_avoid_cb);
8428#endif /* FEATURE_WLAN_CH_AVOID */
8429
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008430 //Register the traffic monitor timer now
8431 if ( pHddCtx->cfg_ini->dynSplitscan)
8432 {
8433 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8434 VOS_TIMER_TYPE_SW,
8435 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8436 (void *)pHddCtx);
8437 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008438 goto success;
8439
8440err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008441#ifdef WLAN_KD_READY_NOTIFIER
8442 nl_srv_exit(pHddCtx->ptt_pid);
8443#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008444 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008445#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008446err_reg_netdev:
8447 unregister_netdevice_notifier(&hdd_netdev_notifier);
8448
8449err_free_power_on_lock:
8450 free_riva_power_on_lock("wlan");
8451
8452err_unregister_pmops:
8453 hddDevTmUnregisterNotifyCallback(pHddCtx);
8454 hddDeregisterPmOps(pHddCtx);
8455
Yue Ma0d4891e2013-08-06 17:01:45 -07008456 hdd_debugfs_exit(pHddCtx);
8457
Jeff Johnson295189b2012-06-20 16:38:30 -07008458#ifdef WLAN_BTAMP_FEATURE
8459err_bap_stop:
8460 WLANBAP_Stop(pVosContext);
8461#endif
8462
8463#ifdef WLAN_BTAMP_FEATURE
8464err_bap_close:
8465 WLANBAP_Close(pVosContext);
8466#endif
8467
Jeff Johnson295189b2012-06-20 16:38:30 -07008468err_close_adapter:
8469 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008470
8471#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308472 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008473#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008474
8475err_vosstop:
8476 vos_stop(pVosContext);
8477
Amar Singhala49cbc52013-10-08 18:37:44 -07008478err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008479 status = vos_sched_close( pVosContext );
8480 if (!VOS_IS_STATUS_SUCCESS(status)) {
8481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8482 "%s: Failed to close VOSS Scheduler", __func__);
8483 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8484 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008485 vos_close(pVosContext );
8486
8487err_wiphy_unregister:
8488
8489#ifdef CONFIG_ENABLE_LINUX_REG
8490 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008491
Amar Singhal0a402232013-10-11 20:57:16 -07008492err_vos_nv_close:
8493
8494 vos_nv_close();
8495
Jeff Johnson295189b2012-06-20 16:38:30 -07008496err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008497#endif
8498
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008499 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008500
8501err_wdclose:
8502 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8503 vos_watchdog_close(pVosContext);
8504
Jeff Johnson295189b2012-06-20 16:38:30 -07008505err_config:
8506 kfree(pHddCtx->cfg_ini);
8507 pHddCtx->cfg_ini= NULL;
8508
8509err_free_hdd_context:
8510 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008511 wiphy_free(wiphy) ;
8512 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008513 VOS_BUG(1);
8514
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008515 if (hdd_is_ssr_required())
8516 {
8517 /* WDI timeout had happened during load, so SSR is needed here */
8518 subsystem_restart("wcnss");
8519 msleep(5000);
8520 }
8521 hdd_set_ssr_required (VOS_FALSE);
8522
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008523 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008524
8525success:
8526 EXIT();
8527 return 0;
8528}
8529
8530/**---------------------------------------------------------------------------
8531
Jeff Johnson32d95a32012-09-10 13:15:23 -07008532 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008533
Jeff Johnson32d95a32012-09-10 13:15:23 -07008534 This is the driver entry point - called in different timeline depending
8535 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008536
8537 \param - None
8538
8539 \return - 0 for success, non zero for failure
8540
8541 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008542static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008543{
8544 VOS_STATUS status;
8545 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 struct device *dev = NULL;
8547 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008548#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8549 int max_retries = 0;
8550#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008551
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308552#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8553 vos_wconn_trace_init();
8554#endif
8555
Jeff Johnson295189b2012-06-20 16:38:30 -07008556 ENTER();
8557
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008558#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008559 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008560#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008561
8562 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8563 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8564
8565 //Power Up Libra WLAN card first if not already powered up
8566 status = vos_chipPowerUp(NULL,NULL,NULL);
8567 if (!VOS_IS_STATUS_SUCCESS(status))
8568 {
8569 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8570 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308571#ifdef WLAN_OPEN_SOURCE
8572 wake_lock_destroy(&wlan_wake_lock);
8573#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008574 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008575 }
8576
Jeff Johnson295189b2012-06-20 16:38:30 -07008577#ifdef ANI_BUS_TYPE_PCI
8578
8579 dev = wcnss_wlan_get_device();
8580
8581#endif // ANI_BUS_TYPE_PCI
8582
8583#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008584
8585#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8586 /* wait until WCNSS driver downloads NV */
8587 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8588 msleep(1000);
8589 }
8590 if (max_retries >= 5) {
8591 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308592#ifdef WLAN_OPEN_SOURCE
8593 wake_lock_destroy(&wlan_wake_lock);
8594#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008595 return -ENODEV;
8596 }
8597#endif
8598
Jeff Johnson295189b2012-06-20 16:38:30 -07008599 dev = wcnss_wlan_get_device();
8600#endif // ANI_BUS_TYPE_PLATFORM
8601
8602
8603 do {
8604 if (NULL == dev) {
8605 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8606 ret_status = -1;
8607 break;
8608 }
8609
Jeff Johnson295189b2012-06-20 16:38:30 -07008610#ifdef TIMER_MANAGER
8611 vos_timer_manager_init();
8612#endif
8613
8614 /* Preopen VOSS so that it is ready to start at least SAL */
8615 status = vos_preOpen(&pVosContext);
8616
8617 if (!VOS_IS_STATUS_SUCCESS(status))
8618 {
8619 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8620 ret_status = -1;
8621 break;
8622 }
8623
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008624#ifndef MODULE
8625 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8626 */
8627 hdd_set_conparam((v_UINT_t)con_mode);
8628#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008629
8630 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008631 if (hdd_wlan_startup(dev))
8632 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008634 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008635 vos_preClose( &pVosContext );
8636 ret_status = -1;
8637 break;
8638 }
8639
8640 /* Cancel the vote for XO Core ON
8641 * This is done here for safety purposes in case we re-initialize without turning
8642 * it OFF in any error scenario.
8643 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008644 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008645 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008646 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008647 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8648 {
8649 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008650 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008651 }
8652 } while (0);
8653
8654 if (0 != ret_status)
8655 {
8656 //Assert Deep sleep signal now to put Libra HW in lowest power state
8657 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8658 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8659
8660 //Vote off any PMIC voltage supplies
8661 vos_chipPowerDown(NULL, NULL, NULL);
8662#ifdef TIMER_MANAGER
8663 vos_timer_exit();
8664#endif
8665#ifdef MEMORY_DEBUG
8666 vos_mem_exit();
8667#endif
8668
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008669#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008670 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008671#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8673 }
8674 else
8675 {
8676 //Send WLAN UP indication to Nlink Service
8677 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8678
8679 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008680 }
8681
8682 EXIT();
8683
8684 return ret_status;
8685}
8686
Jeff Johnson32d95a32012-09-10 13:15:23 -07008687/**---------------------------------------------------------------------------
8688
8689 \brief hdd_module_init() - Init Function
8690
8691 This is the driver entry point (invoked when module is loaded using insmod)
8692
8693 \param - None
8694
8695 \return - 0 for success, non zero for failure
8696
8697 --------------------------------------------------------------------------*/
8698#ifdef MODULE
8699static int __init hdd_module_init ( void)
8700{
8701 return hdd_driver_init();
8702}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008703#else /* #ifdef MODULE */
8704static int __init hdd_module_init ( void)
8705{
8706 /* Driver initialization is delayed to fwpath_changed_handler */
8707 return 0;
8708}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008709#endif /* #ifdef MODULE */
8710
Jeff Johnson295189b2012-06-20 16:38:30 -07008711
8712/**---------------------------------------------------------------------------
8713
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008714 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008715
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008716 This is the driver exit point (invoked when module is unloaded using rmmod
8717 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008718
8719 \param - None
8720
8721 \return - None
8722
8723 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008724static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008725{
8726 hdd_context_t *pHddCtx = NULL;
8727 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008728 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008729
8730 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8731
8732 //Get the global vos context
8733 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8734
8735 if(!pVosContext)
8736 {
8737 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8738 goto done;
8739 }
8740
8741 //Get the HDD context.
8742 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8743
8744 if(!pHddCtx)
8745 {
8746 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8747 }
8748 else
8749 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008750 while(isWDresetInProgress()) {
8751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8752 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008753 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008754
8755 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8756 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8757 "%s:SSR never completed, fatal error", __func__);
8758 VOS_BUG(0);
8759 }
8760 }
8761
Jeff Johnson295189b2012-06-20 16:38:30 -07008762
8763 pHddCtx->isLoadUnloadInProgress = TRUE;
8764 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8765
8766 //Do all the cleanup before deregistering the driver
8767 hdd_wlan_exit(pHddCtx);
8768 }
8769
Jeff Johnson295189b2012-06-20 16:38:30 -07008770 vos_preClose( &pVosContext );
8771
8772#ifdef TIMER_MANAGER
8773 vos_timer_exit();
8774#endif
8775#ifdef MEMORY_DEBUG
8776 vos_mem_exit();
8777#endif
8778
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308779#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8780 vos_wconn_trace_exit();
8781#endif
8782
Jeff Johnson295189b2012-06-20 16:38:30 -07008783done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008784#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008785 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008787 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8788}
8789
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008790/**---------------------------------------------------------------------------
8791
8792 \brief hdd_module_exit() - Exit function
8793
8794 This is the driver exit point (invoked when module is unloaded using rmmod)
8795
8796 \param - None
8797
8798 \return - None
8799
8800 --------------------------------------------------------------------------*/
8801static void __exit hdd_module_exit(void)
8802{
8803 hdd_driver_exit();
8804}
8805
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008806#ifdef MODULE
8807static int fwpath_changed_handler(const char *kmessage,
8808 struct kernel_param *kp)
8809{
Jeff Johnson76052702013-04-16 13:55:05 -07008810 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008811}
8812
8813static int con_mode_handler(const char *kmessage,
8814 struct kernel_param *kp)
8815{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008816 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008817}
8818#else /* #ifdef MODULE */
8819/**---------------------------------------------------------------------------
8820
Jeff Johnson76052702013-04-16 13:55:05 -07008821 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008822
Jeff Johnson76052702013-04-16 13:55:05 -07008823 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008824 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008825 - invoked when module parameter fwpath is modified from userspace to signal
8826 initializing the WLAN driver or when con_mode is modified from userspace
8827 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008828
8829 \return - 0 for success, non zero for failure
8830
8831 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008832static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008833{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008834 int ret_status;
8835
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008836 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008837 ret_status = hdd_driver_init();
8838 wlan_hdd_inited = ret_status ? 0 : 1;
8839 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008840 }
8841
8842 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008843
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008844 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008845
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008846 ret_status = hdd_driver_init();
8847 wlan_hdd_inited = ret_status ? 0 : 1;
8848 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008849}
8850
Jeff Johnson295189b2012-06-20 16:38:30 -07008851/**---------------------------------------------------------------------------
8852
Jeff Johnson76052702013-04-16 13:55:05 -07008853 \brief fwpath_changed_handler() - Handler Function
8854
8855 Handle changes to the fwpath parameter
8856
8857 \return - 0 for success, non zero for failure
8858
8859 --------------------------------------------------------------------------*/
8860static int fwpath_changed_handler(const char *kmessage,
8861 struct kernel_param *kp)
8862{
8863 int ret;
8864
8865 ret = param_set_copystring(kmessage, kp);
8866 if (0 == ret)
8867 ret = kickstart_driver();
8868 return ret;
8869}
8870
8871/**---------------------------------------------------------------------------
8872
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008873 \brief con_mode_handler() -
8874
8875 Handler function for module param con_mode when it is changed by userspace
8876 Dynamically linked - do nothing
8877 Statically linked - exit and init driver, as in rmmod and insmod
8878
Jeff Johnson76052702013-04-16 13:55:05 -07008879 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008880
Jeff Johnson76052702013-04-16 13:55:05 -07008881 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008882
8883 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008884static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008885{
Jeff Johnson76052702013-04-16 13:55:05 -07008886 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008887
Jeff Johnson76052702013-04-16 13:55:05 -07008888 ret = param_set_int(kmessage, kp);
8889 if (0 == ret)
8890 ret = kickstart_driver();
8891 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008892}
8893#endif /* #ifdef MODULE */
8894
8895/**---------------------------------------------------------------------------
8896
Jeff Johnson295189b2012-06-20 16:38:30 -07008897 \brief hdd_get_conparam() -
8898
8899 This is the driver exit point (invoked when module is unloaded using rmmod)
8900
8901 \param - None
8902
8903 \return - tVOS_CON_MODE
8904
8905 --------------------------------------------------------------------------*/
8906tVOS_CON_MODE hdd_get_conparam ( void )
8907{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008908#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008909 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008910#else
8911 return (tVOS_CON_MODE)curr_con_mode;
8912#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008913}
8914void hdd_set_conparam ( v_UINT_t newParam )
8915{
8916 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008917#ifndef MODULE
8918 curr_con_mode = con_mode;
8919#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008920}
8921/**---------------------------------------------------------------------------
8922
8923 \brief hdd_softap_sta_deauth() - function
8924
8925 This to take counter measure to handle deauth req from HDD
8926
8927 \param - pAdapter - Pointer to the HDD
8928
8929 \param - enable - boolean value
8930
8931 \return - None
8932
8933 --------------------------------------------------------------------------*/
8934
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008935VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008936{
Jeff Johnson295189b2012-06-20 16:38:30 -07008937 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008938 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008939
8940 ENTER();
8941
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008942 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8943 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008944
8945 //Ignore request to deauth bcmc station
8946 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008947 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008948
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008949 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008950
8951 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008952 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008953}
8954
8955/**---------------------------------------------------------------------------
8956
8957 \brief hdd_softap_sta_disassoc() - function
8958
8959 This to take counter measure to handle deauth req from HDD
8960
8961 \param - pAdapter - Pointer to the HDD
8962
8963 \param - enable - boolean value
8964
8965 \return - None
8966
8967 --------------------------------------------------------------------------*/
8968
8969void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8970{
8971 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8972
8973 ENTER();
8974
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308975 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008976
8977 //Ignore request to disassoc bcmc station
8978 if( pDestMacAddress[0] & 0x1 )
8979 return;
8980
8981 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8982}
8983
8984void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8985{
8986 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8987
8988 ENTER();
8989
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308990 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008991
8992 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8993}
8994
Jeff Johnson295189b2012-06-20 16:38:30 -07008995/**---------------------------------------------------------------------------
8996 *
8997 * \brief hdd_get__concurrency_mode() -
8998 *
8999 *
9000 * \param - None
9001 *
9002 * \return - CONCURRENCY MODE
9003 *
9004 * --------------------------------------------------------------------------*/
9005tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9006{
9007 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9008 hdd_context_t *pHddCtx;
9009
9010 if (NULL != pVosContext)
9011 {
9012 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9013 if (NULL != pHddCtx)
9014 {
9015 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9016 }
9017 }
9018
9019 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009020 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009021 return VOS_STA;
9022}
9023
9024/* Decide whether to allow/not the apps power collapse.
9025 * Allow apps power collapse if we are in connected state.
9026 * if not, allow only if we are in IMPS */
9027v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9028{
9029 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009030 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009031 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009032 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9033 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9034 hdd_adapter_t *pAdapter = NULL;
9035 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009036 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009037
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9039 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009040
Yathish9f22e662012-12-10 14:21:35 -08009041 concurrent_state = hdd_get_concurrency_mode();
9042
9043#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9044 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9045 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9046 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9047 return TRUE;
9048#endif
9049
Jeff Johnson295189b2012-06-20 16:38:30 -07009050 /*loop through all adapters. TBD fix for Concurrency */
9051 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9052 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9053 {
9054 pAdapter = pAdapterNode->pAdapter;
9055 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9056 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9057 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009058 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009059 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009060 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009061 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9062 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009063 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009064 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009065 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9066 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009067 return FALSE;
9068 }
9069 }
9070 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9071 pAdapterNode = pNext;
9072 }
9073 return TRUE;
9074}
9075
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009076/* Decides whether to send suspend notification to Riva
9077 * if any adapter is in BMPS; then it is required */
9078v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9079{
9080 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9081 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9082
9083 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9084 {
9085 return TRUE;
9086 }
9087 return FALSE;
9088}
9089
Jeff Johnson295189b2012-06-20 16:38:30 -07009090void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9091{
9092 switch(mode)
9093 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009094 case VOS_STA_MODE:
9095 case VOS_P2P_CLIENT_MODE:
9096 case VOS_P2P_GO_MODE:
9097 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009098 pHddCtx->concurrency_mode |= (1 << mode);
9099 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009100 break;
9101 default:
9102 break;
9103
9104 }
9105 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9106 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9107}
9108
9109
9110void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9111{
9112 switch(mode)
9113 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009114 case VOS_STA_MODE:
9115 case VOS_P2P_CLIENT_MODE:
9116 case VOS_P2P_GO_MODE:
9117 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009118 pHddCtx->no_of_sessions[mode]--;
9119 if (!(pHddCtx->no_of_sessions[mode]))
9120 pHddCtx->concurrency_mode &= (~(1 << mode));
9121 break;
9122 default:
9123 break;
9124 }
9125 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9126 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9127}
9128
Jeff Johnsone7245742012-09-05 17:12:55 -07009129/**---------------------------------------------------------------------------
9130 *
9131 * \brief wlan_hdd_restart_init
9132 *
9133 * This function initalizes restart timer/flag. An internal function.
9134 *
9135 * \param - pHddCtx
9136 *
9137 * \return - None
9138 *
9139 * --------------------------------------------------------------------------*/
9140
9141static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9142{
9143 /* Initialize */
9144 pHddCtx->hdd_restart_retries = 0;
9145 atomic_set(&pHddCtx->isRestartInProgress, 0);
9146 vos_timer_init(&pHddCtx->hdd_restart_timer,
9147 VOS_TIMER_TYPE_SW,
9148 wlan_hdd_restart_timer_cb,
9149 pHddCtx);
9150}
9151/**---------------------------------------------------------------------------
9152 *
9153 * \brief wlan_hdd_restart_deinit
9154 *
9155 * This function cleans up the resources used. An internal function.
9156 *
9157 * \param - pHddCtx
9158 *
9159 * \return - None
9160 *
9161 * --------------------------------------------------------------------------*/
9162
9163static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9164{
9165
9166 VOS_STATUS vos_status;
9167 /* Block any further calls */
9168 atomic_set(&pHddCtx->isRestartInProgress, 1);
9169 /* Cleanup */
9170 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9171 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009172 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009173 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9174 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009175 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009176
9177}
9178
9179/**---------------------------------------------------------------------------
9180 *
9181 * \brief wlan_hdd_framework_restart
9182 *
9183 * This function uses a cfg80211 API to start a framework initiated WLAN
9184 * driver module unload/load.
9185 *
9186 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9187 *
9188 *
9189 * \param - pHddCtx
9190 *
9191 * \return - VOS_STATUS_SUCCESS: Success
9192 * VOS_STATUS_E_EMPTY: Adapter is Empty
9193 * VOS_STATUS_E_NOMEM: No memory
9194
9195 * --------------------------------------------------------------------------*/
9196
9197static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9198{
9199 VOS_STATUS status = VOS_STATUS_SUCCESS;
9200 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009201 int len = (sizeof (struct ieee80211_mgmt));
9202 struct ieee80211_mgmt *mgmt = NULL;
9203
9204 /* Prepare the DEAUTH managment frame with reason code */
9205 mgmt = kzalloc(len, GFP_KERNEL);
9206 if(mgmt == NULL)
9207 {
9208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9209 "%s: memory allocation failed (%d bytes)", __func__, len);
9210 return VOS_STATUS_E_NOMEM;
9211 }
9212 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009213
9214 /* Iterate over all adapters/devices */
9215 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9216 do
9217 {
9218 if( (status == VOS_STATUS_SUCCESS) &&
9219 pAdapterNode &&
9220 pAdapterNode->pAdapter)
9221 {
9222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9223 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9224 pAdapterNode->pAdapter->dev->name,
9225 pAdapterNode->pAdapter->device_mode,
9226 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009227 /*
9228 * CFG80211 event to restart the driver
9229 *
9230 * 'cfg80211_send_unprot_deauth' sends a
9231 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9232 * of SME(Linux Kernel) state machine.
9233 *
9234 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9235 * the driver.
9236 *
9237 */
9238
9239 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009240 }
9241 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9242 pAdapterNode = pNext;
9243 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9244
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009245
9246 /* Free the allocated management frame */
9247 kfree(mgmt);
9248
Jeff Johnsone7245742012-09-05 17:12:55 -07009249 /* Retry until we unload or reach max count */
9250 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9251 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9252
9253 return status;
9254
9255}
9256/**---------------------------------------------------------------------------
9257 *
9258 * \brief wlan_hdd_restart_timer_cb
9259 *
9260 * Restart timer callback. An internal function.
9261 *
9262 * \param - User data:
9263 *
9264 * \return - None
9265 *
9266 * --------------------------------------------------------------------------*/
9267
9268void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9269{
9270 hdd_context_t *pHddCtx = usrDataForCallback;
9271 wlan_hdd_framework_restart(pHddCtx);
9272 return;
9273
9274}
9275
9276
9277/**---------------------------------------------------------------------------
9278 *
9279 * \brief wlan_hdd_restart_driver
9280 *
9281 * This function sends an event to supplicant to restart the WLAN driver.
9282 *
9283 * This function is called from vos_wlanRestart.
9284 *
9285 * \param - pHddCtx
9286 *
9287 * \return - VOS_STATUS_SUCCESS: Success
9288 * VOS_STATUS_E_EMPTY: Adapter is Empty
9289 * VOS_STATUS_E_ALREADY: Request already in progress
9290
9291 * --------------------------------------------------------------------------*/
9292VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9293{
9294 VOS_STATUS status = VOS_STATUS_SUCCESS;
9295
9296 /* A tight check to make sure reentrancy */
9297 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9298 {
9299 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9300 "%s: WLAN restart is already in progress", __func__);
9301
9302 return VOS_STATUS_E_ALREADY;
9303 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009304 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009305#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009306 wcnss_reset_intr();
9307#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009308
Jeff Johnsone7245742012-09-05 17:12:55 -07009309 return status;
9310}
9311
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009312/*
9313 * API to find if there is any STA or P2P-Client is connected
9314 */
9315VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9316{
9317 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9318}
Jeff Johnsone7245742012-09-05 17:12:55 -07009319
Jeff Johnson295189b2012-06-20 16:38:30 -07009320//Register the module init/exit functions
9321module_init(hdd_module_init);
9322module_exit(hdd_module_exit);
9323
9324MODULE_LICENSE("Dual BSD/GPL");
9325MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9326MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9327
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009328module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9329 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009330
Jeff Johnson76052702013-04-16 13:55:05 -07009331module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009332 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009333
9334module_param(enable_dfs_chan_scan, int,
9335 S_IRUSR | S_IRGRP | S_IROTH);
9336
9337module_param(enable_11d, int,
9338 S_IRUSR | S_IRGRP | S_IROTH);
9339
9340module_param(country_code, charp,
9341 S_IRUSR | S_IRGRP | S_IROTH);