blob: a7dded4054ef3339e428d3e660b036f276a54894 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
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
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700192/*
193 * Driver miracast parameters 0-Disabled
194 * 1-Source, 2-Sink
195 */
196#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
197#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
198
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800199#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700200static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700201#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700202/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700203static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700204
205//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700206static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
207static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
208static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
209void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800210void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700211
Jeff Johnson295189b2012-06-20 16:38:30 -0700212v_U16_t hdd_select_queue(struct net_device *dev,
213 struct sk_buff *skb);
214
215#ifdef WLAN_FEATURE_PACKET_FILTERING
216static void hdd_set_multicast_list(struct net_device *dev);
217#endif
218
219void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700220int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700221
222extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700223
Srinivas Girigowdade697412013-02-14 16:31:48 -0800224#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
225void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
226static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700227static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
228 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
229 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700230static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
231 tANI_U8 *pTargetApBssid,
232 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800233#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700234#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
235VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
236#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
237
Jeff Johnson295189b2012-06-20 16:38:30 -0700238static int hdd_netdev_notifier_call(struct notifier_block * nb,
239 unsigned long state,
240 void *ndev)
241{
242 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700243 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700244 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700245#ifdef WLAN_BTAMP_FEATURE
246 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700247#endif
248
249 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700250 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700251 (strncmp(dev->name, "p2p", 3)))
252 return NOTIFY_DONE;
253
254 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 return NOTIFY_DONE;
256
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700258 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700259
Jeff Johnson27cee452013-03-27 11:10:24 -0700260 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800262 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 VOS_ASSERT(0);
264 return NOTIFY_DONE;
265 }
266
Jeff Johnson27cee452013-03-27 11:10:24 -0700267 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
268 if (NULL == pHddCtx)
269 {
270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
271 VOS_ASSERT(0);
272 return NOTIFY_DONE;
273 }
274
275 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
276 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277
278 switch (state) {
279 case NETDEV_REGISTER:
280 break;
281
282 case NETDEV_UNREGISTER:
283 break;
284
285 case NETDEV_UP:
286 break;
287
288 case NETDEV_DOWN:
289 break;
290
291 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700292 if(TRUE == pAdapter->isLinkUpSvcNeeded)
293 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 break;
295
296 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700297 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 {
299 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800300 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530301 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700302 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800303 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
305 if(!result)
306 {
307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800308 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700309 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311 }
312 else
313 {
314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700315 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700316 }
317#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 status = WLANBAP_StopAmp();
320 if(VOS_STATUS_SUCCESS != status )
321 {
322 pHddCtx->isAmpAllowed = VOS_TRUE;
323 hddLog(VOS_TRACE_LEVEL_FATAL,
324 "%s: Failed to stop AMP", __func__);
325 }
326 else
327 {
328 //a state m/c implementation in PAL is TBD to avoid this delay
329 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700330 if ( pHddCtx->isAmpAllowed )
331 {
332 WLANBAP_DeregisterFromHCI();
333 pHddCtx->isAmpAllowed = VOS_FALSE;
334 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 }
336#endif //WLAN_BTAMP_FEATURE
337 break;
338
339 default:
340 break;
341 }
342
343 return NOTIFY_DONE;
344}
345
346struct notifier_block hdd_netdev_notifier = {
347 .notifier_call = hdd_netdev_notifier_call,
348};
349
350/*---------------------------------------------------------------------------
351 * Function definitions
352 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700353void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
354void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700355//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700356static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700357#ifndef MODULE
358/* current con_mode - used only for statically linked driver
359 * con_mode is changed by userspace to indicate a mode change which will
360 * result in calling the module exit and init functions. The module
361 * exit function will clean up based on the value of con_mode prior to it
362 * being changed by userspace. So curr_con_mode records the current con_mode
363 * for exit when con_mode becomes the next mode for init
364 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700365static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700366#endif
367
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800368/**---------------------------------------------------------------------------
369
370 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
371
372 Called immediately after the cfg.ini is read in order to configure
373 the desired trace levels.
374
375 \param - moduleId - module whose trace level is being configured
376 \param - bitmask - bitmask of log levels to be enabled
377
378 \return - void
379
380 --------------------------------------------------------------------------*/
381static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
382{
383 wpt_tracelevel level;
384
385 /* if the bitmask is the default value, then a bitmask was not
386 specified in cfg.ini, so leave the logging level alone (it
387 will remain at the "compiled in" default value) */
388 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
389 {
390 return;
391 }
392
393 /* a mask was specified. start by disabling all logging */
394 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
395
396 /* now cycle through the bitmask until all "set" bits are serviced */
397 level = VOS_TRACE_LEVEL_FATAL;
398 while (0 != bitmask)
399 {
400 if (bitmask & 1)
401 {
402 vos_trace_setValue(moduleId, level, 1);
403 }
404 level++;
405 bitmask >>= 1;
406 }
407}
408
409
Jeff Johnson295189b2012-06-20 16:38:30 -0700410/**---------------------------------------------------------------------------
411
412 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
413
414 Called immediately after the cfg.ini is read in order to configure
415 the desired trace levels in the WDI.
416
417 \param - moduleId - module whose trace level is being configured
418 \param - bitmask - bitmask of log levels to be enabled
419
420 \return - void
421
422 --------------------------------------------------------------------------*/
423static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
424{
425 wpt_tracelevel level;
426
427 /* if the bitmask is the default value, then a bitmask was not
428 specified in cfg.ini, so leave the logging level alone (it
429 will remain at the "compiled in" default value) */
430 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
431 {
432 return;
433 }
434
435 /* a mask was specified. start by disabling all logging */
436 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
437
438 /* now cycle through the bitmask until all "set" bits are serviced */
439 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
440 while (0 != bitmask)
441 {
442 if (bitmask & 1)
443 {
444 wpalTraceSetLevel(moduleId, level, 1);
445 }
446 level++;
447 bitmask >>= 1;
448 }
449}
Jeff Johnson295189b2012-06-20 16:38:30 -0700450
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530451/*
452 * FUNCTION: wlan_hdd_validate_context
453 * This function is used to check the HDD context
454 */
455int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
456{
457 ENTER();
458
459 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
460 {
461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
462 "%s: HDD context is Null", __func__);
463 return -ENODEV;
464 }
465
466 if (pHddCtx->isLogpInProgress)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
469 "%s: LOGP in Progress. Ignore!!!", __func__);
470 return -EAGAIN;
471 }
472
473 if (pHddCtx->isLoadUnloadInProgress)
474 {
475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
476 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
477 return -EAGAIN;
478 }
479 return 0;
480}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700481#ifdef CONFIG_ENABLE_LINUX_REG
482void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
483{
484 hdd_adapter_t *pAdapter = NULL;
485 hdd_station_ctx_t *pHddStaCtx = NULL;
486 eCsrPhyMode phyMode;
487 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530488
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700489 if (NULL == pHddCtx)
490 {
491 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
492 "HDD Context is null !!");
493 return ;
494 }
495
496 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
497 if (NULL == pAdapter)
498 {
499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
500 "pAdapter is null !!");
501 return ;
502 }
503
504 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
505 if (NULL == pHddStaCtx)
506 {
507 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
508 "pHddStaCtx is null !!");
509 return ;
510 }
511
512 cfg_param = pHddCtx->cfg_ini;
513 if (NULL == cfg_param)
514 {
515 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
516 "cfg_params not available !!");
517 return ;
518 }
519
520 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
521
522 if (!pHddCtx->isVHT80Allowed)
523 {
524 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
525 (eCSR_DOT11_MODE_11ac == phyMode) ||
526 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
527 {
528 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
529 "Setting phymode to 11n!!");
530 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
531 }
532 }
533 else
534 {
535 /*New country Supports 11ac as well resetting value back from .ini*/
536 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
537 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
538 return ;
539 }
540
541 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
542 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
543 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
544 {
545 VOS_STATUS vosStatus;
546
547 // need to issue a disconnect to CSR.
548 INIT_COMPLETION(pAdapter->disconnect_comp_var);
549 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
550 pAdapter->sessionId,
551 eCSR_DISCONNECT_REASON_UNSPECIFIED );
552
553 if (VOS_STATUS_SUCCESS == vosStatus)
554 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
555 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
556
557 }
558}
559#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530560void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
561{
562 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
563 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
564 hdd_config_t *cfg_param;
565 eCsrPhyMode phyMode;
566
567 if (NULL == pHddCtx)
568 {
569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
570 "HDD Context is null !!");
571 return ;
572 }
573
574 cfg_param = pHddCtx->cfg_ini;
575
576 if (NULL == cfg_param)
577 {
578 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
579 "cfg_params not available !!");
580 return ;
581 }
582
583 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
584
585 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
586 {
587 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
588 (eCSR_DOT11_MODE_11ac == phyMode) ||
589 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
590 {
591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
592 "Setting phymode to 11n!!");
593 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
594 }
595 }
596 else
597 {
598 /*New country Supports 11ac as well resetting value back from .ini*/
599 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
600 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
601 return ;
602 }
603
604 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
605 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
606 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
607 {
608 VOS_STATUS vosStatus;
609
610 // need to issue a disconnect to CSR.
611 INIT_COMPLETION(pAdapter->disconnect_comp_var);
612 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
613 pAdapter->sessionId,
614 eCSR_DISCONNECT_REASON_UNSPECIFIED );
615
616 if (VOS_STATUS_SUCCESS == vosStatus)
617 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
618 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
619
620 }
621}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700622#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530623
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700624void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
625{
626 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
627 hdd_config_t *cfg_param;
628
629 if (NULL == pHddCtx)
630 {
631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
632 "HDD Context is null !!");
633 return ;
634 }
635
636 cfg_param = pHddCtx->cfg_ini;
637
638 if (NULL == cfg_param)
639 {
640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
641 "cfg_params not available !!");
642 return ;
643 }
644
645 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
646 {
647 /*New country doesn't support DFS */
648 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
649 }
650 else
651 {
652 /*New country Supports DFS as well resetting value back from .ini*/
653 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
654 }
655
656}
657
Rajeev79dbe4c2013-10-05 11:03:42 +0530658#ifdef FEATURE_WLAN_BATCH_SCAN
659
660/**---------------------------------------------------------------------------
661
662 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
663 input string
664
665 This function extracts assigned integer from string in below format:
666 "STRING=10" : extracts integer 10 from this string
667
668 \param - pInPtr Pointer to input string
669 \param - base Base for string to int conversion(10 for decimal 16 for hex)
670 \param - pOutPtr Pointer to variable in which extracted integer needs to be
671 assigned
672 \param - pLastArg to tell whether it is last arguement in input string or
673 not
674
675 \return - NULL for failure cases
676 pointer to next arguement in input string for success cases
677 --------------------------------------------------------------------------*/
678static tANI_U8 *
679hdd_extract_assigned_int_from_str
680(
681 tANI_U8 *pInPtr,
682 tANI_U8 base,
683 tANI_U32 *pOutPtr,
684 tANI_U8 *pLastArg
685)
686{
687 int tempInt;
688 int v = 0;
689 char buf[32];
690 int val = 0;
691 *pLastArg = FALSE;
692
693 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
694 if (NULL == pInPtr)
695 {
696 return NULL;
697 }
698
699 pInPtr++;
700
701 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
702
703 val = sscanf(pInPtr, "%32s ", buf);
704 if (val < 0 && val > strlen(pInPtr))
705 {
706 return NULL;
707 }
708 pInPtr += val;
709 v = kstrtos32(buf, base, &tempInt);
710 if (v < 0)
711 {
712 return NULL;
713 }
714 *pOutPtr = tempInt;
715
716 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
717 if (NULL == pInPtr)
718 {
719 *pLastArg = TRUE;
720 return NULL;
721 }
722 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
723
724 return pInPtr;
725}
726
727/**---------------------------------------------------------------------------
728
729 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
730 input string
731
732 This function extracts assigned character from string in below format:
733 "STRING=A" : extracts char 'A' from this string
734
735 \param - pInPtr Pointer to input string
736 \param - pOutPtr Pointer to variable in which extracted char needs to be
737 assigned
738 \param - pLastArg to tell whether it is last arguement in input string or
739 not
740
741 \return - NULL for failure cases
742 pointer to next arguement in input string for success cases
743 --------------------------------------------------------------------------*/
744static tANI_U8 *
745hdd_extract_assigned_char_from_str
746(
747 tANI_U8 *pInPtr,
748 tANI_U8 *pOutPtr,
749 tANI_U8 *pLastArg
750)
751{
752 *pLastArg = FALSE;
753
754 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
755 if (NULL == pInPtr)
756 {
757 return NULL;
758 }
759
760 pInPtr++;
761
762 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
763
764 *pOutPtr = *pInPtr;
765
766 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
767 if (NULL == pInPtr)
768 {
769 *pLastArg = TRUE;
770 return NULL;
771 }
772 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
773
774 return pInPtr;
775}
776
777
778/**---------------------------------------------------------------------------
779
780 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
781
782 This function parses set batch scan command in below format:
783 WLS_BATCHING_SET <space> followed by below arguements
784 "SCANFREQ=XX" : Optional defaults to 30 sec
785 "MSCAN=XX" : Required number of scans to attempt to batch
786 "BESTN=XX" : Best Network (RSSI) defaults to 16
787 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
788 A. implies only 5 GHz , B. implies only 2.4GHz
789 "RTT=X" : optional defaults to 0
790 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
791 error
792
793 For example input commands:
794 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
795 translated into set batch scan with following parameters:
796 a) Frequence 60 seconds
797 b) Batch 10 scans together
798 c) Best RSSI to be 20
799 d) 5GHz band only
800 e) RTT is equal to 0
801
802 \param - pValue Pointer to input channel list
803 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
804
805 \return - 0 for success non-zero for failure
806
807 --------------------------------------------------------------------------*/
808static int
809hdd_parse_set_batchscan_command
810(
811 tANI_U8 *pValue,
812 tSirSetBatchScanReq *pHddSetBatchScanReq
813)
814{
815 tANI_U8 *inPtr = pValue;
816 tANI_U8 val = 0;
817 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800818 tANI_U32 nScanFreq;
819 tANI_U32 nMscan;
820 tANI_U32 nBestN;
821 tANI_U8 ucRfBand;
822 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800823 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530824
825 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800826 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
827 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
828 nRtt = 0;
829 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530830
831 /*go to space after WLS_BATCHING_SET command*/
832 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
833 /*no argument after the command*/
834 if (NULL == inPtr)
835 {
836 return -EINVAL;
837 }
838
839 /*no space after the command*/
840 else if (SPACE_ASCII_VALUE != *inPtr)
841 {
842 return -EINVAL;
843 }
844
845 /*removing empty spaces*/
846 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
847
848 /*no argument followed by spaces*/
849 if ('\0' == *inPtr)
850 {
851 return -EINVAL;
852 }
853
854 /*check and parse SCANFREQ*/
855 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
856 {
857 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800858 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800859
Rajeev Kumarc933d982013-11-18 20:04:20 -0800860 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800861 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800862 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800863 }
864
Rajeev79dbe4c2013-10-05 11:03:42 +0530865 if ( (NULL == inPtr) || (TRUE == lastArg))
866 {
867 return -EINVAL;
868 }
869 }
870
871 /*check and parse MSCAN*/
872 if ((strncmp(inPtr, "MSCAN", 5) == 0))
873 {
874 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800875 &nMscan, &lastArg);
876
877 if (0 == nMscan)
878 {
879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
880 "invalid MSCAN=%d", nMscan);
881 return -EINVAL;
882 }
883
Rajeev79dbe4c2013-10-05 11:03:42 +0530884 if (TRUE == lastArg)
885 {
886 goto done;
887 }
888 else if (NULL == inPtr)
889 {
890 return -EINVAL;
891 }
892 }
893 else
894 {
895 return -EINVAL;
896 }
897
898 /*check and parse BESTN*/
899 if ((strncmp(inPtr, "BESTN", 5) == 0))
900 {
901 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800902 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800903
Rajeev Kumarc933d982013-11-18 20:04:20 -0800904 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800905 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800906 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800907 }
908
Rajeev79dbe4c2013-10-05 11:03:42 +0530909 if (TRUE == lastArg)
910 {
911 goto done;
912 }
913 else if (NULL == inPtr)
914 {
915 return -EINVAL;
916 }
917 }
918
919 /*check and parse CHANNEL*/
920 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
921 {
922 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800923
Rajeev79dbe4c2013-10-05 11:03:42 +0530924 if (('A' == val) || ('a' == val))
925 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800926 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530927 }
928 else if (('B' == val) || ('b' == val))
929 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800930 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530931 }
932 else
933 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800934 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
935 }
936
937 if (TRUE == lastArg)
938 {
939 goto done;
940 }
941 else if (NULL == inPtr)
942 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530943 return -EINVAL;
944 }
945 }
946
947 /*check and parse RTT*/
948 if ((strncmp(inPtr, "RTT", 3) == 0))
949 {
950 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800951 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530952 if (TRUE == lastArg)
953 {
954 goto done;
955 }
956 if (NULL == inPtr)
957 {
958 return -EINVAL;
959 }
960 }
961
962
963done:
964
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800965 pHddSetBatchScanReq->scanFrequency = nScanFreq;
966 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
967 pHddSetBatchScanReq->bestNetwork = nBestN;
968 pHddSetBatchScanReq->rfBand = ucRfBand;
969 pHddSetBatchScanReq->rtt = nRtt;
970
Rajeev79dbe4c2013-10-05 11:03:42 +0530971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
972 "Received WLS_BATCHING_SET with SCANFREQ=%d "
973 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
974 pHddSetBatchScanReq->scanFrequency,
975 pHddSetBatchScanReq->numberOfScansToBatch,
976 pHddSetBatchScanReq->bestNetwork,
977 pHddSetBatchScanReq->rfBand,
978 pHddSetBatchScanReq->rtt);
979
980 return 0;
981}/*End of hdd_parse_set_batchscan_command*/
982
983/**---------------------------------------------------------------------------
984
985 \brief hdd_set_batch_scan_req_callback () - This function is called after
986 receiving set batch scan response from FW and it saves set batch scan
987 response data FW to HDD context and sets the completion event on
988 which hdd_ioctl is waiting
989
990 \param - callbackContext Pointer to HDD adapter
991 \param - pRsp Pointer to set batch scan response data received from FW
992
993 \return - nothing
994
995 --------------------------------------------------------------------------*/
996static void hdd_set_batch_scan_req_callback
997(
998 void *callbackContext,
999 tSirSetBatchScanRsp *pRsp
1000)
1001{
1002 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1003 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1004
1005 /*sanity check*/
1006 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1007 {
1008 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1009 "%s: Invalid pAdapter magic", __func__);
1010 VOS_ASSERT(0);
1011 return;
1012 }
1013 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1014
1015 /*save set batch scan response*/
1016 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1017
1018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1019 "Received set batch scan rsp from FW with nScansToBatch=%d",
1020 pHddSetBatchScanRsp->nScansToBatch);
1021
1022 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1023 complete(&pAdapter->hdd_set_batch_scan_req_var);
1024
1025 return;
1026}/*End of hdd_set_batch_scan_req_callback*/
1027
1028
1029/**---------------------------------------------------------------------------
1030
1031 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1032 info in hdd batch scan response queue
1033
1034 \param - pAdapter Pointer to hdd adapter
1035 \param - pAPMetaInfo Pointer to access point meta info
1036 \param - scanId scan ID of batch scan response
1037 \param - isLastAp tells whether AP is last AP in batch scan response or not
1038
1039 \return - nothing
1040
1041 --------------------------------------------------------------------------*/
1042static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1043 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1044{
1045 tHddBatchScanRsp *pHead;
1046 tHddBatchScanRsp *pNode;
1047 tHddBatchScanRsp *pPrev;
1048 tHddBatchScanRsp *pTemp;
1049 tANI_U8 ssidLen;
1050
1051 /*head of hdd batch scan response queue*/
1052 pHead = pAdapter->pBatchScanRsp;
1053
1054 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1055 if (NULL == pNode)
1056 {
1057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1058 "%s: Could not allocate memory", __func__);
1059 VOS_ASSERT(0);
1060 return;
1061 }
1062
1063 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1064 sizeof(pNode->ApInfo.bssid));
1065 ssidLen = strlen(pApMetaInfo->ssid);
1066 if (SIR_MAX_SSID_SIZE < ssidLen)
1067 {
1068 /*invalid scan result*/
1069 vos_mem_free(pNode);
1070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1071 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1072 return;
1073 }
1074 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1075 /*null terminate ssid*/
1076 pNode->ApInfo.ssid[ssidLen] = '\0';
1077 pNode->ApInfo.ch = pApMetaInfo->ch;
1078 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1079 pNode->ApInfo.age = pApMetaInfo->timestamp;
1080 pNode->ApInfo.batchId = scanId;
1081 pNode->ApInfo.isLastAp = isLastAp;
1082
1083 pNode->pNext = NULL;
1084 if (NULL == pHead)
1085 {
1086 pAdapter->pBatchScanRsp = pNode;
1087 }
1088 else
1089 {
1090 pTemp = pHead;
1091 while (NULL != pTemp)
1092 {
1093 pPrev = pTemp;
1094 pTemp = pTemp->pNext;
1095 }
1096 pPrev->pNext = pNode;
1097 }
1098
1099 return;
1100}/*End of hdd_populate_batch_scan_rsp_queue*/
1101
1102/**---------------------------------------------------------------------------
1103
1104 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1105 receiving batch scan response indication from FW. It saves get batch scan
1106 response data in HDD batch scan response queue. This callback sets the
1107 completion event on which hdd_ioctl is waiting only after getting complete
1108 batch scan response data from FW
1109
1110 \param - callbackContext Pointer to HDD adapter
1111 \param - pRsp Pointer to get batch scan response data received from FW
1112
1113 \return - nothing
1114
1115 --------------------------------------------------------------------------*/
1116static void hdd_batch_scan_result_ind_callback
1117(
1118 void *callbackContext,
1119 void *pRsp
1120)
1121{
1122 v_BOOL_t isLastAp;
1123 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001124 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301125 tANI_U32 numberScanList;
1126 tANI_U32 nextScanListOffset;
1127 tANI_U32 nextApMetaInfoOffset;
1128 hdd_adapter_t* pAdapter;
1129 tpSirBatchScanList pScanList;
1130 tpSirBatchScanNetworkInfo pApMetaInfo;
1131 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1132 tSirSetBatchScanReq *pReq;
1133
1134 pAdapter = (hdd_adapter_t *)callbackContext;
1135 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001136 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301137 {
1138 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1139 "%s: Invalid pAdapter magic", __func__);
1140 VOS_ASSERT(0);
1141 return;
1142 }
1143
1144 /*initialize locals*/
1145 pReq = &pAdapter->hddSetBatchScanReq;
1146 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1147 isLastAp = FALSE;
1148 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001149 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301150 numberScanList = 0;
1151 nextScanListOffset = 0;
1152 nextApMetaInfoOffset = 0;
1153 pScanList = NULL;
1154 pApMetaInfo = NULL;
1155
1156 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1157 {
1158 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1159 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1160 isLastAp = TRUE;
1161 goto done;
1162 }
1163
1164 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1166 "Batch scan rsp: numberScalList %d", numberScanList);
1167
1168 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1169 {
1170 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1171 "%s: numberScanList %d", __func__, numberScanList);
1172 isLastAp = TRUE;
1173 goto done;
1174 }
1175
1176 while (numberScanList)
1177 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001178 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301179 nextScanListOffset);
1180 if (NULL == pScanList)
1181 {
1182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1183 "%s: pScanList is %p", __func__, pScanList);
1184 isLastAp = TRUE;
1185 goto done;
1186 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001187 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001189 "Batch scan rsp: numApMetaInfo %d scanId %d",
1190 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301191
1192 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1193 {
1194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1196 isLastAp = TRUE;
1197 goto done;
1198 }
1199
Rajeev Kumarce651e42013-10-21 18:57:15 -07001200 /*Initialize next AP meta info offset for next scan list*/
1201 nextApMetaInfoOffset = 0;
1202
Rajeev79dbe4c2013-10-05 11:03:42 +05301203 while (numApMetaInfo)
1204 {
1205 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1206 nextApMetaInfoOffset);
1207 if (NULL == pApMetaInfo)
1208 {
1209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1210 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1211 isLastAp = TRUE;
1212 goto done;
1213 }
1214 /*calculate AP age*/
1215 pApMetaInfo->timestamp =
1216 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1217
1218 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001219 "%s: bssId "MAC_ADDRESS_STR
1220 " ch %d rssi %d timestamp %d", __func__,
1221 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1222 pApMetaInfo->ch, pApMetaInfo->rssi,
1223 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301224
1225 /*mark last AP in batch scan response*/
1226 if ((TRUE == pBatchScanRsp->isLastResult) &&
1227 (1 == numberScanList) && (1 == numApMetaInfo))
1228 {
1229 isLastAp = TRUE;
1230 }
1231
1232 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1233 /*store batch scan repsonse in hdd queue*/
1234 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1235 pScanList->scanId, isLastAp);
1236 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1237
1238 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1239 numApMetaInfo--;
1240 }
1241
Rajeev Kumarce651e42013-10-21 18:57:15 -07001242 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1243 + (sizeof(tSirBatchScanNetworkInfo)
1244 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301245 numberScanList--;
1246 }
1247
1248done:
1249
1250 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1251 requested from hdd_ioctl*/
1252 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1253 (TRUE == isLastAp))
1254 {
1255 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1256 complete(&pAdapter->hdd_get_batch_scan_req_var);
1257 }
1258
1259 return;
1260}/*End of hdd_batch_scan_result_ind_callback*/
1261
1262/**---------------------------------------------------------------------------
1263
1264 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1265 response as per batch scan FR request format by putting proper markers
1266
1267 \param - pDest pointer to destination buffer
1268 \param - cur_len current length
1269 \param - tot_len total remaining size which can be written to user space
1270 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1271 \param - pAdapter Pointer to HDD adapter
1272
1273 \return - ret no of characters written
1274
1275 --------------------------------------------------------------------------*/
1276static tANI_U32
1277hdd_format_batch_scan_rsp
1278(
1279 tANI_U8 *pDest,
1280 tANI_U32 cur_len,
1281 tANI_U32 tot_len,
1282 tHddBatchScanRsp *pApMetaInfo,
1283 hdd_adapter_t* pAdapter
1284)
1285{
1286 tANI_U32 ret = 0;
1287 tANI_U32 rem_len = 0;
1288 tANI_U8 temp_len = 0;
1289 tANI_U8 temp_total_len = 0;
1290 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1291 tANI_U8 *pTemp = temp;
1292
1293 /*Batch scan reponse needs to be returned to user space in
1294 following format:
1295 "scancount=X\n" where X is the number of scans in current batch
1296 batch
1297 "trunc\n" optional present if current scan truncated
1298 "bssid=XX:XX:XX:XX:XX:XX\n"
1299 "ssid=XXXX\n"
1300 "freq=X\n" frequency in Mhz
1301 "level=XX\n"
1302 "age=X\n" ms
1303 "dist=X\n" cm (-1 if not available)
1304 "errror=X\n" (-1if not available)
1305 "====\n" (end of ap marker)
1306 "####\n" (end of scan marker)
1307 "----\n" (end of results)*/
1308 /*send scan result in above format to user space based on
1309 available length*/
1310 /*The GET response may have more data than the driver can return in its
1311 buffer. In that case the buffer should be filled to the nearest complete
1312 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1313 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1314 The final buffer should end with "----\n"*/
1315
1316 /*sanity*/
1317 if (cur_len > tot_len)
1318 {
1319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1320 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1321 return 0;
1322 }
1323 else
1324 {
1325 rem_len = (tot_len - cur_len);
1326 }
1327
1328 /*end scan marker*/
1329 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1330 {
1331 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1332 pTemp += temp_len;
1333 temp_total_len += temp_len;
1334 }
1335
1336 /*bssid*/
1337 temp_len = snprintf(pTemp, sizeof(temp),
1338 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1339 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1340 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1341 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1342 pTemp += temp_len;
1343 temp_total_len += temp_len;
1344
1345 /*ssid*/
1346 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1347 pApMetaInfo->ApInfo.ssid);
1348 pTemp += temp_len;
1349 temp_total_len += temp_len;
1350
1351 /*freq*/
1352 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001353 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301354 pTemp += temp_len;
1355 temp_total_len += temp_len;
1356
1357 /*level*/
1358 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1359 pApMetaInfo->ApInfo.rssi);
1360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362
1363 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001364 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301365 pApMetaInfo->ApInfo.age);
1366 pTemp += temp_len;
1367 temp_total_len += temp_len;
1368
1369 /*dist*/
1370 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1371 pTemp += temp_len;
1372 temp_total_len += temp_len;
1373
1374 /*error*/
1375 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1376 pTemp += temp_len;
1377 temp_total_len += temp_len;
1378
1379 /*end AP marker*/
1380 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1381 pTemp += temp_len;
1382 temp_total_len += temp_len;
1383
1384 /*last AP in batch scan response*/
1385 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1386 {
1387 /*end scan marker*/
1388 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*end batch scan result marker*/
1393 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1394 pTemp += temp_len;
1395 temp_total_len += temp_len;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001396
1397 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301398 }
1399
1400 if (temp_total_len < rem_len)
1401 {
1402 ret = temp_total_len + 1;
1403 strlcpy(pDest, temp, ret);
1404 pAdapter->isTruncated = FALSE;
1405 }
1406 else
1407 {
1408 pAdapter->isTruncated = TRUE;
1409 if (rem_len >= strlen("%%%%"))
1410 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001411 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301412 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001413 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301414 {
1415 ret = 0;
1416 }
1417 }
1418
1419 return ret;
1420
1421}/*End of hdd_format_batch_scan_rsp*/
1422
1423/**---------------------------------------------------------------------------
1424
1425 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1426 buffer starting with head of hdd batch scan response queue
1427
1428 \param - pAdapter Pointer to HDD adapter
1429 \param - pDest Pointer to user data buffer
1430 \param - cur_len current offset in user buffer
1431 \param - rem_len remaining no of bytes in user buffer
1432
1433 \return - number of bytes written in user buffer
1434
1435 --------------------------------------------------------------------------*/
1436
1437tANI_U32 hdd_populate_user_batch_scan_rsp
1438(
1439 hdd_adapter_t* pAdapter,
1440 tANI_U8 *pDest,
1441 tANI_U32 cur_len,
1442 tANI_U32 rem_len
1443)
1444{
1445 tHddBatchScanRsp *pHead;
1446 tHddBatchScanRsp *pPrev;
1447 tANI_U32 len;
1448
Rajeev79dbe4c2013-10-05 11:03:42 +05301449 pAdapter->isTruncated = FALSE;
1450
1451 /*head of hdd batch scan response queue*/
1452 pHead = pAdapter->pBatchScanRsp;
1453 while (pHead)
1454 {
1455 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1456 pAdapter);
1457 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001458 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301459 cur_len += len;
1460 if(TRUE == pAdapter->isTruncated)
1461 {
1462 /*result is truncated return rest of scan rsp in next req*/
1463 cur_len = rem_len;
1464 break;
1465 }
1466 pPrev = pHead;
1467 pHead = pHead->pNext;
1468 pAdapter->pBatchScanRsp = pHead;
1469 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1470 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001471 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301472 }
1473
1474 return cur_len;
1475}/*End of hdd_populate_user_batch_scan_rsp*/
1476
1477/**---------------------------------------------------------------------------
1478
1479 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1480 scan response data from HDD queue to user space
1481 It does following in detail:
1482 a) if HDD has enough data in its queue then it 1st copies data to user
1483 space and then send get batch scan indication message to FW. In this
1484 case it does not wait on any event and batch scan response data will
1485 be populated in HDD response queue in MC thread context after receiving
1486 indication from FW
1487 b) else send get batch scan indication message to FW and wait on an event
1488 which will be set once HDD receives complete batch scan response from
1489 FW and then this function returns batch scan response to user space
1490
1491 \param - pAdapter Pointer to HDD adapter
1492 \param - pPrivData Pointer to priv_data
1493
1494 \return - 0 for success -EFAULT for failure
1495
1496 --------------------------------------------------------------------------*/
1497
1498int hdd_return_batch_scan_rsp_to_user
1499(
1500 hdd_adapter_t* pAdapter,
1501 hdd_priv_data_t *pPrivData,
1502 tANI_U8 *command
1503)
1504{
1505 tANI_U8 *pDest;
1506 tANI_U32 count = 0;
1507 tANI_U32 len = 0;
1508 tANI_U32 cur_len = 0;
1509 tANI_U32 rem_len = 0;
1510 eHalStatus halStatus;
1511 unsigned long rc;
1512 tSirTriggerBatchScanResultInd *pReq;
1513
1514 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1515 pReq->param = 0;/*batch scan client*/
1516 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1517 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1518
1519 cur_len = pPrivData->used_len;
1520 if (pPrivData->total_len > pPrivData->used_len)
1521 {
1522 rem_len = pPrivData->total_len - pPrivData->used_len;
1523 }
1524 else
1525 {
1526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1527 "%s: Invalid user data buffer total_len %d used_len %d",
1528 __func__, pPrivData->total_len, pPrivData->used_len);
1529 return -EFAULT;
1530 }
1531
1532 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1533 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1534 cur_len, rem_len);
1535 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1536
1537 /*enough scan result available in cache to return to user space or
1538 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001539 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301540 {
1541 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1542 halStatus = sme_TriggerBatchScanResultInd(
1543 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1544 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1545 pAdapter);
1546 if ( eHAL_STATUS_SUCCESS == halStatus )
1547 {
1548 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1549 {
1550 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1551 rc = wait_for_completion_timeout(
1552 &pAdapter->hdd_get_batch_scan_req_var,
1553 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1554 if (0 == rc)
1555 {
1556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "%s: Timeout waiting to fetch batch scan rsp from fw",
1558 __func__);
1559 return -EFAULT;
1560 }
1561 }
1562
1563 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001564 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301565 pDest += len;
1566 cur_len += len;
1567
1568 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1569 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1570 cur_len, rem_len);
1571 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1572
1573 count = 0;
1574 len = (len - pPrivData->used_len);
1575 pDest = (command + pPrivData->used_len);
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001577 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301578 while(count < len)
1579 {
1580 printk("%c", *(pDest + count));
1581 count++;
1582 }
1583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1584 "%s: copy %d data to user buffer", __func__, len);
1585 if (copy_to_user(pPrivData->buf, pDest, len))
1586 {
1587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1588 "%s: failed to copy data to user buffer", __func__);
1589 return -EFAULT;
1590 }
1591 }
1592 else
1593 {
1594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1595 "sme_GetBatchScanScan returned failure halStatus %d",
1596 halStatus);
1597 return -EINVAL;
1598 }
1599 }
1600 else
1601 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301602 count = 0;
1603 len = (len - pPrivData->used_len);
1604 pDest = (command + pPrivData->used_len);
1605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001606 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301607 while(count < len)
1608 {
1609 printk("%c", *(pDest + count));
1610 count++;
1611 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1613 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301614 if (copy_to_user(pPrivData->buf, pDest, len))
1615 {
1616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1617 "%s: failed to copy data to user buffer", __func__);
1618 return -EFAULT;
1619 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301620 }
1621
1622 return 0;
1623} /*End of hdd_return_batch_scan_rsp_to_user*/
1624
1625#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1626
Jeff Johnson295189b2012-06-20 16:38:30 -07001627int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1628{
1629 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1630 hdd_priv_data_t priv_data;
1631 tANI_U8 *command = NULL;
1632 int ret = 0;
1633
1634 if (NULL == pAdapter)
1635 {
1636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001637 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001638 ret = -ENODEV;
1639 goto exit;
1640 }
1641
Jeff Johnsone7245742012-09-05 17:12:55 -07001642 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 {
1644 ret = -EINVAL;
1645 goto exit;
1646 }
1647
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001648 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1649 {
1650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1651 "%s:LOGP in Progress. Ignore!!!", __func__);
1652 ret = -EBUSY;
1653 goto exit;
1654 }
1655
Jeff Johnson295189b2012-06-20 16:38:30 -07001656 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1657 {
1658 ret = -EFAULT;
1659 goto exit;
1660 }
1661
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001662 if (priv_data.total_len <= 0)
1663 {
1664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1665 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1666 priv_data.total_len);
1667 ret = -EINVAL;
1668 goto exit;
1669 }
1670
1671 /* Allocate +1 for '\0' */
1672 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001673 if (!command)
1674 {
1675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001676 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001677 ret = -ENOMEM;
1678 goto exit;
1679 }
1680
1681 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1682 {
1683 ret = -EFAULT;
1684 goto exit;
1685 }
1686
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001687 /* Making sure the command is NUL-terminated */
1688 command[priv_data.total_len] = '\0';
1689
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 if ((SIOCDEVPRIVATE + 1) == cmd)
1691 {
1692 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1693
1694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001695 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001696
1697 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1698 {
1699 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1700 sizeof(tSirMacAddr)))
1701 {
1702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001703 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 ret = -EFAULT;
1705 }
1706 }
Amar Singhal0974e402013-02-12 14:27:46 -08001707 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001708 {
Amar Singhal0974e402013-02-12 14:27:46 -08001709 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001710 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001711
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001713
1714 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001716 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001717 "%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 -07001718 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001719 ret = hdd_setBand_helper(dev, ptr);
1720 }
Kiet Lamf040f472013-11-20 21:15:23 +05301721 else if(strncmp(command, "SETWMMPS", 8) == 0)
1722 {
1723 tANI_U8 *ptr = command;
1724 ret = hdd_wmmps_helper(pAdapter, ptr);
1725 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001726 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1727 {
1728 char *country_code;
1729
1730 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001731
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001732 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001733 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001734#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301735 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001736#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001737 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1738 (void *)(tSmeChangeCountryCallback)
1739 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301740 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001741 if (eHAL_STATUS_SUCCESS == ret)
1742 {
1743 ret = wait_for_completion_interruptible_timeout(
1744 &pAdapter->change_country_code,
1745 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1746 if (0 >= ret)
1747 {
1748 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1749 __func__);
1750 }
1751 }
1752 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001753 {
1754 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001755 "%s: SME Change Country code fail ret=%d", __func__, ret);
1756 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001757 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001758
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001759 }
1760 /*
1761 command should be a string having format
1762 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1763 */
Amar Singhal0974e402013-02-12 14:27:46 -08001764 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001765 {
Amar Singhal0974e402013-02-12 14:27:46 -08001766 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001767
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001769 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001770
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001771 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001772 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001773 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1774 {
1775 int suspend = 0;
1776 tANI_U8 *ptr = (tANI_U8*)command + 15;
1777
1778 suspend = *ptr - '0';
1779 hdd_set_wlan_suspend_mode(suspend);
1780 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001781#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1782 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1783 {
1784 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001786 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1787 eHalStatus status = eHAL_STATUS_SUCCESS;
1788
1789 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1790 value = value + 15;
1791
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001792 /* Convert the value from ascii to integer */
1793 ret = kstrtos8(value, 10, &rssi);
1794 if (ret < 0)
1795 {
1796 /* If the input value is greater than max value of datatype, then also
1797 kstrtou8 fails */
1798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001800 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001801 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1802 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
Srinivas Girigowdade697412013-02-14 16:31:48 -08001807 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001808
Srinivas Girigowdade697412013-02-14 16:31:48 -08001809 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1810 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "Neighbor lookup threshold value %d is out of range"
1814 " (Min: %d Max: %d)", lookUpThreshold,
1815 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1816 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1817 ret = -EINVAL;
1818 goto exit;
1819 }
1820
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1822 "%s: Received Command to Set Roam trigger"
1823 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1824
1825 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1826 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1827 if (eHAL_STATUS_SUCCESS != status)
1828 {
1829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1830 "%s: Failed to set roam trigger, try again", __func__);
1831 ret = -EPERM;
1832 goto exit;
1833 }
1834
1835 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1836 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1837 }
1838 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1839 {
1840 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1841 int rssi = (-1) * lookUpThreshold;
1842 char extra[32];
1843 tANI_U8 len = 0;
1844
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001845 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001846 if (copy_to_user(priv_data.buf, &extra, len + 1))
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "%s: failed to copy data to user buffer", __func__);
1850 ret = -EFAULT;
1851 goto exit;
1852 }
1853 }
1854 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1855 {
1856 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001857 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001858 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001859
Srinivas Girigowdade697412013-02-14 16:31:48 -08001860 /* input refresh period is in terms of seconds */
1861 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1862 value = value + 18;
1863 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001864 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001865 if (ret < 0)
1866 {
1867 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001868 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001870 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001871 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001872 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1873 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001874 ret = -EINVAL;
1875 goto exit;
1876 }
1877
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001878 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1879 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001880 {
1881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001882 "Roam scan period value %d is out of range"
1883 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001884 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1885 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001886 ret = -EINVAL;
1887 goto exit;
1888 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001889 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001890
1891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1892 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001893 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001894
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001895 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1896 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001897 }
1898 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1899 {
1900 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1901 char extra[32];
1902 tANI_U8 len = 0;
1903
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001904 len = scnprintf(extra, sizeof(extra), "%s %d",
1905 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001906 /* Returned value is in units of seconds */
1907 if (copy_to_user(priv_data.buf, &extra, len + 1))
1908 {
1909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1910 "%s: failed to copy data to user buffer", __func__);
1911 ret = -EFAULT;
1912 goto exit;
1913 }
1914 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001915 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1916 {
1917 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001918 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001920
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001921 /* input refresh period is in terms of seconds */
1922 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1923 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001924
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001925 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001926 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001927 if (ret < 0)
1928 {
1929 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001930 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001932 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001933 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001934 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1935 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1936 ret = -EINVAL;
1937 goto exit;
1938 }
1939
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001940 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1941 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1942 {
1943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1944 "Neighbor scan results refresh period value %d is out of range"
1945 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1946 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1947 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1948 ret = -EINVAL;
1949 goto exit;
1950 }
1951 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1952
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1954 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001955 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001956
1957 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1958 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1959 }
1960 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1961 {
1962 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1963 char extra[32];
1964 tANI_U8 len = 0;
1965
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001966 len = scnprintf(extra, sizeof(extra), "%s %d",
1967 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001968 /* Returned value is in units of seconds */
1969 if (copy_to_user(priv_data.buf, &extra, len + 1))
1970 {
1971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1972 "%s: failed to copy data to user buffer", __func__);
1973 ret = -EFAULT;
1974 goto exit;
1975 }
1976 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001977#ifdef FEATURE_WLAN_LFR
1978 /* SETROAMMODE */
1979 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1980 {
1981 tANI_U8 *value = command;
1982 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1983
1984 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1985 value = value + SIZE_OF_SETROAMMODE + 1;
1986
1987 /* Convert the value from ascii to integer */
1988 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1989 if (ret < 0)
1990 {
1991 /* If the input value is greater than max value of datatype, then also
1992 kstrtou8 fails */
1993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1994 "%s: kstrtou8 failed range [%d - %d]", __func__,
1995 CFG_LFR_FEATURE_ENABLED_MIN,
1996 CFG_LFR_FEATURE_ENABLED_MAX);
1997 ret = -EINVAL;
1998 goto exit;
1999 }
2000 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2001 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2002 {
2003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2004 "Roam Mode value %d is out of range"
2005 " (Min: %d Max: %d)", roamMode,
2006 CFG_LFR_FEATURE_ENABLED_MIN,
2007 CFG_LFR_FEATURE_ENABLED_MAX);
2008 ret = -EINVAL;
2009 goto exit;
2010 }
2011
2012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2013 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2014 /*
2015 * Note that
2016 * SETROAMMODE 0 is to enable LFR while
2017 * SETROAMMODE 1 is to disable LFR, but
2018 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2019 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2020 */
2021 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2022 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2023 else
2024 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2025
2026 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2027 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2028 }
2029 /* GETROAMMODE */
2030 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2031 {
2032 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2033 char extra[32];
2034 tANI_U8 len = 0;
2035
2036 /*
2037 * roamMode value shall be inverted because the sementics is different.
2038 */
2039 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2040 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2041 else
2042 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2043
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002044 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002045 if (copy_to_user(priv_data.buf, &extra, len + 1))
2046 {
2047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2048 "%s: failed to copy data to user buffer", __func__);
2049 ret = -EFAULT;
2050 goto exit;
2051 }
2052 }
2053#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002054#endif
2055#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2056 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2057 {
2058 tANI_U8 *value = command;
2059 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2060
2061 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2062 value = value + 13;
2063 /* Convert the value from ascii to integer */
2064 ret = kstrtou8(value, 10, &roamRssiDiff);
2065 if (ret < 0)
2066 {
2067 /* If the input value is greater than max value of datatype, then also
2068 kstrtou8 fails */
2069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2070 "%s: kstrtou8 failed range [%d - %d]", __func__,
2071 CFG_ROAM_RSSI_DIFF_MIN,
2072 CFG_ROAM_RSSI_DIFF_MAX);
2073 ret = -EINVAL;
2074 goto exit;
2075 }
2076
2077 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2078 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2079 {
2080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2081 "Roam rssi diff value %d is out of range"
2082 " (Min: %d Max: %d)", roamRssiDiff,
2083 CFG_ROAM_RSSI_DIFF_MIN,
2084 CFG_ROAM_RSSI_DIFF_MAX);
2085 ret = -EINVAL;
2086 goto exit;
2087 }
2088
2089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2090 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2091
2092 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2093 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2094 }
2095 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2096 {
2097 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2098 char extra[32];
2099 tANI_U8 len = 0;
2100
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002101 len = scnprintf(extra, sizeof(extra), "%s %d",
2102 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002103 if (copy_to_user(priv_data.buf, &extra, len + 1))
2104 {
2105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2106 "%s: failed to copy data to user buffer", __func__);
2107 ret = -EFAULT;
2108 goto exit;
2109 }
2110 }
2111#endif
2112#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2113 else if (strncmp(command, "GETBAND", 7) == 0)
2114 {
2115 int band = -1;
2116 char extra[32];
2117 tANI_U8 len = 0;
2118 hdd_getBand_helper(pHddCtx, &band);
2119
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002120 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002121 if (copy_to_user(priv_data.buf, &extra, len + 1))
2122 {
2123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2124 "%s: failed to copy data to user buffer", __func__);
2125 ret = -EFAULT;
2126 goto exit;
2127 }
2128 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002129 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2130 {
2131 tANI_U8 *value = command;
2132 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2133 tANI_U8 numChannels = 0;
2134 eHalStatus status = eHAL_STATUS_SUCCESS;
2135
2136 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2137 if (eHAL_STATUS_SUCCESS != status)
2138 {
2139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2140 "%s: Failed to parse channel list information", __func__);
2141 ret = -EINVAL;
2142 goto exit;
2143 }
2144
2145 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2146 {
2147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2148 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2149 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2150 ret = -EINVAL;
2151 goto exit;
2152 }
2153 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2154 numChannels);
2155 if (eHAL_STATUS_SUCCESS != status)
2156 {
2157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2158 "%s: Failed to update channel list information", __func__);
2159 ret = -EINVAL;
2160 goto exit;
2161 }
2162 }
2163 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2164 {
2165 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2166 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002167 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002168 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002169 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002170
2171 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2172 ChannelList, &numChannels ))
2173 {
2174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2175 "%s: failed to get roam scan channel list", __func__);
2176 ret = -EFAULT;
2177 goto exit;
2178 }
2179 /* output channel list is of the format
2180 [Number of roam scan channels][Channel1][Channel2]... */
2181 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002182 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002183 for (j = 0; (j < numChannels); j++)
2184 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002185 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2186 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002187 }
2188
2189 if (copy_to_user(priv_data.buf, &extra, len + 1))
2190 {
2191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2192 "%s: failed to copy data to user buffer", __func__);
2193 ret = -EFAULT;
2194 goto exit;
2195 }
2196 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002197 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2198 {
2199 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2200 char extra[32];
2201 tANI_U8 len = 0;
2202
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002203 /* Check if the features OKC/CCX/11R are supported simultaneously,
2204 then this operation is not permitted (return FAILURE) */
2205 if (ccxMode &&
2206 hdd_is_okc_mode_enabled(pHddCtx) &&
2207 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2208 {
2209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2210 "%s: OKC/CCX/11R are supported simultaneously"
2211 " hence this operation is not permitted!", __func__);
2212 ret = -EPERM;
2213 goto exit;
2214 }
2215
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002216 len = scnprintf(extra, sizeof(extra), "%s %d",
2217 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002218 if (copy_to_user(priv_data.buf, &extra, len + 1))
2219 {
2220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2221 "%s: failed to copy data to user buffer", __func__);
2222 ret = -EFAULT;
2223 goto exit;
2224 }
2225 }
2226 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2227 {
2228 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2229 char extra[32];
2230 tANI_U8 len = 0;
2231
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002232 /* Check if the features OKC/CCX/11R are supported simultaneously,
2233 then this operation is not permitted (return FAILURE) */
2234 if (okcMode &&
2235 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2236 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2237 {
2238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2239 "%s: OKC/CCX/11R are supported simultaneously"
2240 " hence this operation is not permitted!", __func__);
2241 ret = -EPERM;
2242 goto exit;
2243 }
2244
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002245 len = scnprintf(extra, sizeof(extra), "%s %d",
2246 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002247 if (copy_to_user(priv_data.buf, &extra, len + 1))
2248 {
2249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2250 "%s: failed to copy data to user buffer", __func__);
2251 ret = -EFAULT;
2252 goto exit;
2253 }
2254 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002255 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002256 {
2257 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2258 char extra[32];
2259 tANI_U8 len = 0;
2260
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002261 len = scnprintf(extra, sizeof(extra), "%s %d",
2262 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002263 if (copy_to_user(priv_data.buf, &extra, len + 1))
2264 {
2265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2266 "%s: failed to copy data to user buffer", __func__);
2267 ret = -EFAULT;
2268 goto exit;
2269 }
2270 }
2271 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2272 {
2273 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2274 char extra[32];
2275 tANI_U8 len = 0;
2276
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002277 len = scnprintf(extra, sizeof(extra), "%s %d",
2278 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002279 if (copy_to_user(priv_data.buf, &extra, len + 1))
2280 {
2281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2282 "%s: failed to copy data to user buffer", __func__);
2283 ret = -EFAULT;
2284 goto exit;
2285 }
2286 }
2287 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2288 {
2289 tANI_U8 *value = command;
2290 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2291
2292 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2293 value = value + 26;
2294 /* Convert the value from ascii to integer */
2295 ret = kstrtou8(value, 10, &minTime);
2296 if (ret < 0)
2297 {
2298 /* If the input value is greater than max value of datatype, then also
2299 kstrtou8 fails */
2300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2301 "%s: kstrtou8 failed range [%d - %d]", __func__,
2302 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2303 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2304 ret = -EINVAL;
2305 goto exit;
2306 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002307 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2308 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2309 {
2310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2311 "scan min channel time value %d is out of range"
2312 " (Min: %d Max: %d)", minTime,
2313 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2314 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2315 ret = -EINVAL;
2316 goto exit;
2317 }
2318
2319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2320 "%s: Received Command to change channel min time = %d", __func__, minTime);
2321
2322 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2323 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2324 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002325 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2326 {
2327 tANI_U8 *value = command;
2328 tANI_U8 channel = 0;
2329 tANI_U8 dwellTime = 0;
2330 tANI_U8 bufLen = 0;
2331 tANI_U8 *buf = NULL;
2332 tSirMacAddr targetApBssid;
2333 eHalStatus status = eHAL_STATUS_SUCCESS;
2334 struct ieee80211_channel chan;
2335 tANI_U8 finalLen = 0;
2336 tANI_U8 *finalBuf = NULL;
2337 tANI_U8 temp = 0;
2338 u64 cookie;
2339 hdd_station_ctx_t *pHddStaCtx = NULL;
2340 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2341
2342 /* if not associated, no need to send action frame */
2343 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2344 {
2345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2346 ret = -EINVAL;
2347 goto exit;
2348 }
2349
2350 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2351 &dwellTime, &buf, &bufLen);
2352 if (eHAL_STATUS_SUCCESS != status)
2353 {
2354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2355 "%s: Failed to parse send action frame data", __func__);
2356 ret = -EINVAL;
2357 goto exit;
2358 }
2359
2360 /* if the target bssid is different from currently associated AP,
2361 then no need to send action frame */
2362 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2363 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2364 {
2365 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2366 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002367 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002368 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002369 goto exit;
2370 }
2371
2372 /* if the channel number is different from operating channel then
2373 no need to send action frame */
2374 if (channel != pHddStaCtx->conn_info.operationChannel)
2375 {
2376 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2377 "%s: channel(%d) is different from operating channel(%d)",
2378 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2379 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002380 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002381 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002382 goto exit;
2383 }
2384 chan.center_freq = sme_ChnToFreq(channel);
2385
2386 finalLen = bufLen + 24;
2387 finalBuf = vos_mem_malloc(finalLen);
2388 if (NULL == finalBuf)
2389 {
2390 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2391 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002392 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002393 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002394 goto exit;
2395 }
2396 vos_mem_zero(finalBuf, finalLen);
2397
2398 /* Fill subtype */
2399 temp = SIR_MAC_MGMT_ACTION << 4;
2400 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2401
2402 /* Fill type */
2403 temp = SIR_MAC_MGMT_FRAME;
2404 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2405
2406 /* Fill destination address (bssid of the AP) */
2407 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2408
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002409 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002410 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2411
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002412 /* Fill BSSID (AP mac address) */
2413 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002414
2415 /* Fill received buffer from 24th address */
2416 vos_mem_copy(finalBuf + 24, buf, bufLen);
2417
Jeff Johnson11c33152013-04-16 17:52:40 -07002418 /* done with the parsed buffer */
2419 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002420 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002421
Yue Maf49ba872013-08-19 12:04:25 -07002422 wlan_hdd_action( NULL,
2423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2424 &(pAdapter->wdev),
2425#else
2426 dev,
2427#endif
2428 &chan, 0,
2429#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2430 NL80211_CHAN_HT20, 1,
2431#endif
2432 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002433 1, &cookie );
2434 vos_mem_free(finalBuf);
2435 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2437 {
2438 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2439 char extra[32];
2440 tANI_U8 len = 0;
2441
2442 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002443 len = scnprintf(extra, sizeof(extra), "%s %d",
2444 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002445 if (copy_to_user(priv_data.buf, &extra, len + 1))
2446 {
2447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2448 "%s: failed to copy data to user buffer", __func__);
2449 ret = -EFAULT;
2450 goto exit;
2451 }
2452 }
2453 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2454 {
2455 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002456 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002457
2458 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2459 value = value + 19;
2460 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002461 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002462 if (ret < 0)
2463 {
2464 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002465 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002467 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002468 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2469 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2470 ret = -EINVAL;
2471 goto exit;
2472 }
2473
2474 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2475 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2476 {
2477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2478 "lfr mode value %d is out of range"
2479 " (Min: %d Max: %d)", maxTime,
2480 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2481 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2482 ret = -EINVAL;
2483 goto exit;
2484 }
2485
2486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2487 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2488
2489 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2490 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2491 }
2492 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2493 {
2494 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2495 char extra[32];
2496 tANI_U8 len = 0;
2497
2498 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002499 len = scnprintf(extra, sizeof(extra), "%s %d",
2500 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002501 if (copy_to_user(priv_data.buf, &extra, len + 1))
2502 {
2503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2504 "%s: failed to copy data to user buffer", __func__);
2505 ret = -EFAULT;
2506 goto exit;
2507 }
2508 }
2509 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2510 {
2511 tANI_U8 *value = command;
2512 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2513
2514 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2515 value = value + 16;
2516 /* Convert the value from ascii to integer */
2517 ret = kstrtou16(value, 10, &val);
2518 if (ret < 0)
2519 {
2520 /* If the input value is greater than max value of datatype, then also
2521 kstrtou16 fails */
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2523 "%s: kstrtou16 failed range [%d - %d]", __func__,
2524 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2525 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2526 ret = -EINVAL;
2527 goto exit;
2528 }
2529
2530 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2531 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2532 {
2533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2534 "scan home time value %d is out of range"
2535 " (Min: %d Max: %d)", val,
2536 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2537 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2538 ret = -EINVAL;
2539 goto exit;
2540 }
2541
2542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2543 "%s: Received Command to change scan home time = %d", __func__, val);
2544
2545 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2546 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2547 }
2548 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2549 {
2550 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2551 char extra[32];
2552 tANI_U8 len = 0;
2553
2554 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002555 len = scnprintf(extra, sizeof(extra), "%s %d",
2556 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002557 if (copy_to_user(priv_data.buf, &extra, len + 1))
2558 {
2559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2560 "%s: failed to copy data to user buffer", __func__);
2561 ret = -EFAULT;
2562 goto exit;
2563 }
2564 }
2565 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2566 {
2567 tANI_U8 *value = command;
2568 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2569
2570 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2571 value = value + 17;
2572 /* Convert the value from ascii to integer */
2573 ret = kstrtou8(value, 10, &val);
2574 if (ret < 0)
2575 {
2576 /* If the input value is greater than max value of datatype, then also
2577 kstrtou8 fails */
2578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2579 "%s: kstrtou8 failed range [%d - %d]", __func__,
2580 CFG_ROAM_INTRA_BAND_MIN,
2581 CFG_ROAM_INTRA_BAND_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
2586 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2587 (val > CFG_ROAM_INTRA_BAND_MAX))
2588 {
2589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2590 "intra band mode value %d is out of range"
2591 " (Min: %d Max: %d)", val,
2592 CFG_ROAM_INTRA_BAND_MIN,
2593 CFG_ROAM_INTRA_BAND_MAX);
2594 ret = -EINVAL;
2595 goto exit;
2596 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2598 "%s: Received Command to change intra band = %d", __func__, val);
2599
2600 pHddCtx->cfg_ini->nRoamIntraBand = val;
2601 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2602 }
2603 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2604 {
2605 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2606 char extra[32];
2607 tANI_U8 len = 0;
2608
2609 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002610 len = scnprintf(extra, sizeof(extra), "%s %d",
2611 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002612 if (copy_to_user(priv_data.buf, &extra, len + 1))
2613 {
2614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2615 "%s: failed to copy data to user buffer", __func__);
2616 ret = -EFAULT;
2617 goto exit;
2618 }
2619 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002620 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2621 {
2622 tANI_U8 *value = command;
2623 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2624
2625 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2626 value = value + 15;
2627 /* Convert the value from ascii to integer */
2628 ret = kstrtou8(value, 10, &nProbes);
2629 if (ret < 0)
2630 {
2631 /* If the input value is greater than max value of datatype, then also
2632 kstrtou8 fails */
2633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2634 "%s: kstrtou8 failed range [%d - %d]", __func__,
2635 CFG_ROAM_SCAN_N_PROBES_MIN,
2636 CFG_ROAM_SCAN_N_PROBES_MAX);
2637 ret = -EINVAL;
2638 goto exit;
2639 }
2640
2641 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2642 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2643 {
2644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2645 "NProbes value %d is out of range"
2646 " (Min: %d Max: %d)", nProbes,
2647 CFG_ROAM_SCAN_N_PROBES_MIN,
2648 CFG_ROAM_SCAN_N_PROBES_MAX);
2649 ret = -EINVAL;
2650 goto exit;
2651 }
2652
2653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2654 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2655
2656 pHddCtx->cfg_ini->nProbes = nProbes;
2657 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2658 }
2659 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2660 {
2661 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2662 char extra[32];
2663 tANI_U8 len = 0;
2664
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002665 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002666 if (copy_to_user(priv_data.buf, &extra, len + 1))
2667 {
2668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2669 "%s: failed to copy data to user buffer", __func__);
2670 ret = -EFAULT;
2671 goto exit;
2672 }
2673 }
2674 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2675 {
2676 tANI_U8 *value = command;
2677 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2678
2679 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2680 /* input value is in units of msec */
2681 value = value + 20;
2682 /* Convert the value from ascii to integer */
2683 ret = kstrtou16(value, 10, &homeAwayTime);
2684 if (ret < 0)
2685 {
2686 /* If the input value is greater than max value of datatype, then also
2687 kstrtou8 fails */
2688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2689 "%s: kstrtou8 failed range [%d - %d]", __func__,
2690 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2691 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2692 ret = -EINVAL;
2693 goto exit;
2694 }
2695
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002696 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2697 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2698 {
2699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2700 "homeAwayTime value %d is out of range"
2701 " (Min: %d Max: %d)", homeAwayTime,
2702 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2703 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2704 ret = -EINVAL;
2705 goto exit;
2706 }
2707
2708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2709 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002710 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2711 {
2712 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2713 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2714 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002715 }
2716 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2717 {
2718 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2719 char extra[32];
2720 tANI_U8 len = 0;
2721
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002722 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002723 if (copy_to_user(priv_data.buf, &extra, len + 1))
2724 {
2725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2726 "%s: failed to copy data to user buffer", __func__);
2727 ret = -EFAULT;
2728 goto exit;
2729 }
2730 }
2731 else if (strncmp(command, "REASSOC", 7) == 0)
2732 {
2733 tANI_U8 *value = command;
2734 tANI_U8 channel = 0;
2735 tSirMacAddr targetApBssid;
2736 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002737#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2738 tCsrHandoffRequest handoffInfo;
2739#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002740 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002741 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2742
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002743 /* if not associated, no need to proceed with reassoc */
2744 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2745 {
2746 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2747 ret = -EINVAL;
2748 goto exit;
2749 }
2750
2751 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2752 if (eHAL_STATUS_SUCCESS != status)
2753 {
2754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2755 "%s: Failed to parse reassoc command data", __func__);
2756 ret = -EINVAL;
2757 goto exit;
2758 }
2759
2760 /* if the target bssid is same as currently associated AP,
2761 then no need to proceed with reassoc */
2762 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2763 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2764 {
2765 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2766 ret = -EINVAL;
2767 goto exit;
2768 }
2769
2770 /* Check channel number is a valid channel number */
2771 if(VOS_STATUS_SUCCESS !=
2772 wlan_hdd_validate_operation_channel(pAdapter, channel))
2773 {
2774 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002775 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002776 return -EINVAL;
2777 }
2778
2779 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002780#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2781 handoffInfo.channel = channel;
2782 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2783 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2784#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002785 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002786 else if (strncmp(command, "SETWESMODE", 10) == 0)
2787 {
2788 tANI_U8 *value = command;
2789 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2790
2791 /* Move pointer to ahead of SETWESMODE<delimiter> */
2792 value = value + 11;
2793 /* Convert the value from ascii to integer */
2794 ret = kstrtou8(value, 10, &wesMode);
2795 if (ret < 0)
2796 {
2797 /* If the input value is greater than max value of datatype, then also
2798 kstrtou8 fails */
2799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2800 "%s: kstrtou8 failed range [%d - %d]", __func__,
2801 CFG_ENABLE_WES_MODE_NAME_MIN,
2802 CFG_ENABLE_WES_MODE_NAME_MAX);
2803 ret = -EINVAL;
2804 goto exit;
2805 }
2806
2807 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2808 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2809 {
2810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2811 "WES Mode value %d is out of range"
2812 " (Min: %d Max: %d)", wesMode,
2813 CFG_ENABLE_WES_MODE_NAME_MIN,
2814 CFG_ENABLE_WES_MODE_NAME_MAX);
2815 ret = -EINVAL;
2816 goto exit;
2817 }
2818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2819 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2820
2821 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2822 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2823 }
2824 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2825 {
2826 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2827 char extra[32];
2828 tANI_U8 len = 0;
2829
Arif Hussain826d9412013-11-12 16:44:54 -08002830 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002831 if (copy_to_user(priv_data.buf, &extra, len + 1))
2832 {
2833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2834 "%s: failed to copy data to user buffer", __func__);
2835 ret = -EFAULT;
2836 goto exit;
2837 }
2838 }
2839#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002840#ifdef FEATURE_WLAN_LFR
2841 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2842 {
2843 tANI_U8 *value = command;
2844 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2845
2846 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2847 value = value + 12;
2848 /* Convert the value from ascii to integer */
2849 ret = kstrtou8(value, 10, &lfrMode);
2850 if (ret < 0)
2851 {
2852 /* If the input value is greater than max value of datatype, then also
2853 kstrtou8 fails */
2854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2855 "%s: kstrtou8 failed range [%d - %d]", __func__,
2856 CFG_LFR_FEATURE_ENABLED_MIN,
2857 CFG_LFR_FEATURE_ENABLED_MAX);
2858 ret = -EINVAL;
2859 goto exit;
2860 }
2861
2862 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2863 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2864 {
2865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2866 "lfr mode value %d is out of range"
2867 " (Min: %d Max: %d)", lfrMode,
2868 CFG_LFR_FEATURE_ENABLED_MIN,
2869 CFG_LFR_FEATURE_ENABLED_MAX);
2870 ret = -EINVAL;
2871 goto exit;
2872 }
2873
2874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2875 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2876
2877 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2878 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2879 }
2880#endif
2881#ifdef WLAN_FEATURE_VOWIFI_11R
2882 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2883 {
2884 tANI_U8 *value = command;
2885 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2886
2887 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2888 value = value + 18;
2889 /* Convert the value from ascii to integer */
2890 ret = kstrtou8(value, 10, &ft);
2891 if (ret < 0)
2892 {
2893 /* If the input value is greater than max value of datatype, then also
2894 kstrtou8 fails */
2895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2896 "%s: kstrtou8 failed range [%d - %d]", __func__,
2897 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2898 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2899 ret = -EINVAL;
2900 goto exit;
2901 }
2902
2903 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2904 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2905 {
2906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2907 "ft mode value %d is out of range"
2908 " (Min: %d Max: %d)", ft,
2909 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2910 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
2914
2915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2916 "%s: Received Command to change ft mode = %d", __func__, ft);
2917
2918 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2919 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2920 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302921
2922 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2923 {
2924 tANI_U8 *value = command;
2925 tSirMacAddr targetApBssid;
2926 tANI_U8 trigger = 0;
2927 eHalStatus status = eHAL_STATUS_SUCCESS;
2928 hdd_station_ctx_t *pHddStaCtx = NULL;
2929 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2930
2931 /* if not associated, no need to proceed with reassoc */
2932 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2933 {
2934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2935 ret = -EINVAL;
2936 goto exit;
2937 }
2938
2939 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2940 if (eHAL_STATUS_SUCCESS != status)
2941 {
2942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "%s: Failed to parse reassoc command data", __func__);
2944 ret = -EINVAL;
2945 goto exit;
2946 }
2947
2948 /* if the target bssid is same as currently associated AP,
2949 then no need to proceed with reassoc */
2950 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2951 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2952 {
2953 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2954 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2955 __func__);
2956 ret = -EINVAL;
2957 goto exit;
2958 }
2959
2960 /* Proceed with scan/roam */
2961 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2962 &targetApBssid[0],
2963 (tSmeFastRoamTrigger)(trigger));
2964 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002965#endif
2966#ifdef FEATURE_WLAN_CCX
2967 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2968 {
2969 tANI_U8 *value = command;
2970 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2971
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002972 /* Check if the features OKC/CCX/11R are supported simultaneously,
2973 then this operation is not permitted (return FAILURE) */
2974 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2975 hdd_is_okc_mode_enabled(pHddCtx) &&
2976 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2977 {
2978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2979 "%s: OKC/CCX/11R are supported simultaneously"
2980 " hence this operation is not permitted!", __func__);
2981 ret = -EPERM;
2982 goto exit;
2983 }
2984
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002985 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2986 value = value + 11;
2987 /* Convert the value from ascii to integer */
2988 ret = kstrtou8(value, 10, &ccxMode);
2989 if (ret < 0)
2990 {
2991 /* If the input value is greater than max value of datatype, then also
2992 kstrtou8 fails */
2993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2994 "%s: kstrtou8 failed range [%d - %d]", __func__,
2995 CFG_CCX_FEATURE_ENABLED_MIN,
2996 CFG_CCX_FEATURE_ENABLED_MAX);
2997 ret = -EINVAL;
2998 goto exit;
2999 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003000 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3001 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3002 {
3003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3004 "Ccx mode value %d is out of range"
3005 " (Min: %d Max: %d)", ccxMode,
3006 CFG_CCX_FEATURE_ENABLED_MIN,
3007 CFG_CCX_FEATURE_ENABLED_MAX);
3008 ret = -EINVAL;
3009 goto exit;
3010 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3012 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3013
3014 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3015 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3016 }
3017#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003018 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3019 {
3020 tANI_U8 *value = command;
3021 tANI_BOOLEAN roamScanControl = 0;
3022
3023 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3024 value = value + 19;
3025 /* Convert the value from ascii to integer */
3026 ret = kstrtou8(value, 10, &roamScanControl);
3027 if (ret < 0)
3028 {
3029 /* If the input value is greater than max value of datatype, then also
3030 kstrtou8 fails */
3031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3032 "%s: kstrtou8 failed ", __func__);
3033 ret = -EINVAL;
3034 goto exit;
3035 }
3036
3037 if (0 != roamScanControl)
3038 {
3039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3040 "roam scan control invalid value = %d",
3041 roamScanControl);
3042 ret = -EINVAL;
3043 goto exit;
3044 }
3045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3046 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3047
3048 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3049 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003050#ifdef FEATURE_WLAN_OKC
3051 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3052 {
3053 tANI_U8 *value = command;
3054 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3055
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003056 /* Check if the features OKC/CCX/11R are supported simultaneously,
3057 then this operation is not permitted (return FAILURE) */
3058 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3059 hdd_is_okc_mode_enabled(pHddCtx) &&
3060 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3061 {
3062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3063 "%s: OKC/CCX/11R are supported simultaneously"
3064 " hence this operation is not permitted!", __func__);
3065 ret = -EPERM;
3066 goto exit;
3067 }
3068
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003069 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3070 value = value + 11;
3071 /* Convert the value from ascii to integer */
3072 ret = kstrtou8(value, 10, &okcMode);
3073 if (ret < 0)
3074 {
3075 /* If the input value is greater than max value of datatype, then also
3076 kstrtou8 fails */
3077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3078 "%s: kstrtou8 failed range [%d - %d]", __func__,
3079 CFG_OKC_FEATURE_ENABLED_MIN,
3080 CFG_OKC_FEATURE_ENABLED_MAX);
3081 ret = -EINVAL;
3082 goto exit;
3083 }
3084
3085 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3086 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3087 {
3088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3089 "Okc mode value %d is out of range"
3090 " (Min: %d Max: %d)", okcMode,
3091 CFG_OKC_FEATURE_ENABLED_MIN,
3092 CFG_OKC_FEATURE_ENABLED_MAX);
3093 ret = -EINVAL;
3094 goto exit;
3095 }
3096
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3098 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3099
3100 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3101 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003102#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003103 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3104 {
3105 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3106 char extra[32];
3107 tANI_U8 len = 0;
3108
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003109 len = scnprintf(extra, sizeof(extra), "%s %d",
3110 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003111 if (copy_to_user(priv_data.buf, &extra, len + 1))
3112 {
3113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3114 "%s: failed to copy data to user buffer", __func__);
3115 ret = -EFAULT;
3116 goto exit;
3117 }
3118 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303119#ifdef WLAN_FEATURE_PACKET_FILTERING
3120 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3121 {
3122 tANI_U8 filterType = 0;
3123 tANI_U8 *value = command;
3124
3125 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3126 value = value + 22;
3127
3128 /* Convert the value from ascii to integer */
3129 ret = kstrtou8(value, 10, &filterType);
3130 if (ret < 0)
3131 {
3132 /* If the input value is greater than max value of datatype,
3133 * then also kstrtou8 fails
3134 */
3135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3136 "%s: kstrtou8 failed range ", __func__);
3137 ret = -EINVAL;
3138 goto exit;
3139 }
3140
3141 if (filterType != 0 && filterType != 1)
3142 {
3143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3144 "%s: Accepted Values are 0 and 1 ", __func__);
3145 ret = -EINVAL;
3146 goto exit;
3147 }
3148 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3149 pAdapter->sessionId);
3150 }
3151#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303152 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3153 {
3154 char *dhcpPhase;
3155 dhcpPhase = command + 12;
3156 if ('1' == *dhcpPhase)
3157 {
3158 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3159 pAdapter->macAddressCurrent.bytes);
3160 }
3161 else if ('2' == *dhcpPhase)
3162 {
3163 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3164 pAdapter->macAddressCurrent.bytes);
3165 }
3166 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003167 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3168 {
3169 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3170 }
3171 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3172 {
3173 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3174 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303175 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3176 {
3177 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3178 char extra[32];
3179 tANI_U8 len = 0;
3180
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003181 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303182 (int)pCfg->nActiveMaxChnTime);
3183 if (copy_to_user(priv_data.buf, &extra, len + 1))
3184 {
3185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3186 "%s: failed to copy data to user buffer", __func__);
3187 ret = -EFAULT;
3188 goto exit;
3189 }
3190 ret = len;
3191 }
3192 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3193 {
3194 tANI_U8 *value = command;
3195 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3196 int val = 0, temp;
3197
3198 value = value + 13;
3199 temp = kstrtou32(value, 10, &val);
3200 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3201 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3202 {
3203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3204 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3205 ret = -EFAULT;
3206 goto exit;
3207 }
3208 pCfg->nActiveMaxChnTime = val;
3209 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003210 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3211 {
3212 tANI_U8 filterType = 0;
3213 tANI_U8 *value;
3214 value = command + 9;
3215
3216 /* Convert the value from ascii to integer */
3217 ret = kstrtou8(value, 10, &filterType);
3218 if (ret < 0)
3219 {
3220 /* If the input value is greater than max value of datatype,
3221 * then also kstrtou8 fails
3222 */
3223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3224 "%s: kstrtou8 failed range ", __func__);
3225 ret = -EINVAL;
3226 goto exit;
3227 }
3228 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3229 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3230 {
3231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3232 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3233 " 2-Sink ", __func__);
3234 ret = -EINVAL;
3235 goto exit;
3236 }
3237 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3238 pHddCtx->drvr_miracast = filterType;
3239 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3240 }
Leo Chang614d2072013-08-22 14:59:44 -07003241 else if (strncmp(command, "SETMCRATE", 9) == 0)
3242 {
Leo Chang614d2072013-08-22 14:59:44 -07003243 tANI_U8 *value = command;
3244 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003245 tSirRateUpdateInd *rateUpdate;
3246 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003247
3248 /* Only valid for SAP mode */
3249 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3250 {
3251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3252 "%s: SAP mode is not running", __func__);
3253 ret = -EFAULT;
3254 goto exit;
3255 }
3256
3257 /* Move pointer to ahead of SETMCRATE<delimiter> */
3258 /* input value is in units of hundred kbps */
3259 value = value + 10;
3260 /* Convert the value from ascii to integer, decimal base */
3261 ret = kstrtouint(value, 10, &targetRate);
3262
Leo Chang1f98cbd2013-10-17 15:03:52 -07003263 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3264 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003265 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003266 hddLog(VOS_TRACE_LEVEL_ERROR,
3267 "%s: SETMCRATE indication alloc fail", __func__);
3268 ret = -EFAULT;
3269 goto exit;
3270 }
3271 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3272
3273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3274 "MC Target rate %d", targetRate);
3275 /* Ignore unicast */
3276 rateUpdate->ucastDataRate = -1;
3277 rateUpdate->mcastDataRate24GHz = targetRate;
3278 rateUpdate->mcastDataRate5GHz = targetRate;
3279 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3280 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3281 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3282 if (eHAL_STATUS_SUCCESS != status)
3283 {
3284 hddLog(VOS_TRACE_LEVEL_ERROR,
3285 "%s: SET_MC_RATE failed", __func__);
3286 vos_mem_free(rateUpdate);
3287 ret = -EFAULT;
3288 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003289 }
3290 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303291#ifdef FEATURE_WLAN_BATCH_SCAN
3292 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3293 {
3294 char extra[32];
3295 tANI_U8 len = 0;
3296 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3297
3298 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3299 {
3300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3301 "%s: Batch scan feature is not supported by FW", __func__);
3302 ret = -EINVAL;
3303 goto exit;
3304 }
3305
3306 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3307 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3308 {
3309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3310 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3311 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3312 " mode",
3313 pAdapter->device_mode);
3314 ret = -EINVAL;
3315 goto exit;
3316 }
3317
Arif Hussain826d9412013-11-12 16:44:54 -08003318 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303319 version);
3320 if (copy_to_user(priv_data.buf, &extra, len + 1))
3321 {
3322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3323 "%s: failed to copy data to user buffer", __func__);
3324 ret = -EFAULT;
3325 goto exit;
3326 }
3327 ret = HDD_BATCH_SCAN_VERSION;
3328 }
3329 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3330 {
3331 int status;
3332 tANI_U8 *value = (command + 16);
3333 eHalStatus halStatus;
3334 unsigned long rc;
3335 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3336 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3337
3338 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3339 {
3340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3341 "%s: Batch scan feature is not supported by FW", __func__);
3342 ret = -EINVAL;
3343 goto exit;
3344 }
3345
Rajeev Kumar20140c12013-10-21 19:39:02 -07003346
Rajeev79dbe4c2013-10-05 11:03:42 +05303347 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
Rajeev Kumar5286bb92013-12-05 11:52:10 -08003348 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
3349 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
Rajeev79dbe4c2013-10-05 11:03:42 +05303350 {
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003352 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303353 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3354 pAdapter->device_mode);
3355 ret = -EINVAL;
3356 goto exit;
3357 }
3358
Rajeev Kumar20140c12013-10-21 19:39:02 -07003359
Rajeev79dbe4c2013-10-05 11:03:42 +05303360 status = hdd_parse_set_batchscan_command(value, pReq);
3361 if (status)
3362 {
3363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003364 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303365 ret = -EINVAL;
3366 goto exit;
3367 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003368
3369
Rajeev79dbe4c2013-10-05 11:03:42 +05303370 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3371 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3372 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3373 pAdapter);
3374
3375 if ( eHAL_STATUS_SUCCESS == halStatus )
3376 {
3377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3378 "sme_SetBatchScanReq returned success halStatus %d",
3379 halStatus);
3380 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3381 {
3382 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3383 rc = wait_for_completion_timeout(
3384 &pAdapter->hdd_set_batch_scan_req_var,
3385 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3386 if (0 == rc)
3387 {
3388 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3389 "%s: Timeout waiting for set batch scan to complete",
3390 __func__);
3391 ret = -EINVAL;
3392 goto exit;
3393 }
3394 }
3395 if ( !pRsp->nScansToBatch )
3396 {
3397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3398 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003399 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303400 ret = -EINVAL;
3401 goto exit;
3402 }
3403 /*As per the Batch Scan Framework API we should return the MIN of
3404 either MSCAN or the max # of scans firmware can cache*/
3405 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3406
Rajeev Kumar20140c12013-10-21 19:39:02 -07003407 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3408
Rajeev79dbe4c2013-10-05 11:03:42 +05303409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "%s: request MSCAN %d response MSCAN %d ret %d",
3411 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3412 }
3413 else
3414 {
3415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3416 "sme_SetBatchScanReq returned failure halStatus %d",
3417 halStatus);
3418 ret = -EINVAL;
3419 goto exit;
3420 }
3421 }
3422 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3423 {
3424 eHalStatus halStatus;
3425 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3426 pInd->param = 0;
3427
3428 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3429 {
3430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3431 "%s: Batch scan feature is not supported by FW", __func__);
3432 ret = -EINVAL;
3433 goto exit;
3434 }
3435
Rajeev Kumar20140c12013-10-21 19:39:02 -07003436 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303437 {
3438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003439 "Batch scan is not yet enabled batch scan state %d",
3440 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303441 ret = -EINVAL;
3442 goto exit;
3443 }
3444
Rajeev Kumar20140c12013-10-21 19:39:02 -07003445 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3446
Rajeev79dbe4c2013-10-05 11:03:42 +05303447 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3448 pAdapter->sessionId);
3449 if ( eHAL_STATUS_SUCCESS == halStatus )
3450 {
3451 ret = 0;
3452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3453 "sme_StopBatchScanInd returned success halStatus %d",
3454 halStatus);
3455 }
3456 else
3457 {
3458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3459 "sme_StopBatchScanInd returned failure halStatus %d",
3460 halStatus);
3461 ret = -EINVAL;
3462 goto exit;
3463 }
3464 }
3465 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3466 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003467 tANI_U32 remain_len;
3468
Rajeev79dbe4c2013-10-05 11:03:42 +05303469 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3470 {
3471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3472 "%s: Batch scan feature is not supported by FW", __func__);
3473 ret = -EINVAL;
3474 goto exit;
3475 }
3476
Rajeev Kumar20140c12013-10-21 19:39:02 -07003477 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303478 {
3479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003480 "Batch scan is not yet enabled could not return results"
3481 "Batch Scan state %d",
3482 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303483 ret = -EINVAL;
3484 goto exit;
3485 }
3486
3487 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003488 remain_len = priv_data.total_len - priv_data.used_len;
3489 if (remain_len < priv_data.total_len)
3490 {
3491 /*Clear previous batch scan response data if any*/
3492 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3493 }
3494 else
3495 {
3496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3497 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003498 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003499 priv_data.total_len, priv_data.used_len, remain_len);
3500 ret = -EINVAL;
3501 goto exit;
3502 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303503 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3504 }
3505#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003506#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3507 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3508 {
3509 tANI_U8 *value = command;
3510 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3511 tANI_U8 numChannels = 0;
3512 eHalStatus status = eHAL_STATUS_SUCCESS;
3513
3514 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3515 if (eHAL_STATUS_SUCCESS != status)
3516 {
3517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3518 "%s: Failed to parse channel list information", __func__);
3519 ret = -EINVAL;
3520 goto exit;
3521 }
3522
3523 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3524 {
3525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3526 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3527 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3528 ret = -EINVAL;
3529 goto exit;
3530 }
3531 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3532 ChannelList,
3533 numChannels);
3534 if (eHAL_STATUS_SUCCESS != status)
3535 {
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3537 "%s: Failed to update channel list information", __func__);
3538 ret = -EINVAL;
3539 goto exit;
3540 }
3541 }
3542 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3543 {
3544 tANI_U8 *value = command;
3545 char extra[128] = {0};
3546 int len = 0;
3547 tANI_U8 tid = 0;
3548 hdd_station_ctx_t *pHddStaCtx = NULL;
3549 tAniTrafStrmMetrics tsmMetrics;
3550 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3551
3552 /* if not associated, return error */
3553 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3554 {
3555 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3556 ret = -EINVAL;
3557 goto exit;
3558 }
3559
3560 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3561 value = value + 12;
3562 /* Convert the value from ascii to integer */
3563 ret = kstrtou8(value, 10, &tid);
3564 if (ret < 0)
3565 {
3566 /* If the input value is greater than max value of datatype, then also
3567 kstrtou8 fails */
3568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3569 "%s: kstrtou8 failed range [%d - %d]", __func__,
3570 TID_MIN_VALUE,
3571 TID_MAX_VALUE);
3572 ret = -EINVAL;
3573 goto exit;
3574 }
3575
3576 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3577 {
3578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3579 "tid value %d is out of range"
3580 " (Min: %d Max: %d)", tid,
3581 TID_MIN_VALUE,
3582 TID_MAX_VALUE);
3583 ret = -EINVAL;
3584 goto exit;
3585 }
3586
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3588 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3589
3590 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3591 {
3592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3593 "%s: failed to get tsm stats", __func__);
3594 ret = -EFAULT;
3595 goto exit;
3596 }
3597
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3599 "UplinkPktQueueDly(%d)\n"
3600 "UplinkPktQueueDlyHist[0](%d)\n"
3601 "UplinkPktQueueDlyHist[1](%d)\n"
3602 "UplinkPktQueueDlyHist[2](%d)\n"
3603 "UplinkPktQueueDlyHist[3](%d)\n"
3604 "UplinkPktTxDly(%lu)\n"
3605 "UplinkPktLoss(%d)\n"
3606 "UplinkPktCount(%d)\n"
3607 "RoamingCount(%d)\n"
3608 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3609 tsmMetrics.UplinkPktQueueDlyHist[0],
3610 tsmMetrics.UplinkPktQueueDlyHist[1],
3611 tsmMetrics.UplinkPktQueueDlyHist[2],
3612 tsmMetrics.UplinkPktQueueDlyHist[3],
3613 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3614 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3615
3616 /* Output TSM stats is of the format
3617 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3618 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003619 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003620 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3621 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3622 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3623 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3624 tsmMetrics.RoamingDly);
3625
3626 if (copy_to_user(priv_data.buf, &extra, len + 1))
3627 {
3628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3629 "%s: failed to copy data to user buffer", __func__);
3630 ret = -EFAULT;
3631 goto exit;
3632 }
3633 }
3634 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3635 {
3636 tANI_U8 *value = command;
3637 tANI_U8 *cckmIe = NULL;
3638 tANI_U8 cckmIeLen = 0;
3639 eHalStatus status = eHAL_STATUS_SUCCESS;
3640
3641 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3642 if (eHAL_STATUS_SUCCESS != status)
3643 {
3644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3645 "%s: Failed to parse cckm ie data", __func__);
3646 ret = -EINVAL;
3647 goto exit;
3648 }
3649
3650 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3651 {
3652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3653 "%s: CCKM Ie input length is more than max[%d]", __func__,
3654 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003655 vos_mem_free(cckmIe);
3656 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003657 ret = -EINVAL;
3658 goto exit;
3659 }
3660 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003661 vos_mem_free(cckmIe);
3662 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003663 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003664 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3665 {
3666 tANI_U8 *value = command;
3667 tCsrCcxBeaconReq ccxBcnReq;
3668 eHalStatus status = eHAL_STATUS_SUCCESS;
3669 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3670 if (eHAL_STATUS_SUCCESS != status)
3671 {
3672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3673 "%s: Failed to parse ccx beacon req", __func__);
3674 ret = -EINVAL;
3675 goto exit;
3676 }
3677
3678 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3679 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003680#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003681 else {
3682 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3683 __func__, command);
3684 }
3685
Jeff Johnson295189b2012-06-20 16:38:30 -07003686 }
3687exit:
3688 if (command)
3689 {
3690 kfree(command);
3691 }
3692 return ret;
3693}
3694
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003695
3696
3697#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003698/**---------------------------------------------------------------------------
3699
3700 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3701
3702 This function parses the ccx beacon request passed in the format
3703 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3704 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3705 <space>Scan Mode N<space>Meas Duration N
3706 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3707 then take N.
3708 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3709 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3710 This function does not take care of removing duplicate channels from the list
3711
3712 \param - pValue Pointer to data
3713 \param - pCcxBcnReq output pointer to store parsed ie information
3714
3715 \return - 0 for success non-zero for failure
3716
3717 --------------------------------------------------------------------------*/
3718static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3719 tCsrCcxBeaconReq *pCcxBcnReq)
3720{
3721 tANI_U8 *inPtr = pValue;
3722 int tempInt = 0;
3723 int j = 0, i = 0, v = 0;
3724 char buf[32];
3725
3726 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3727 /*no argument after the command*/
3728 if (NULL == inPtr)
3729 {
3730 return -EINVAL;
3731 }
3732 /*no space after the command*/
3733 else if (SPACE_ASCII_VALUE != *inPtr)
3734 {
3735 return -EINVAL;
3736 }
3737
3738 /*removing empty spaces*/
3739 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3740
3741 /*no argument followed by spaces*/
3742 if ('\0' == *inPtr) return -EINVAL;
3743
3744 /*getting the first argument ie measurement token*/
3745 v = sscanf(inPtr, "%32s ", buf);
3746 if (1 != v) return -EINVAL;
3747
3748 v = kstrtos32(buf, 10, &tempInt);
3749 if ( v < 0) return -EINVAL;
3750
3751 pCcxBcnReq->numBcnReqIe = tempInt;
3752
3753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3754 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3755
3756 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3757 {
3758 for (i = 0; i < 4; i++)
3759 {
3760 /*inPtr pointing to the beginning of first space after number of ie fields*/
3761 inPtr = strpbrk( inPtr, " " );
3762 /*no ie data after the number of ie fields argument*/
3763 if (NULL == inPtr) return -EINVAL;
3764
3765 /*removing empty space*/
3766 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3767
3768 /*no ie data after the number of ie fields argument and spaces*/
3769 if ( '\0' == *inPtr ) return -EINVAL;
3770
3771 v = sscanf(inPtr, "%32s ", buf);
3772 if (1 != v) return -EINVAL;
3773
3774 v = kstrtos32(buf, 10, &tempInt);
3775 if (v < 0) return -EINVAL;
3776
3777 switch (i)
3778 {
3779 case 0: /* Measurement token */
3780 if (tempInt <= 0)
3781 {
3782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 "Invalid Measurement Token(%d)", tempInt);
3784 return -EINVAL;
3785 }
3786 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3787 break;
3788
3789 case 1: /* Channel number */
3790 if ((tempInt <= 0) ||
3791 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3792 {
3793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3794 "Invalid Channel Number(%d)", tempInt);
3795 return -EINVAL;
3796 }
3797 pCcxBcnReq->bcnReq[j].channel = tempInt;
3798 break;
3799
3800 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003801 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003802 {
3803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3804 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3805 return -EINVAL;
3806 }
3807 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3808 break;
3809
3810 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003811 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3812 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003813 {
3814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3815 "Invalid Measurement Duration(%d)", tempInt);
3816 return -EINVAL;
3817 }
3818 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3819 break;
3820 }
3821 }
3822 }
3823
3824 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3825 {
3826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3827 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3828 j,
3829 pCcxBcnReq->bcnReq[j].measurementToken,
3830 pCcxBcnReq->bcnReq[j].channel,
3831 pCcxBcnReq->bcnReq[j].scanMode,
3832 pCcxBcnReq->bcnReq[j].measurementDuration);
3833 }
3834
3835 return VOS_STATUS_SUCCESS;
3836}
3837
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003838static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3839{
3840 struct statsContext *pStatsContext = NULL;
3841 hdd_adapter_t *pAdapter = NULL;
3842
3843 if (NULL == pContext)
3844 {
3845 hddLog(VOS_TRACE_LEVEL_ERROR,
3846 "%s: Bad param, pContext [%p]",
3847 __func__, pContext);
3848 return;
3849 }
3850
Jeff Johnson72a40512013-12-19 10:14:15 -08003851 /* there is a race condition that exists between this callback
3852 function and the caller since the caller could time out either
3853 before or while this code is executing. we use a spinlock to
3854 serialize these actions */
3855 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003856
3857 pStatsContext = pContext;
3858 pAdapter = pStatsContext->pAdapter;
3859 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3860 {
3861 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003862 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003863 hddLog(VOS_TRACE_LEVEL_WARN,
3864 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3865 __func__, pAdapter, pStatsContext->magic);
3866 return;
3867 }
3868
Jeff Johnson72a40512013-12-19 10:14:15 -08003869 /* context is valid so caller is still waiting */
3870
3871 /* paranoia: invalidate the magic */
3872 pStatsContext->magic = 0;
3873
3874 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003875 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3876 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3877 tsmMetrics.UplinkPktQueueDlyHist,
3878 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3879 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3880 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3881 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3882 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3883 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3884 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3885
Jeff Johnson72a40512013-12-19 10:14:15 -08003886 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003887 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003888
3889 /* serialization is complete */
3890 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003891}
3892
3893
3894
3895static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3896 tAniTrafStrmMetrics* pTsmMetrics)
3897{
3898 hdd_station_ctx_t *pHddStaCtx = NULL;
3899 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003900 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003901 long lrc;
3902 struct statsContext context;
3903 hdd_context_t *pHddCtx = NULL;
3904
3905 if (NULL == pAdapter)
3906 {
3907 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3908 return VOS_STATUS_E_FAULT;
3909 }
3910
3911 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3912 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3913
3914 /* we are connected prepare our callback context */
3915 init_completion(&context.completion);
3916 context.pAdapter = pAdapter;
3917 context.magic = STATS_CONTEXT_MAGIC;
3918
3919 /* query tsm stats */
3920 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3921 pHddStaCtx->conn_info.staId[ 0 ],
3922 pHddStaCtx->conn_info.bssId,
3923 &context, pHddCtx->pvosContext, tid);
3924
3925 if (eHAL_STATUS_SUCCESS != hstatus)
3926 {
Jeff Johnson72a40512013-12-19 10:14:15 -08003927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
3928 __func__);
3929 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003930 }
3931 else
3932 {
3933 /* request was sent -- wait for the response */
3934 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3935 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003936 if (lrc <= 0)
3937 {
3938 hddLog(VOS_TRACE_LEVEL_ERROR,
3939 "%s: SME %s while retrieving statistics",
3940 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08003941 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003942 }
3943 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003944
Jeff Johnson72a40512013-12-19 10:14:15 -08003945 /* either we never sent a request, we sent a request and received a
3946 response or we sent a request and timed out. if we never sent a
3947 request or if we sent a request and got a response, we want to
3948 clear the magic out of paranoia. if we timed out there is a
3949 race condition such that the callback function could be
3950 executing at the same time we are. of primary concern is if the
3951 callback function had already verified the "magic" but had not
3952 yet set the completion variable when a timeout occurred. we
3953 serialize these activities by invalidating the magic while
3954 holding a shared spinlock which will cause us to block if the
3955 callback is currently executing */
3956 spin_lock(&hdd_context_lock);
3957 context.magic = 0;
3958 spin_unlock(&hdd_context_lock);
3959
3960 if (VOS_STATUS_SUCCESS == vstatus)
3961 {
3962 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3963 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3964 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3965 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3966 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3967 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3968 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3969 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3970 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3971 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3972 }
3973 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003974}
3975#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3976
Srinivas Girigowdade697412013-02-14 16:31:48 -08003977#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3978void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3979{
3980 eCsrBand band = -1;
3981 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3982 switch (band)
3983 {
3984 case eCSR_BAND_ALL:
3985 *pBand = WLAN_HDD_UI_BAND_AUTO;
3986 break;
3987
3988 case eCSR_BAND_24:
3989 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3990 break;
3991
3992 case eCSR_BAND_5G:
3993 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3994 break;
3995
3996 default:
3997 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3998 *pBand = -1;
3999 break;
4000 }
4001}
4002
4003/**---------------------------------------------------------------------------
4004
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004005 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4006
4007 This function parses the send action frame data passed in the format
4008 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4009
Srinivas Girigowda56076852013-08-20 14:00:50 -07004010 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004011 \param - pTargetApBssid Pointer to target Ap bssid
4012 \param - pChannel Pointer to the Target AP channel
4013 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4014 \param - pBuf Pointer to data
4015 \param - pBufLen Pointer to data length
4016
4017 \return - 0 for success non-zero for failure
4018
4019 --------------------------------------------------------------------------*/
4020VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4021 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4022{
4023 tANI_U8 *inPtr = pValue;
4024 tANI_U8 *dataEnd;
4025 int tempInt;
4026 int j = 0;
4027 int i = 0;
4028 int v = 0;
4029 tANI_U8 tempBuf[32];
4030 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004031 /* 12 hexa decimal digits and 5 ':' */
4032 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004033
4034 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4035 /*no argument after the command*/
4036 if (NULL == inPtr)
4037 {
4038 return -EINVAL;
4039 }
4040
4041 /*no space after the command*/
4042 else if (SPACE_ASCII_VALUE != *inPtr)
4043 {
4044 return -EINVAL;
4045 }
4046
4047 /*removing empty spaces*/
4048 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4049
4050 /*no argument followed by spaces*/
4051 if ('\0' == *inPtr)
4052 {
4053 return -EINVAL;
4054 }
4055
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004056 v = sscanf(inPtr, "%17s", macAddress);
4057 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004058 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4060 "Invalid MAC address or All hex inputs are not read (%d)", v);
4061 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004062 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004063
4064 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4065 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4066 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4067 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4068 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4069 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004070
4071 /* point to the next argument */
4072 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4073 /*no argument after the command*/
4074 if (NULL == inPtr) return -EINVAL;
4075
4076 /*removing empty spaces*/
4077 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4078
4079 /*no argument followed by spaces*/
4080 if ('\0' == *inPtr)
4081 {
4082 return -EINVAL;
4083 }
4084
4085 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004086 v = sscanf(inPtr, "%32s ", tempBuf);
4087 if (1 != v) return -EINVAL;
4088
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004089 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304090 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4091 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004092
4093 *pChannel = tempInt;
4094
4095 /* point to the next argument */
4096 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4097 /*no argument after the command*/
4098 if (NULL == inPtr) return -EINVAL;
4099 /*removing empty spaces*/
4100 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4101
4102 /*no argument followed by spaces*/
4103 if ('\0' == *inPtr)
4104 {
4105 return -EINVAL;
4106 }
4107
4108 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004109 v = sscanf(inPtr, "%32s ", tempBuf);
4110 if (1 != v) return -EINVAL;
4111
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004112 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304113 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004114
4115 *pDwellTime = tempInt;
4116
4117 /* point to the next argument */
4118 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4119 /*no argument after the command*/
4120 if (NULL == inPtr) return -EINVAL;
4121 /*removing empty spaces*/
4122 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4123
4124 /*no argument followed by spaces*/
4125 if ('\0' == *inPtr)
4126 {
4127 return -EINVAL;
4128 }
4129
4130 /* find the length of data */
4131 dataEnd = inPtr;
4132 while(('\0' != *dataEnd) )
4133 {
4134 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004135 }
Kiet Lambe150c22013-11-21 16:30:32 +05304136 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004137 if ( *pBufLen <= 0) return -EINVAL;
4138
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004139 /* Allocate the number of bytes based on the number of input characters
4140 whether it is even or odd.
4141 if the number of input characters are even, then we need N/2 byte.
4142 if the number of input characters are odd, then we need do (N+1)/2 to
4143 compensate rounding off.
4144 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4145 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4146 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004147 if (NULL == *pBuf)
4148 {
4149 hddLog(VOS_TRACE_LEVEL_FATAL,
4150 "%s: vos_mem_alloc failed ", __func__);
4151 return -EINVAL;
4152 }
4153
4154 /* the buffer received from the upper layer is character buffer,
4155 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4156 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4157 and f0 in 3rd location */
4158 for (i = 0, j = 0; j < *pBufLen; j += 2)
4159 {
Kiet Lambe150c22013-11-21 16:30:32 +05304160 if( j+1 == *pBufLen)
4161 {
4162 tempByte = hdd_parse_hex(inPtr[j]);
4163 }
4164 else
4165 {
4166 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4167 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004168 (*pBuf)[i++] = tempByte;
4169 }
4170 *pBufLen = i;
4171 return VOS_STATUS_SUCCESS;
4172}
4173
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004174/**---------------------------------------------------------------------------
4175
Srinivas Girigowdade697412013-02-14 16:31:48 -08004176 \brief hdd_parse_channellist() - HDD Parse channel list
4177
4178 This function parses the channel list passed in the format
4179 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004180 if the Number of channels (N) does not match with the actual number of channels passed
4181 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4182 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4183 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4184 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004185
4186 \param - pValue Pointer to input channel list
4187 \param - ChannelList Pointer to local output array to record channel list
4188 \param - pNumChannels Pointer to number of roam scan channels
4189
4190 \return - 0 for success non-zero for failure
4191
4192 --------------------------------------------------------------------------*/
4193VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4194{
4195 tANI_U8 *inPtr = pValue;
4196 int tempInt;
4197 int j = 0;
4198 int v = 0;
4199 char buf[32];
4200
4201 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4202 /*no argument after the command*/
4203 if (NULL == inPtr)
4204 {
4205 return -EINVAL;
4206 }
4207
4208 /*no space after the command*/
4209 else if (SPACE_ASCII_VALUE != *inPtr)
4210 {
4211 return -EINVAL;
4212 }
4213
4214 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004215 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004216
4217 /*no argument followed by spaces*/
4218 if ('\0' == *inPtr)
4219 {
4220 return -EINVAL;
4221 }
4222
4223 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004224 v = sscanf(inPtr, "%32s ", buf);
4225 if (1 != v) return -EINVAL;
4226
Srinivas Girigowdade697412013-02-14 16:31:48 -08004227 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004228 if ((v < 0) ||
4229 (tempInt <= 0) ||
4230 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4231 {
4232 return -EINVAL;
4233 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004234
4235 *pNumChannels = tempInt;
4236
4237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4238 "Number of channels are: %d", *pNumChannels);
4239
4240 for (j = 0; j < (*pNumChannels); j++)
4241 {
4242 /*inPtr pointing to the beginning of first space after number of channels*/
4243 inPtr = strpbrk( inPtr, " " );
4244 /*no channel list after the number of channels argument*/
4245 if (NULL == inPtr)
4246 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004247 if (0 != j)
4248 {
4249 *pNumChannels = j;
4250 return VOS_STATUS_SUCCESS;
4251 }
4252 else
4253 {
4254 return -EINVAL;
4255 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004256 }
4257
4258 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004259 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004260
4261 /*no channel list after the number of channels argument and spaces*/
4262 if ( '\0' == *inPtr )
4263 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004264 if (0 != j)
4265 {
4266 *pNumChannels = j;
4267 return VOS_STATUS_SUCCESS;
4268 }
4269 else
4270 {
4271 return -EINVAL;
4272 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004273 }
4274
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004275 v = sscanf(inPtr, "%32s ", buf);
4276 if (1 != v) return -EINVAL;
4277
Srinivas Girigowdade697412013-02-14 16:31:48 -08004278 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004279 if ((v < 0) ||
4280 (tempInt <= 0) ||
4281 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4282 {
4283 return -EINVAL;
4284 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004285 pChannelList[j] = tempInt;
4286
4287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4288 "Channel %d added to preferred channel list",
4289 pChannelList[j] );
4290 }
4291
Srinivas Girigowdade697412013-02-14 16:31:48 -08004292 return VOS_STATUS_SUCCESS;
4293}
4294
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004295
4296/**---------------------------------------------------------------------------
4297
4298 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4299
4300 This function parses the reasoc command data passed in the format
4301 REASSOC<space><bssid><space><channel>
4302
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004303 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004304 \param - pTargetApBssid Pointer to target Ap bssid
4305 \param - pChannel Pointer to the Target AP channel
4306
4307 \return - 0 for success non-zero for failure
4308
4309 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004310VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4311 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004312{
4313 tANI_U8 *inPtr = pValue;
4314 int tempInt;
4315 int v = 0;
4316 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004317 /* 12 hexa decimal digits and 5 ':' */
4318 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004319
4320 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4321 /*no argument after the command*/
4322 if (NULL == inPtr)
4323 {
4324 return -EINVAL;
4325 }
4326
4327 /*no space after the command*/
4328 else if (SPACE_ASCII_VALUE != *inPtr)
4329 {
4330 return -EINVAL;
4331 }
4332
4333 /*removing empty spaces*/
4334 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4335
4336 /*no argument followed by spaces*/
4337 if ('\0' == *inPtr)
4338 {
4339 return -EINVAL;
4340 }
4341
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004342 v = sscanf(inPtr, "%17s", macAddress);
4343 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004344 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4346 "Invalid MAC address or All hex inputs are not read (%d)", v);
4347 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004348 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004349
4350 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4351 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4352 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4353 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4354 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4355 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004356
4357 /* point to the next argument */
4358 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4359 /*no argument after the command*/
4360 if (NULL == inPtr) return -EINVAL;
4361
4362 /*removing empty spaces*/
4363 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4364
4365 /*no argument followed by spaces*/
4366 if ('\0' == *inPtr)
4367 {
4368 return -EINVAL;
4369 }
4370
4371 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004372 v = sscanf(inPtr, "%32s ", tempBuf);
4373 if (1 != v) return -EINVAL;
4374
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004375 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004376 if ((v < 0) ||
4377 (tempInt <= 0) ||
4378 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4379 {
4380 return -EINVAL;
4381 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004382
4383 *pChannel = tempInt;
4384 return VOS_STATUS_SUCCESS;
4385}
4386
4387#endif
4388
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004389#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4390/**---------------------------------------------------------------------------
4391
4392 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4393
4394 This function parses the SETCCKM IE command
4395 SETCCKMIE<space><ie data>
4396
4397 \param - pValue Pointer to input data
4398 \param - pCckmIe Pointer to output cckm Ie
4399 \param - pCckmIeLen Pointer to output cckm ie length
4400
4401 \return - 0 for success non-zero for failure
4402
4403 --------------------------------------------------------------------------*/
4404VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4405 tANI_U8 *pCckmIeLen)
4406{
4407 tANI_U8 *inPtr = pValue;
4408 tANI_U8 *dataEnd;
4409 int j = 0;
4410 int i = 0;
4411 tANI_U8 tempByte = 0;
4412
4413 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4414 /*no argument after the command*/
4415 if (NULL == inPtr)
4416 {
4417 return -EINVAL;
4418 }
4419
4420 /*no space after the command*/
4421 else if (SPACE_ASCII_VALUE != *inPtr)
4422 {
4423 return -EINVAL;
4424 }
4425
4426 /*removing empty spaces*/
4427 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4428
4429 /*no argument followed by spaces*/
4430 if ('\0' == *inPtr)
4431 {
4432 return -EINVAL;
4433 }
4434
4435 /* find the length of data */
4436 dataEnd = inPtr;
4437 while(('\0' != *dataEnd) )
4438 {
4439 dataEnd++;
4440 ++(*pCckmIeLen);
4441 }
4442 if ( *pCckmIeLen <= 0) return -EINVAL;
4443
4444 /* Allocate the number of bytes based on the number of input characters
4445 whether it is even or odd.
4446 if the number of input characters are even, then we need N/2 byte.
4447 if the number of input characters are odd, then we need do (N+1)/2 to
4448 compensate rounding off.
4449 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4450 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4451 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4452 if (NULL == *pCckmIe)
4453 {
4454 hddLog(VOS_TRACE_LEVEL_FATAL,
4455 "%s: vos_mem_alloc failed ", __func__);
4456 return -EINVAL;
4457 }
4458 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4459 /* the buffer received from the upper layer is character buffer,
4460 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4461 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4462 and f0 in 3rd location */
4463 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4464 {
4465 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4466 (*pCckmIe)[i++] = tempByte;
4467 }
4468 *pCckmIeLen = i;
4469
4470 return VOS_STATUS_SUCCESS;
4471}
4472#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4473
Jeff Johnson295189b2012-06-20 16:38:30 -07004474/**---------------------------------------------------------------------------
4475
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004476 \brief hdd_is_valid_mac_address() - Validate MAC address
4477
4478 This function validates whether the given MAC address is valid or not
4479 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4480 where X is the hexa decimal digit character and separated by ':'
4481 This algorithm works even if MAC address is not separated by ':'
4482
4483 This code checks given input string mac contains exactly 12 hexadecimal digits.
4484 and a separator colon : appears in the input string only after
4485 an even number of hex digits.
4486
4487 \param - pMacAddr pointer to the input MAC address
4488 \return - 1 for valid and 0 for invalid
4489
4490 --------------------------------------------------------------------------*/
4491
4492v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4493{
4494 int xdigit = 0;
4495 int separator = 0;
4496 while (*pMacAddr)
4497 {
4498 if (isxdigit(*pMacAddr))
4499 {
4500 xdigit++;
4501 }
4502 else if (':' == *pMacAddr)
4503 {
4504 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4505 break;
4506
4507 ++separator;
4508 }
4509 else
4510 {
4511 separator = -1;
4512 /* Invalid MAC found */
4513 return 0;
4514 }
4515 ++pMacAddr;
4516 }
4517 return (xdigit == 12 && (separator == 5 || separator == 0));
4518}
4519
4520/**---------------------------------------------------------------------------
4521
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 \brief hdd_open() - HDD Open function
4523
4524 This is called in response to ifconfig up
4525
4526 \param - dev Pointer to net_device structure
4527
4528 \return - 0 for success non-zero for failure
4529
4530 --------------------------------------------------------------------------*/
4531int hdd_open (struct net_device *dev)
4532{
4533 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4534 hdd_context_t *pHddCtx;
4535 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4536 VOS_STATUS status;
4537 v_BOOL_t in_standby = TRUE;
4538
4539 if (NULL == pAdapter)
4540 {
4541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004542 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004543 return -ENODEV;
4544 }
4545
4546 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4547 if (NULL == pHddCtx)
4548 {
4549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004550 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004551 return -ENODEV;
4552 }
4553
4554 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4555 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4556 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004557 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4558 {
4559 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304560 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004561 in_standby = FALSE;
4562 break;
4563 }
4564 else
4565 {
4566 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4567 pAdapterNode = pNext;
4568 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004569 }
4570
4571 if (TRUE == in_standby)
4572 {
4573 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4574 {
4575 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4576 "wlan out of power save", __func__);
4577 return -EINVAL;
4578 }
4579 }
4580
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004581 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004582 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4583 {
4584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004585 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 /* Enable TX queues only when we are connected */
4587 netif_tx_start_all_queues(dev);
4588 }
4589
4590 return 0;
4591}
4592
4593int hdd_mon_open (struct net_device *dev)
4594{
4595 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4596
4597 if(pAdapter == NULL) {
4598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004599 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004600 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 }
4602
4603 netif_start_queue(dev);
4604
4605 return 0;
4606}
4607/**---------------------------------------------------------------------------
4608
4609 \brief hdd_stop() - HDD stop function
4610
4611 This is called in response to ifconfig down
4612
4613 \param - dev Pointer to net_device structure
4614
4615 \return - 0 for success non-zero for failure
4616
4617 --------------------------------------------------------------------------*/
4618
4619int hdd_stop (struct net_device *dev)
4620{
4621 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4622 hdd_context_t *pHddCtx;
4623 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4624 VOS_STATUS status;
4625 v_BOOL_t enter_standby = TRUE;
4626
4627 ENTER();
4628
4629 if (NULL == pAdapter)
4630 {
4631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004632 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004633 return -ENODEV;
4634 }
4635
4636 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4637 if (NULL == pHddCtx)
4638 {
4639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004640 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 return -ENODEV;
4642 }
4643
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004644 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4646 netif_tx_disable(pAdapter->dev);
4647 netif_carrier_off(pAdapter->dev);
4648
4649
4650 /* SoftAP ifaces should never go in power save mode
4651 making sure same here. */
4652 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4653 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004655 )
4656 {
4657 /* SoftAP mode, so return from here */
4658 EXIT();
4659 return 0;
4660 }
4661
4662 /* Find if any iface is up then
4663 if any iface is up then can't put device to sleep/ power save mode. */
4664 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4665 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4666 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004667 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4668 {
4669 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304670 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004671 enter_standby = FALSE;
4672 break;
4673 }
4674 else
4675 {
4676 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4677 pAdapterNode = pNext;
4678 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004679 }
4680
4681 if (TRUE == enter_standby)
4682 {
4683 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4684 "entering standby", __func__);
4685 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4686 {
4687 /*log and return success*/
4688 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4689 "wlan in power save", __func__);
4690 }
4691 }
4692
4693 EXIT();
4694 return 0;
4695}
4696
4697/**---------------------------------------------------------------------------
4698
4699 \brief hdd_uninit() - HDD uninit function
4700
4701 This is called during the netdev unregister to uninitialize all data
4702associated with the device
4703
4704 \param - dev Pointer to net_device structure
4705
4706 \return - void
4707
4708 --------------------------------------------------------------------------*/
4709static void hdd_uninit (struct net_device *dev)
4710{
4711 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4712
4713 ENTER();
4714
4715 do
4716 {
4717 if (NULL == pAdapter)
4718 {
4719 hddLog(VOS_TRACE_LEVEL_FATAL,
4720 "%s: NULL pAdapter", __func__);
4721 break;
4722 }
4723
4724 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4725 {
4726 hddLog(VOS_TRACE_LEVEL_FATAL,
4727 "%s: Invalid magic", __func__);
4728 break;
4729 }
4730
4731 if (NULL == pAdapter->pHddCtx)
4732 {
4733 hddLog(VOS_TRACE_LEVEL_FATAL,
4734 "%s: NULL pHddCtx", __func__);
4735 break;
4736 }
4737
4738 if (dev != pAdapter->dev)
4739 {
4740 hddLog(VOS_TRACE_LEVEL_FATAL,
4741 "%s: Invalid device reference", __func__);
4742 /* we haven't validated all cases so let this go for now */
4743 }
4744
4745 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4746
4747 /* after uninit our adapter structure will no longer be valid */
4748 pAdapter->dev = NULL;
4749 pAdapter->magic = 0;
4750 } while (0);
4751
4752 EXIT();
4753}
4754
4755/**---------------------------------------------------------------------------
4756
4757 \brief hdd_release_firmware() -
4758
4759 This function calls the release firmware API to free the firmware buffer.
4760
4761 \param - pFileName Pointer to the File Name.
4762 pCtx - Pointer to the adapter .
4763
4764
4765 \return - 0 for success, non zero for failure
4766
4767 --------------------------------------------------------------------------*/
4768
4769VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4770{
4771 VOS_STATUS status = VOS_STATUS_SUCCESS;
4772 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4773 ENTER();
4774
4775
4776 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4777
4778 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4779
4780 if(pHddCtx->fw) {
4781 release_firmware(pHddCtx->fw);
4782 pHddCtx->fw = NULL;
4783 }
4784 else
4785 status = VOS_STATUS_E_FAILURE;
4786 }
4787 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4788 if(pHddCtx->nv) {
4789 release_firmware(pHddCtx->nv);
4790 pHddCtx->nv = NULL;
4791 }
4792 else
4793 status = VOS_STATUS_E_FAILURE;
4794
4795 }
4796
4797 EXIT();
4798 return status;
4799}
4800
4801/**---------------------------------------------------------------------------
4802
4803 \brief hdd_request_firmware() -
4804
4805 This function reads the firmware file using the request firmware
4806 API and returns the the firmware data and the firmware file size.
4807
4808 \param - pfileName - Pointer to the file name.
4809 - pCtx - Pointer to the adapter .
4810 - ppfw_data - Pointer to the pointer of the firmware data.
4811 - pSize - Pointer to the file size.
4812
4813 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4814
4815 --------------------------------------------------------------------------*/
4816
4817
4818VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4819{
4820 int status;
4821 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4822 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4823 ENTER();
4824
4825 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4826
4827 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4828
4829 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4830 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4831 __func__, pfileName);
4832 retval = VOS_STATUS_E_FAILURE;
4833 }
4834
4835 else {
4836 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4837 *pSize = pHddCtx->fw->size;
4838 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4839 __func__, *pSize);
4840 }
4841 }
4842 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4843
4844 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4845
4846 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4847 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4848 __func__, pfileName);
4849 retval = VOS_STATUS_E_FAILURE;
4850 }
4851
4852 else {
4853 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4854 *pSize = pHddCtx->nv->size;
4855 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4856 __func__, *pSize);
4857 }
4858 }
4859
4860 EXIT();
4861 return retval;
4862}
4863/**---------------------------------------------------------------------------
4864 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4865
4866 This is the function invoked by SME to inform the result of a full power
4867 request issued by HDD
4868
4869 \param - callbackcontext - Pointer to cookie
4870 status - result of request
4871
4872 \return - None
4873
4874--------------------------------------------------------------------------*/
4875void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4876{
4877 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4878
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004879 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 if(&pHddCtx->full_pwr_comp_var)
4881 {
4882 complete(&pHddCtx->full_pwr_comp_var);
4883 }
4884}
4885
4886/**---------------------------------------------------------------------------
4887
4888 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4889
4890 This is the function invoked by SME to inform the result of BMPS
4891 request issued by HDD
4892
4893 \param - callbackcontext - Pointer to cookie
4894 status - result of request
4895
4896 \return - None
4897
4898--------------------------------------------------------------------------*/
4899void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4900{
4901
4902 struct completion *completion_var = (struct completion*) callbackContext;
4903
Arif Hussain6d2a3322013-11-17 19:50:10 -08004904 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 if(completion_var != NULL)
4906 {
4907 complete(completion_var);
4908 }
4909}
4910
4911/**---------------------------------------------------------------------------
4912
4913 \brief hdd_get_cfg_file_size() -
4914
4915 This function reads the configuration file using the request firmware
4916 API and returns the configuration file size.
4917
4918 \param - pCtx - Pointer to the adapter .
4919 - pFileName - Pointer to the file name.
4920 - pBufSize - Pointer to the buffer size.
4921
4922 \return - 0 for success, non zero for failure
4923
4924 --------------------------------------------------------------------------*/
4925
4926VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4927{
4928 int status;
4929 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4930
4931 ENTER();
4932
4933 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4934
4935 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4937 status = VOS_STATUS_E_FAILURE;
4938 }
4939 else {
4940 *pBufSize = pHddCtx->fw->size;
4941 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4942 release_firmware(pHddCtx->fw);
4943 pHddCtx->fw = NULL;
4944 }
4945
4946 EXIT();
4947 return VOS_STATUS_SUCCESS;
4948}
4949
4950/**---------------------------------------------------------------------------
4951
4952 \brief hdd_read_cfg_file() -
4953
4954 This function reads the configuration file using the request firmware
4955 API and returns the cfg data and the buffer size of the configuration file.
4956
4957 \param - pCtx - Pointer to the adapter .
4958 - pFileName - Pointer to the file name.
4959 - pBuffer - Pointer to the data buffer.
4960 - pBufSize - Pointer to the buffer size.
4961
4962 \return - 0 for success, non zero for failure
4963
4964 --------------------------------------------------------------------------*/
4965
4966VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4967 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4968{
4969 int status;
4970 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4971
4972 ENTER();
4973
4974 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4975
4976 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4977 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4978 return VOS_STATUS_E_FAILURE;
4979 }
4980 else {
4981 if(*pBufSize != pHddCtx->fw->size) {
4982 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4983 "file size", __func__);
4984 release_firmware(pHddCtx->fw);
4985 pHddCtx->fw = NULL;
4986 return VOS_STATUS_E_FAILURE;
4987 }
4988 else {
4989 if(pBuffer) {
4990 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4991 }
4992 release_firmware(pHddCtx->fw);
4993 pHddCtx->fw = NULL;
4994 }
4995 }
4996
4997 EXIT();
4998
4999 return VOS_STATUS_SUCCESS;
5000}
5001
5002/**---------------------------------------------------------------------------
5003
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 \brief hdd_set_mac_address() -
5005
5006 This function sets the user specified mac address using
5007 the command ifconfig wlanX hw ether <mac adress>.
5008
5009 \param - dev - Pointer to the net device.
5010 - addr - Pointer to the sockaddr.
5011 \return - 0 for success, non zero for failure
5012
5013 --------------------------------------------------------------------------*/
5014
5015static int hdd_set_mac_address(struct net_device *dev, void *addr)
5016{
5017 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5018 struct sockaddr *psta_mac_addr = addr;
5019 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5020
5021 ENTER();
5022
5023 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5024
5025#ifdef HDD_SESSIONIZE
5026 // set the MAC address though the STA ID CFG.
5027 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5028 (v_U8_t *)&pAdapter->macAddressCurrent,
5029 sizeof( pAdapter->macAddressCurrent ),
5030 hdd_set_mac_addr_cb, VOS_FALSE );
5031#endif
5032
5033 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5034
5035 EXIT();
5036 return halStatus;
5037}
5038
5039tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5040{
5041 int i;
5042 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5043 {
5044 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5045 break;
5046 }
5047
5048 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5049 return NULL;
5050
5051 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5052 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5053}
5054
5055void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5056{
5057 int i;
5058 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5059 {
5060 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5061 {
5062 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5063 break;
5064 }
5065 }
5066 return;
5067}
5068
5069#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5070 static struct net_device_ops wlan_drv_ops = {
5071 .ndo_open = hdd_open,
5072 .ndo_stop = hdd_stop,
5073 .ndo_uninit = hdd_uninit,
5074 .ndo_start_xmit = hdd_hard_start_xmit,
5075 .ndo_tx_timeout = hdd_tx_timeout,
5076 .ndo_get_stats = hdd_stats,
5077 .ndo_do_ioctl = hdd_ioctl,
5078 .ndo_set_mac_address = hdd_set_mac_address,
5079 .ndo_select_queue = hdd_select_queue,
5080#ifdef WLAN_FEATURE_PACKET_FILTERING
5081#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5082 .ndo_set_rx_mode = hdd_set_multicast_list,
5083#else
5084 .ndo_set_multicast_list = hdd_set_multicast_list,
5085#endif //LINUX_VERSION_CODE
5086#endif
5087 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 static struct net_device_ops wlan_mon_drv_ops = {
5089 .ndo_open = hdd_mon_open,
5090 .ndo_stop = hdd_stop,
5091 .ndo_uninit = hdd_uninit,
5092 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5093 .ndo_tx_timeout = hdd_tx_timeout,
5094 .ndo_get_stats = hdd_stats,
5095 .ndo_do_ioctl = hdd_ioctl,
5096 .ndo_set_mac_address = hdd_set_mac_address,
5097 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005098
5099#endif
5100
5101void hdd_set_station_ops( struct net_device *pWlanDev )
5102{
5103#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 pWlanDev->netdev_ops = &wlan_drv_ops;
5105#else
5106 pWlanDev->open = hdd_open;
5107 pWlanDev->stop = hdd_stop;
5108 pWlanDev->uninit = hdd_uninit;
5109 pWlanDev->hard_start_xmit = NULL;
5110 pWlanDev->tx_timeout = hdd_tx_timeout;
5111 pWlanDev->get_stats = hdd_stats;
5112 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005113 pWlanDev->set_mac_address = hdd_set_mac_address;
5114#endif
5115}
5116
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005117static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005118{
5119 struct net_device *pWlanDev = NULL;
5120 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 /*
5122 * cfg80211 initialization and registration....
5123 */
5124 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5125
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 if(pWlanDev != NULL)
5127 {
5128
5129 //Save the pointer to the net_device in the HDD adapter
5130 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5131
Jeff Johnson295189b2012-06-20 16:38:30 -07005132 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5133
5134 pAdapter->dev = pWlanDev;
5135 pAdapter->pHddCtx = pHddCtx;
5136 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5137
5138 init_completion(&pAdapter->session_open_comp_var);
5139 init_completion(&pAdapter->session_close_comp_var);
5140 init_completion(&pAdapter->disconnect_comp_var);
5141 init_completion(&pAdapter->linkup_event_var);
5142 init_completion(&pAdapter->cancel_rem_on_chan_var);
5143 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005144#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5145 init_completion(&pAdapter->offchannel_tx_event);
5146#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005148#ifdef FEATURE_WLAN_TDLS
5149 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005150 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005151 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305152 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 init_completion(&pHddCtx->mc_sus_event_var);
5155 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305156 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005157 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005158 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005159
Rajeev79dbe4c2013-10-05 11:03:42 +05305160#ifdef FEATURE_WLAN_BATCH_SCAN
5161 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5162 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5163 pAdapter->pBatchScanRsp = NULL;
5164 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005165 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005166 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305167 mutex_init(&pAdapter->hdd_batch_scan_lock);
5168#endif
5169
Jeff Johnson295189b2012-06-20 16:38:30 -07005170 pAdapter->isLinkUpSvcNeeded = FALSE;
5171 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5172 //Init the net_device structure
5173 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5174
5175 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5176 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5177 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5178 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5179
5180 hdd_set_station_ops( pAdapter->dev );
5181
5182 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5184 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5185 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 /* set pWlanDev's parent to underlying device */
5187 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5188 }
5189
5190 return pAdapter;
5191}
5192
5193VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5194{
5195 struct net_device *pWlanDev = pAdapter->dev;
5196 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5197 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5198 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5199
5200 if( rtnl_lock_held )
5201 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005202 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005203 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5204 {
5205 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5206 return VOS_STATUS_E_FAILURE;
5207 }
5208 }
5209 if (register_netdevice(pWlanDev))
5210 {
5211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5212 return VOS_STATUS_E_FAILURE;
5213 }
5214 }
5215 else
5216 {
5217 if(register_netdev(pWlanDev))
5218 {
5219 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5220 return VOS_STATUS_E_FAILURE;
5221 }
5222 }
5223 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5224
5225 return VOS_STATUS_SUCCESS;
5226}
5227
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005228static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005229{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005230 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005231
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005232 if (NULL == pAdapter)
5233 {
5234 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5235 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005236 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005237
5238 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5239 {
5240 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5241 return eHAL_STATUS_NOT_INITIALIZED;
5242 }
5243
5244 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5245
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005246#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005247 /* need to make sure all of our scheduled work has completed.
5248 * This callback is called from MC thread context, so it is safe to
5249 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005250 *
5251 * Even though this is called from MC thread context, if there is a faulty
5252 * work item in the system, that can hang this call forever. So flushing
5253 * this global work queue is not safe; and now we make sure that
5254 * individual work queues are stopped correctly. But the cancel work queue
5255 * is a GPL only API, so the proprietary version of the driver would still
5256 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005257 */
5258 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005259#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005260
5261 /* We can be blocked while waiting for scheduled work to be
5262 * flushed, and the adapter structure can potentially be freed, in
5263 * which case the magic will have been reset. So make sure the
5264 * magic is still good, and hence the adapter structure is still
5265 * valid, before signaling completion */
5266 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5267 {
5268 complete(&pAdapter->session_close_comp_var);
5269 }
5270
Jeff Johnson295189b2012-06-20 16:38:30 -07005271 return eHAL_STATUS_SUCCESS;
5272}
5273
5274VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5275{
5276 struct net_device *pWlanDev = pAdapter->dev;
5277 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5278 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5279 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5280 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5281 int rc = 0;
5282
5283 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005284 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005285 //Open a SME session for future operation
5286 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005287 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5289 {
5290 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005291 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005292 halStatus, halStatus );
5293 status = VOS_STATUS_E_FAILURE;
5294 goto error_sme_open;
5295 }
5296
5297 //Block on a completion variable. Can't wait forever though.
5298 rc = wait_for_completion_interruptible_timeout(
5299 &pAdapter->session_open_comp_var,
5300 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5301 if (!rc)
5302 {
5303 hddLog(VOS_TRACE_LEVEL_FATAL,
5304 "Session is not opened within timeout period code %08d", rc );
5305 status = VOS_STATUS_E_FAILURE;
5306 goto error_sme_open;
5307 }
5308
5309 // Register wireless extensions
5310 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5311 {
5312 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005313 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 halStatus, halStatus );
5315 status = VOS_STATUS_E_FAILURE;
5316 goto error_register_wext;
5317 }
5318 //Safe to register the hard_start_xmit function again
5319#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5320 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5321#else
5322 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5323#endif
5324
5325 //Set the Connection State to Not Connected
5326 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5327
5328 //Set the default operation channel
5329 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5330
5331 /* Make the default Auth Type as OPEN*/
5332 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5333
5334 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5335 {
5336 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005337 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 status, status );
5339 goto error_init_txrx;
5340 }
5341
5342 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5343
5344 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5345 {
5346 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005347 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 status, status );
5349 goto error_wmm_init;
5350 }
5351
5352 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5353
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005354#ifdef FEATURE_WLAN_TDLS
5355 if(0 != wlan_hdd_tdls_init(pAdapter))
5356 {
5357 status = VOS_STATUS_E_FAILURE;
5358 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5359 goto error_tdls_init;
5360 }
5361 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5362#endif
5363
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 return VOS_STATUS_SUCCESS;
5365
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005366#ifdef FEATURE_WLAN_TDLS
5367error_tdls_init:
5368 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5369 hdd_wmm_adapter_close(pAdapter);
5370#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005371error_wmm_init:
5372 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5373 hdd_deinit_tx_rx(pAdapter);
5374error_init_txrx:
5375 hdd_UnregisterWext(pWlanDev);
5376error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005377 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 {
5379 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005380 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005382 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 {
5384 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005385 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005387 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 }
5389}
5390error_sme_open:
5391 return status;
5392}
5393
Jeff Johnson295189b2012-06-20 16:38:30 -07005394void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5395{
5396 hdd_cfg80211_state_t *cfgState;
5397
5398 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5399
5400 if( NULL != cfgState->buf )
5401 {
5402 int rc;
5403 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5404 rc = wait_for_completion_interruptible_timeout(
5405 &pAdapter->tx_action_cnf_event,
5406 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5407 if(!rc)
5408 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005410 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 }
5412 }
5413 return;
5414}
Jeff Johnson295189b2012-06-20 16:38:30 -07005415
5416void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5417{
5418 ENTER();
5419 switch ( pAdapter->device_mode )
5420 {
5421 case WLAN_HDD_INFRA_STATION:
5422 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005423 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005424 {
5425 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5426 {
5427 hdd_deinit_tx_rx( pAdapter );
5428 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5429 }
5430
5431 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5432 {
5433 hdd_wmm_adapter_close( pAdapter );
5434 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5435 }
5436
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005438#ifdef FEATURE_WLAN_TDLS
5439 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5440 {
5441 wlan_hdd_tdls_exit(pAdapter);
5442 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5443 }
5444#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005445
5446 break;
5447 }
5448
5449 case WLAN_HDD_SOFTAP:
5450 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305452
5453 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5454 {
5455 hdd_wmm_adapter_close( pAdapter );
5456 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5457 }
5458
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005460
5461 hdd_unregister_hostapd(pAdapter);
5462 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 break;
5465 }
5466
5467 case WLAN_HDD_MONITOR:
5468 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5471 {
5472 hdd_deinit_tx_rx( pAdapter );
5473 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 if(NULL != pAdapterforTx)
5476 {
5477 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005479 break;
5480 }
5481
5482
5483 default:
5484 break;
5485 }
5486
5487 EXIT();
5488}
5489
5490void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5491{
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305492 struct net_device *pWlanDev;
5493
5494 ENTER();
5495 if (NULL == pAdapter)
5496 {
5497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5498 "%s: HDD adapter is Null", __func__);
5499 return;
5500 }
5501
5502 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005503
Rajeev79dbe4c2013-10-05 11:03:42 +05305504#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305505 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5506 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
5507 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5508 )
5509 {
Rajeev79dbe4c2013-10-05 11:03:42 +05305510 tHddBatchScanRsp *pNode;
5511 tHddBatchScanRsp *pPrev;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305512 pNode = pAdapter->pBatchScanRsp;
5513 while (pNode)
Rajeev79dbe4c2013-10-05 11:03:42 +05305514 {
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305515 pPrev = pNode;
5516 pNode = pNode->pNext;
5517 vos_mem_free((v_VOID_t * )pPrev);
5518 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305519 }
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305520 pAdapter->pBatchScanRsp = NULL;
5521 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305522#endif
5523
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5525 if( rtnl_held )
5526 {
5527 unregister_netdevice(pWlanDev);
5528 }
5529 else
5530 {
5531 unregister_netdev(pWlanDev);
5532 }
5533 // note that the pAdapter is no longer valid at this point
5534 // since the memory has been reclaimed
5535 }
5536
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305537 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005538}
5539
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005540void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5541{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305542 VOS_STATUS status;
5543 hdd_adapter_t *pAdapter = NULL;
5544 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005545
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305546 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005547
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305548 /*loop through all adapters.*/
5549 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005550 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305551 pAdapter = pAdapterNode->pAdapter;
5552 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5553 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005554
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305555 { // we skip this registration for modes other than STA and P2P client modes.
5556 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5557 pAdapterNode = pNext;
5558 continue;
5559 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005560
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305561 //Apply Dynamic DTIM For P2P
5562 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5563 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5564 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5565 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5566 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5567 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5568 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5569 (eConnectionState_Associated ==
5570 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5571 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5572 {
5573 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005574
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305575 powerRequest.uIgnoreDTIM = 1;
5576 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5577
5578 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5579 {
5580 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5581 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5582 }
5583 else
5584 {
5585 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5586 }
5587
5588 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5589 * specified during Enter/Exit BMPS when LCD off*/
5590 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5591 NULL, eANI_BOOLEAN_FALSE);
5592 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5593 NULL, eANI_BOOLEAN_FALSE);
5594
5595 /* switch to the DTIM specified in cfg.ini */
5596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5597 "Switch to DTIM %d", powerRequest.uListenInterval);
5598 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5599 break;
5600
5601 }
5602
5603 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5604 pAdapterNode = pNext;
5605 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005606}
5607
5608void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5609{
5610 /*Switch back to DTIM 1*/
5611 tSirSetPowerParamsReq powerRequest = { 0 };
5612
5613 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5614 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005615 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005616
5617 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5618 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5619 NULL, eANI_BOOLEAN_FALSE);
5620 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5621 NULL, eANI_BOOLEAN_FALSE);
5622
5623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5624 "Switch to DTIM%d",powerRequest.uListenInterval);
5625 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5626
5627}
5628
Jeff Johnson295189b2012-06-20 16:38:30 -07005629VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5630{
5631 VOS_STATUS status = VOS_STATUS_SUCCESS;
5632
5633 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5634 {
5635 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5636 }
5637
5638 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5639 {
5640 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5641 }
5642
5643 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5644 {
5645 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5646 }
5647
5648 return status;
5649}
5650
5651VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5652{
5653 hdd_adapter_t *pAdapter = NULL;
5654 eHalStatus halStatus;
5655 VOS_STATUS status = VOS_STATUS_E_INVAL;
5656 v_BOOL_t disableBmps = FALSE;
5657 v_BOOL_t disableImps = FALSE;
5658
5659 switch(session_type)
5660 {
5661 case WLAN_HDD_INFRA_STATION:
5662 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 case WLAN_HDD_P2P_CLIENT:
5664 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005665 //Exit BMPS -> Is Sta/P2P Client is already connected
5666 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5667 if((NULL != pAdapter)&&
5668 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5669 {
5670 disableBmps = TRUE;
5671 }
5672
5673 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5674 if((NULL != pAdapter)&&
5675 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5676 {
5677 disableBmps = TRUE;
5678 }
5679
5680 //Exit both Bmps and Imps incase of Go/SAP Mode
5681 if((WLAN_HDD_SOFTAP == session_type) ||
5682 (WLAN_HDD_P2P_GO == session_type))
5683 {
5684 disableBmps = TRUE;
5685 disableImps = TRUE;
5686 }
5687
5688 if(TRUE == disableImps)
5689 {
5690 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5691 {
5692 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5693 }
5694 }
5695
5696 if(TRUE == disableBmps)
5697 {
5698 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5699 {
5700 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5701
5702 if(eHAL_STATUS_SUCCESS != halStatus)
5703 {
5704 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005705 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 VOS_ASSERT(0);
5707 return status;
5708 }
5709 }
5710
5711 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5712 {
5713 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5714
5715 if(eHAL_STATUS_SUCCESS != halStatus)
5716 {
5717 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005718 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005719 VOS_ASSERT(0);
5720 return status;
5721 }
5722 }
5723 }
5724
5725 if((TRUE == disableBmps) ||
5726 (TRUE == disableImps))
5727 {
5728 /* Now, get the chip into Full Power now */
5729 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5730 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5731 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5732
5733 if(halStatus != eHAL_STATUS_SUCCESS)
5734 {
5735 if(halStatus == eHAL_STATUS_PMC_PENDING)
5736 {
5737 //Block on a completion variable. Can't wait forever though
5738 wait_for_completion_interruptible_timeout(
5739 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5740 }
5741 else
5742 {
5743 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005744 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005745 VOS_ASSERT(0);
5746 return status;
5747 }
5748 }
5749
5750 status = VOS_STATUS_SUCCESS;
5751 }
5752
5753 break;
5754 }
5755 return status;
5756}
5757
5758hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005759 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005760 tANI_U8 rtnl_held )
5761{
5762 hdd_adapter_t *pAdapter = NULL;
5763 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5764 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5765 VOS_STATUS exitbmpsStatus;
5766
Arif Hussain6d2a3322013-11-17 19:50:10 -08005767 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005768
5769 //Disable BMPS incase of Concurrency
5770 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5771
5772 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5773 {
5774 //Fail to Exit BMPS
5775 VOS_ASSERT(0);
5776 return NULL;
5777 }
5778
5779 switch(session_type)
5780 {
5781 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005782 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005783 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 {
5785 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5786
5787 if( NULL == pAdapter )
5788 return NULL;
5789
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305790#ifdef FEATURE_WLAN_TDLS
5791 /* A Mutex Lock is introduced while changing/initializing the mode to
5792 * protect the concurrent access for the Adapters by TDLS module.
5793 */
5794 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5795 {
5796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5797 "%s: unable to lock list", __func__);
5798 return NULL;
5799 }
5800#endif
5801
Jeff Johnsone7245742012-09-05 17:12:55 -07005802 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5803 NL80211_IFTYPE_P2P_CLIENT:
5804 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005805
Jeff Johnson295189b2012-06-20 16:38:30 -07005806 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305807#ifdef FEATURE_WLAN_TDLS
5808 mutex_unlock(&pHddCtx->tdls_lock);
5809#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305810
5811 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 if( VOS_STATUS_SUCCESS != status )
5813 goto err_free_netdev;
5814
5815 status = hdd_register_interface( pAdapter, rtnl_held );
5816 if( VOS_STATUS_SUCCESS != status )
5817 {
5818 hdd_deinit_adapter(pHddCtx, pAdapter);
5819 goto err_free_netdev;
5820 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305821
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305822 // Workqueue which gets scheduled in IPv4 notification callback.
5823 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5824
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305825#ifdef WLAN_NS_OFFLOAD
5826 // Workqueue which gets scheduled in IPv6 notification callback.
5827 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5828#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 //Stop the Interface TX queue.
5830 netif_tx_disable(pAdapter->dev);
5831 //netif_tx_disable(pWlanDev);
5832 netif_carrier_off(pAdapter->dev);
5833
5834 break;
5835 }
5836
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 case WLAN_HDD_SOFTAP:
5839 {
5840 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5841 if( NULL == pAdapter )
5842 return NULL;
5843
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5845 NL80211_IFTYPE_AP:
5846 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 pAdapter->device_mode = session_type;
5848
5849 status = hdd_init_ap_mode(pAdapter);
5850 if( VOS_STATUS_SUCCESS != status )
5851 goto err_free_netdev;
5852
5853 status = hdd_register_hostapd( pAdapter, rtnl_held );
5854 if( VOS_STATUS_SUCCESS != status )
5855 {
5856 hdd_deinit_adapter(pHddCtx, pAdapter);
5857 goto err_free_netdev;
5858 }
5859
5860 netif_tx_disable(pAdapter->dev);
5861 netif_carrier_off(pAdapter->dev);
5862
5863 hdd_set_conparam( 1 );
5864 break;
5865 }
5866 case WLAN_HDD_MONITOR:
5867 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5869 if( NULL == pAdapter )
5870 return NULL;
5871
5872 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5873 pAdapter->device_mode = session_type;
5874 status = hdd_register_interface( pAdapter, rtnl_held );
5875#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5876 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5877#else
5878 pAdapter->dev->open = hdd_mon_open;
5879 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5880#endif
5881 hdd_init_tx_rx( pAdapter );
5882 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5883 //Set adapter to be used for data tx. It will use either GO or softap.
5884 pAdapter->sessionCtx.monitor.pAdapterForTx =
5885 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5887 {
5888 pAdapter->sessionCtx.monitor.pAdapterForTx =
5889 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 /* This workqueue will be used to transmit management packet over
5892 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005893 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5894 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5895 return NULL;
5896 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005897
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5899 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005900 }
5901 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 case WLAN_HDD_FTM:
5903 {
5904 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5905
5906 if( NULL == pAdapter )
5907 return NULL;
5908 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5909 * message while loading driver in FTM mode. */
5910 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5911 pAdapter->device_mode = session_type;
5912 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305913
5914 hdd_init_tx_rx( pAdapter );
5915
5916 //Stop the Interface TX queue.
5917 netif_tx_disable(pAdapter->dev);
5918 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005919 }
5920 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 default:
5922 {
5923 VOS_ASSERT(0);
5924 return NULL;
5925 }
5926 }
5927
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 if( VOS_STATUS_SUCCESS == status )
5929 {
5930 //Add it to the hdd's session list.
5931 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5932 if( NULL == pHddAdapterNode )
5933 {
5934 status = VOS_STATUS_E_NOMEM;
5935 }
5936 else
5937 {
5938 pHddAdapterNode->pAdapter = pAdapter;
5939 status = hdd_add_adapter_back ( pHddCtx,
5940 pHddAdapterNode );
5941 }
5942 }
5943
5944 if( VOS_STATUS_SUCCESS != status )
5945 {
5946 if( NULL != pAdapter )
5947 {
5948 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5949 pAdapter = NULL;
5950 }
5951 if( NULL != pHddAdapterNode )
5952 {
5953 vos_mem_free( pHddAdapterNode );
5954 }
5955
5956 goto resume_bmps;
5957 }
5958
5959 if(VOS_STATUS_SUCCESS == status)
5960 {
5961 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5962
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005963 //Initialize the WoWL service
5964 if(!hdd_init_wowl(pAdapter))
5965 {
5966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5967 goto err_free_netdev;
5968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 return pAdapter;
5971
5972err_free_netdev:
5973 free_netdev(pAdapter->dev);
5974 wlan_hdd_release_intf_addr( pHddCtx,
5975 pAdapter->macAddressCurrent.bytes );
5976
5977resume_bmps:
5978 //If bmps disabled enable it
5979 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5980 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305981 if (pHddCtx->hdd_wlan_suspended)
5982 {
5983 hdd_set_pwrparams(pHddCtx);
5984 }
5985 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005986 }
5987 return NULL;
5988}
5989
5990VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5991 tANI_U8 rtnl_held )
5992{
5993 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5994 VOS_STATUS status;
5995
5996 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5997 if( VOS_STATUS_SUCCESS != status )
5998 return status;
5999
6000 while ( pCurrent->pAdapter != pAdapter )
6001 {
6002 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6003 if( VOS_STATUS_SUCCESS != status )
6004 break;
6005
6006 pCurrent = pNext;
6007 }
6008 pAdapterNode = pCurrent;
6009 if( VOS_STATUS_SUCCESS == status )
6010 {
6011 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6012 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306013
6014#ifdef FEATURE_WLAN_TDLS
6015
6016 /* A Mutex Lock is introduced while changing/initializing the mode to
6017 * protect the concurrent access for the Adapters by TDLS module.
6018 */
6019 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6020 {
6021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6022 "%s: unable to lock list", __func__);
6023 return VOS_STATUS_E_FAILURE;
6024 }
6025#endif
6026
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 hdd_remove_adapter( pHddCtx, pAdapterNode );
6028 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006029 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006030
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306031#ifdef FEATURE_WLAN_TDLS
6032 mutex_unlock(&pHddCtx->tdls_lock);
6033#endif
6034
Jeff Johnson295189b2012-06-20 16:38:30 -07006035
6036 /* If there is a single session of STA/P2P client, re-enable BMPS */
6037 if ((!vos_concurrent_sessions_running()) &&
6038 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6039 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6040 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306041 if (pHddCtx->hdd_wlan_suspended)
6042 {
6043 hdd_set_pwrparams(pHddCtx);
6044 }
6045 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 }
6047
6048 return VOS_STATUS_SUCCESS;
6049 }
6050
6051 return VOS_STATUS_E_FAILURE;
6052}
6053
6054VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6055{
6056 hdd_adapter_list_node_t *pHddAdapterNode;
6057 VOS_STATUS status;
6058
6059 ENTER();
6060
6061 do
6062 {
6063 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6064 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6065 {
6066 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6067 vos_mem_free( pHddAdapterNode );
6068 }
6069 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6070
6071 EXIT();
6072
6073 return VOS_STATUS_SUCCESS;
6074}
6075
6076void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6077{
6078 v_U8_t addIE[1] = {0};
6079
6080 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6081 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6082 eANI_BOOLEAN_FALSE) )
6083 {
6084 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006085 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 }
6087
6088 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6089 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6090 eANI_BOOLEAN_FALSE) )
6091 {
6092 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006093 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006094 }
6095
6096 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6097 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6098 eANI_BOOLEAN_FALSE) )
6099 {
6100 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006101 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006102 }
6103}
6104
6105VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6106{
6107 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6108 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6109 union iwreq_data wrqu;
6110
6111 ENTER();
6112
6113 switch(pAdapter->device_mode)
6114 {
6115 case WLAN_HDD_INFRA_STATION:
6116 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006117 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6119 {
6120 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6121 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6122 pAdapter->sessionId,
6123 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6124 else
6125 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6126 pAdapter->sessionId,
6127 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6128 //success implies disconnect command got queued up successfully
6129 if(halStatus == eHAL_STATUS_SUCCESS)
6130 {
6131 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6132 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6133 }
6134 memset(&wrqu, '\0', sizeof(wrqu));
6135 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6136 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6137 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6138 }
6139 else
6140 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306141 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306143#ifdef WLAN_OPEN_SOURCE
6144#ifdef WLAN_NS_OFFLOAD
6145 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6146#endif
6147#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006148
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306149#ifdef WLAN_OPEN_SOURCE
6150 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6153 {
6154 INIT_COMPLETION(pAdapter->session_close_comp_var);
6155 if (eHAL_STATUS_SUCCESS ==
6156 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6157 hdd_smeCloseSessionCallback, pAdapter))
6158 {
6159 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006160 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006161 &pAdapter->session_close_comp_var,
6162 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6163 }
6164 }
6165
6166 break;
6167
6168 case WLAN_HDD_SOFTAP:
6169 case WLAN_HDD_P2P_GO:
6170 //Any softap specific cleanup here...
6171 mutex_lock(&pHddCtx->sap_lock);
6172 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6173 {
6174 VOS_STATUS status;
6175 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6176
6177 //Stop Bss.
6178 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6179 if (VOS_IS_STATUS_SUCCESS(status))
6180 {
6181 hdd_hostapd_state_t *pHostapdState =
6182 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6183
6184 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6185
6186 if (!VOS_IS_STATUS_SUCCESS(status))
6187 {
6188 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006189 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 }
6191 }
6192 else
6193 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006194 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 }
6196 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6197
6198 if (eHAL_STATUS_FAILURE ==
6199 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6200 0, NULL, eANI_BOOLEAN_FALSE))
6201 {
6202 hddLog(LOGE,
6203 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006204 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006205 }
6206
6207 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6208 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6209 eANI_BOOLEAN_FALSE) )
6210 {
6211 hddLog(LOGE,
6212 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6213 }
6214
6215 // Reset WNI_CFG_PROBE_RSP Flags
6216 wlan_hdd_reset_prob_rspies(pAdapter);
6217 kfree(pAdapter->sessionCtx.ap.beacon);
6218 pAdapter->sessionCtx.ap.beacon = NULL;
6219 }
6220 mutex_unlock(&pHddCtx->sap_lock);
6221 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006222
Jeff Johnson295189b2012-06-20 16:38:30 -07006223 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006224#ifdef WLAN_OPEN_SOURCE
6225 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6226#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006228
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 default:
6230 break;
6231 }
6232
6233 EXIT();
6234 return VOS_STATUS_SUCCESS;
6235}
6236
6237VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6238{
6239 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6240 VOS_STATUS status;
6241 hdd_adapter_t *pAdapter;
6242
6243 ENTER();
6244
6245 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6246
6247 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6248 {
6249 pAdapter = pAdapterNode->pAdapter;
6250 netif_tx_disable(pAdapter->dev);
6251 netif_carrier_off(pAdapter->dev);
6252
6253 hdd_stop_adapter( pHddCtx, pAdapter );
6254
6255 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6256 pAdapterNode = pNext;
6257 }
6258
6259 EXIT();
6260
6261 return VOS_STATUS_SUCCESS;
6262}
6263
6264VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6265{
6266 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6267 VOS_STATUS status;
6268 hdd_adapter_t *pAdapter;
6269
6270 ENTER();
6271
6272 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6273
6274 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6275 {
6276 pAdapter = pAdapterNode->pAdapter;
6277 netif_tx_disable(pAdapter->dev);
6278 netif_carrier_off(pAdapter->dev);
6279
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006280 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6281
Jeff Johnson295189b2012-06-20 16:38:30 -07006282 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306283 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6284 {
6285 hdd_wmm_adapter_close( pAdapter );
6286 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6287 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006288
6289 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6290 pAdapterNode = pNext;
6291 }
6292
6293 EXIT();
6294
6295 return VOS_STATUS_SUCCESS;
6296}
6297
6298VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6299{
6300 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6301 VOS_STATUS status;
6302 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306303 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006304
6305 ENTER();
6306
6307 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6308
6309 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6310 {
6311 pAdapter = pAdapterNode->pAdapter;
6312
6313 switch(pAdapter->device_mode)
6314 {
6315 case WLAN_HDD_INFRA_STATION:
6316 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006317 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306318
6319 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6320
Jeff Johnson295189b2012-06-20 16:38:30 -07006321 hdd_init_station_mode(pAdapter);
6322 /* Open the gates for HDD to receive Wext commands */
6323 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006324 pHddCtx->scan_info.mScanPending = FALSE;
6325 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006326
6327 //Trigger the initial scan
6328 hdd_wlan_initial_scan(pAdapter);
6329
6330 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306331 if (eConnectionState_Associated == connState ||
6332 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 {
6334 union iwreq_data wrqu;
6335 memset(&wrqu, '\0', sizeof(wrqu));
6336 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6337 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6338 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006339 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006340
Jeff Johnson295189b2012-06-20 16:38:30 -07006341 /* indicate disconnected event to nl80211 */
6342 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6343 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006344 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306345 else if (eConnectionState_Connecting == connState)
6346 {
6347 /*
6348 * Indicate connect failure to supplicant if we were in the
6349 * process of connecting
6350 */
6351 cfg80211_connect_result(pAdapter->dev, NULL,
6352 NULL, 0, NULL, 0,
6353 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6354 GFP_KERNEL);
6355 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 break;
6357
6358 case WLAN_HDD_SOFTAP:
6359 /* softAP can handle SSR */
6360 break;
6361
6362 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006363 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006364 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006365 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 break;
6367
6368 case WLAN_HDD_MONITOR:
6369 /* monitor interface start */
6370 break;
6371 default:
6372 break;
6373 }
6374
6375 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6376 pAdapterNode = pNext;
6377 }
6378
6379 EXIT();
6380
6381 return VOS_STATUS_SUCCESS;
6382}
6383
6384VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6385{
6386 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6387 hdd_adapter_t *pAdapter;
6388 VOS_STATUS status;
6389 v_U32_t roamId;
6390
6391 ENTER();
6392
6393 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6394
6395 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6396 {
6397 pAdapter = pAdapterNode->pAdapter;
6398
6399 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6400 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6401 {
6402 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6403 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6404
6405 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6406 init_completion(&pAdapter->disconnect_comp_var);
6407 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6408 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6409
6410 wait_for_completion_interruptible_timeout(
6411 &pAdapter->disconnect_comp_var,
6412 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6413
6414 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6415 pHddCtx->isAmpAllowed = VOS_FALSE;
6416 sme_RoamConnect(pHddCtx->hHal,
6417 pAdapter->sessionId, &(pWextState->roamProfile),
6418 &roamId);
6419 }
6420
6421 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6422 pAdapterNode = pNext;
6423 }
6424
6425 EXIT();
6426
6427 return VOS_STATUS_SUCCESS;
6428}
6429
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006430void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6431{
6432 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6433 VOS_STATUS status;
6434 hdd_adapter_t *pAdapter;
6435 hdd_station_ctx_t *pHddStaCtx;
6436 hdd_ap_ctx_t *pHddApCtx;
6437 hdd_hostapd_state_t * pHostapdState;
6438 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6439 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6440 const char *p2pMode = "DEV";
6441 const char *ccMode = "Standalone";
6442 int n;
6443
6444 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6445 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6446 {
6447 pAdapter = pAdapterNode->pAdapter;
6448 switch (pAdapter->device_mode) {
6449 case WLAN_HDD_INFRA_STATION:
6450 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6451 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6452 staChannel = pHddStaCtx->conn_info.operationChannel;
6453 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6454 }
6455 break;
6456 case WLAN_HDD_P2P_CLIENT:
6457 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6458 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6459 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6460 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6461 p2pMode = "CLI";
6462 }
6463 break;
6464 case WLAN_HDD_P2P_GO:
6465 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6466 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6467 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6468 p2pChannel = pHddApCtx->operatingChannel;
6469 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6470 }
6471 p2pMode = "GO";
6472 break;
6473 case WLAN_HDD_SOFTAP:
6474 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6475 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6476 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6477 apChannel = pHddApCtx->operatingChannel;
6478 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6479 }
6480 break;
6481 default:
6482 break;
6483 }
6484 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6485 pAdapterNode = pNext;
6486 }
6487 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6488 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6489 }
6490 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6491 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6492 if (p2pChannel > 0) {
6493 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6494 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6495 }
6496 if (apChannel > 0) {
6497 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6498 apChannel, MAC_ADDR_ARRAY(apBssid));
6499 }
6500
6501 if (p2pChannel > 0 && apChannel > 0) {
6502 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6503 }
6504}
6505
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006506bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006507{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006508 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006509}
6510
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006511/* Once SSR is disabled then it cannot be set. */
6512void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006513{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006514 if (HDD_SSR_DISABLED == isSsrRequired)
6515 return;
6516
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 isSsrRequired = value;
6518}
6519
6520VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6521 hdd_adapter_list_node_t** ppAdapterNode)
6522{
6523 VOS_STATUS status;
6524 spin_lock(&pHddCtx->hddAdapters.lock);
6525 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6526 (hdd_list_node_t**) ppAdapterNode );
6527 spin_unlock(&pHddCtx->hddAdapters.lock);
6528 return status;
6529}
6530
6531VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6532 hdd_adapter_list_node_t* pAdapterNode,
6533 hdd_adapter_list_node_t** pNextAdapterNode)
6534{
6535 VOS_STATUS status;
6536 spin_lock(&pHddCtx->hddAdapters.lock);
6537 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6538 (hdd_list_node_t*) pAdapterNode,
6539 (hdd_list_node_t**)pNextAdapterNode );
6540
6541 spin_unlock(&pHddCtx->hddAdapters.lock);
6542 return status;
6543}
6544
6545VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6546 hdd_adapter_list_node_t* pAdapterNode)
6547{
6548 VOS_STATUS status;
6549 spin_lock(&pHddCtx->hddAdapters.lock);
6550 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6551 &pAdapterNode->node );
6552 spin_unlock(&pHddCtx->hddAdapters.lock);
6553 return status;
6554}
6555
6556VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6557 hdd_adapter_list_node_t** ppAdapterNode)
6558{
6559 VOS_STATUS status;
6560 spin_lock(&pHddCtx->hddAdapters.lock);
6561 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6562 (hdd_list_node_t**) ppAdapterNode );
6563 spin_unlock(&pHddCtx->hddAdapters.lock);
6564 return status;
6565}
6566
6567VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6568 hdd_adapter_list_node_t* pAdapterNode)
6569{
6570 VOS_STATUS status;
6571 spin_lock(&pHddCtx->hddAdapters.lock);
6572 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6573 (hdd_list_node_t*) pAdapterNode );
6574 spin_unlock(&pHddCtx->hddAdapters.lock);
6575 return status;
6576}
6577
6578VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6579 hdd_adapter_list_node_t* pAdapterNode)
6580{
6581 VOS_STATUS status;
6582 spin_lock(&pHddCtx->hddAdapters.lock);
6583 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6584 (hdd_list_node_t*) pAdapterNode );
6585 spin_unlock(&pHddCtx->hddAdapters.lock);
6586 return status;
6587}
6588
6589hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6590 tSirMacAddr macAddr )
6591{
6592 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6593 hdd_adapter_t *pAdapter;
6594 VOS_STATUS status;
6595
6596 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6597
6598 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6599 {
6600 pAdapter = pAdapterNode->pAdapter;
6601
6602 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6603 macAddr, sizeof(tSirMacAddr) ) )
6604 {
6605 return pAdapter;
6606 }
6607 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6608 pAdapterNode = pNext;
6609 }
6610
6611 return NULL;
6612
6613}
6614
6615hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6616{
6617 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6618 hdd_adapter_t *pAdapter;
6619 VOS_STATUS status;
6620
6621 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6622
6623 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6624 {
6625 pAdapter = pAdapterNode->pAdapter;
6626
6627 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6628 IFNAMSIZ ) )
6629 {
6630 return pAdapter;
6631 }
6632 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6633 pAdapterNode = pNext;
6634 }
6635
6636 return NULL;
6637
6638}
6639
6640hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6641{
6642 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6643 hdd_adapter_t *pAdapter;
6644 VOS_STATUS status;
6645
6646 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6647
6648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6649 {
6650 pAdapter = pAdapterNode->pAdapter;
6651
6652 if( pAdapter && (mode == pAdapter->device_mode) )
6653 {
6654 return pAdapter;
6655 }
6656 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6657 pAdapterNode = pNext;
6658 }
6659
6660 return NULL;
6661
6662}
6663
6664//Remove this function later
6665hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6666{
6667 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6668 hdd_adapter_t *pAdapter;
6669 VOS_STATUS status;
6670
6671 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6672
6673 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6674 {
6675 pAdapter = pAdapterNode->pAdapter;
6676
6677 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6678 {
6679 return pAdapter;
6680 }
6681
6682 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6683 pAdapterNode = pNext;
6684 }
6685
6686 return NULL;
6687
6688}
6689
Jeff Johnson295189b2012-06-20 16:38:30 -07006690/**---------------------------------------------------------------------------
6691
6692 \brief hdd_set_monitor_tx_adapter() -
6693
6694 This API initializes the adapter to be used while transmitting on monitor
6695 adapter.
6696
6697 \param - pHddCtx - Pointer to the HDD context.
6698 pAdapter - Adapter that will used for TX. This can be NULL.
6699 \return - None.
6700 --------------------------------------------------------------------------*/
6701void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6702{
6703 hdd_adapter_t *pMonAdapter;
6704
6705 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6706
6707 if( NULL != pMonAdapter )
6708 {
6709 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6710 }
6711}
Jeff Johnson295189b2012-06-20 16:38:30 -07006712/**---------------------------------------------------------------------------
6713
6714 \brief hdd_select_queue() -
6715
6716 This API returns the operating channel of the requested device mode
6717
6718 \param - pHddCtx - Pointer to the HDD context.
6719 - mode - Device mode for which operating channel is required
6720 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6721 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6722 \return - channel number. "0" id the requested device is not found OR it is not connected.
6723 --------------------------------------------------------------------------*/
6724v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6725{
6726 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6727 VOS_STATUS status;
6728 hdd_adapter_t *pAdapter;
6729 v_U8_t operatingChannel = 0;
6730
6731 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6732
6733 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6734 {
6735 pAdapter = pAdapterNode->pAdapter;
6736
6737 if( mode == pAdapter->device_mode )
6738 {
6739 switch(pAdapter->device_mode)
6740 {
6741 case WLAN_HDD_INFRA_STATION:
6742 case WLAN_HDD_P2P_CLIENT:
6743 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6744 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6745 break;
6746 case WLAN_HDD_SOFTAP:
6747 case WLAN_HDD_P2P_GO:
6748 /*softap connection info */
6749 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6750 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6751 break;
6752 default:
6753 break;
6754 }
6755
6756 break; //Found the device of interest. break the loop
6757 }
6758
6759 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6760 pAdapterNode = pNext;
6761 }
6762 return operatingChannel;
6763}
6764
6765#ifdef WLAN_FEATURE_PACKET_FILTERING
6766/**---------------------------------------------------------------------------
6767
6768 \brief hdd_set_multicast_list() -
6769
6770 This used to set the multicast address list.
6771
6772 \param - dev - Pointer to the WLAN device.
6773 - skb - Pointer to OS packet (sk_buff).
6774 \return - success/fail
6775
6776 --------------------------------------------------------------------------*/
6777static void hdd_set_multicast_list(struct net_device *dev)
6778{
6779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006780 int mc_count;
6781 int i = 0;
6782 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306783
6784 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 {
6786 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306787 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 return;
6789 }
6790
6791 if (dev->flags & IFF_ALLMULTI)
6792 {
6793 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006794 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306795 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006796 }
6797 else
6798 {
6799 mc_count = netdev_mc_count(dev);
6800 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006801 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6803 {
6804 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006805 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306806 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006807 return;
6808 }
6809
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306810 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006811
6812 netdev_for_each_mc_addr(ha, dev) {
6813 if (i == mc_count)
6814 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306815 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6816 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006817 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006818 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306819 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006820 i++;
6821 }
6822 }
6823 return;
6824}
6825#endif
6826
6827/**---------------------------------------------------------------------------
6828
6829 \brief hdd_select_queue() -
6830
6831 This function is registered with the Linux OS for network
6832 core to decide which queue to use first.
6833
6834 \param - dev - Pointer to the WLAN device.
6835 - skb - Pointer to OS packet (sk_buff).
6836 \return - ac, Queue Index/access category corresponding to UP in IP header
6837
6838 --------------------------------------------------------------------------*/
6839v_U16_t hdd_select_queue(struct net_device *dev,
6840 struct sk_buff *skb)
6841{
6842 return hdd_wmm_select_queue(dev, skb);
6843}
6844
6845
6846/**---------------------------------------------------------------------------
6847
6848 \brief hdd_wlan_initial_scan() -
6849
6850 This function triggers the initial scan
6851
6852 \param - pAdapter - Pointer to the HDD adapter.
6853
6854 --------------------------------------------------------------------------*/
6855void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6856{
6857 tCsrScanRequest scanReq;
6858 tCsrChannelInfo channelInfo;
6859 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006860 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006861 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6862
6863 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6864 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6865 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6866
6867 if(sme_Is11dSupported(pHddCtx->hHal))
6868 {
6869 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6870 if ( HAL_STATUS_SUCCESS( halStatus ) )
6871 {
6872 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6873 if( !scanReq.ChannelInfo.ChannelList )
6874 {
6875 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6876 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006877 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006878 return;
6879 }
6880 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6881 channelInfo.numOfChannels);
6882 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6883 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006884 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006885 }
6886
6887 scanReq.scanType = eSIR_PASSIVE_SCAN;
6888 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6889 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6890 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6891 }
6892 else
6893 {
6894 scanReq.scanType = eSIR_ACTIVE_SCAN;
6895 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6896 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6897 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6898 }
6899
6900 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6901 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6902 {
6903 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6904 __func__, halStatus );
6905 }
6906
6907 if(sme_Is11dSupported(pHddCtx->hHal))
6908 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6909}
6910
Jeff Johnson295189b2012-06-20 16:38:30 -07006911/**---------------------------------------------------------------------------
6912
6913 \brief hdd_full_power_callback() - HDD full power callback function
6914
6915 This is the function invoked by SME to inform the result of a full power
6916 request issued by HDD
6917
6918 \param - callbackcontext - Pointer to cookie
6919 \param - status - result of request
6920
6921 \return - None
6922
6923 --------------------------------------------------------------------------*/
6924static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6925{
Jeff Johnson72a40512013-12-19 10:14:15 -08006926 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07006927
6928 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306929 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006930
6931 if (NULL == callbackContext)
6932 {
6933 hddLog(VOS_TRACE_LEVEL_ERROR,
6934 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006935 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 return;
6937 }
6938
Jeff Johnson72a40512013-12-19 10:14:15 -08006939 /* there is a race condition that exists between this callback
6940 function and the caller since the caller could time out either
6941 before or while this code is executing. we use a spinlock to
6942 serialize these actions */
6943 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006944
6945 if (POWER_CONTEXT_MAGIC != pContext->magic)
6946 {
6947 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006948 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006949 hddLog(VOS_TRACE_LEVEL_WARN,
6950 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006951 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 return;
6953 }
6954
Jeff Johnson72a40512013-12-19 10:14:15 -08006955 /* context is valid so caller is still waiting */
6956
6957 /* paranoia: invalidate the magic */
6958 pContext->magic = 0;
6959
6960 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07006961 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006962
6963 /* serialization is complete */
6964 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006965}
6966
6967/**---------------------------------------------------------------------------
6968
6969 \brief hdd_wlan_exit() - HDD WLAN exit function
6970
6971 This is the driver exit point (invoked during rmmod)
6972
6973 \param - pHddCtx - Pointer to the HDD Context
6974
6975 \return - None
6976
6977 --------------------------------------------------------------------------*/
6978void hdd_wlan_exit(hdd_context_t *pHddCtx)
6979{
6980 eHalStatus halStatus;
6981 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6982 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306983 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 hdd_adapter_t* pAdapter;
Jeff Johnson72a40512013-12-19 10:14:15 -08006985 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 long lrc;
6987
6988 ENTER();
6989
Jeff Johnson88ba7742013-02-27 14:36:02 -08006990 if (VOS_FTM_MODE != hdd_get_conparam())
6991 {
6992 // Unloading, restart logic is no more required.
6993 wlan_hdd_restart_deinit(pHddCtx);
6994 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006995
Jeff Johnson295189b2012-06-20 16:38:30 -07006996 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006997 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006999 {
7000 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7001 WLAN_HDD_INFRA_STATION);
7002 if (pAdapter == NULL)
7003 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7004
7005 if (pAdapter != NULL)
7006 {
7007 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7008 hdd_UnregisterWext(pAdapter->dev);
7009 }
7010 }
7011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007012
Jeff Johnson295189b2012-06-20 16:38:30 -07007013 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007014 {
7015 wlan_hdd_ftm_close(pHddCtx);
7016 goto free_hdd_ctx;
7017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007018 //Stop the Interface TX queue.
7019 //netif_tx_disable(pWlanDev);
7020 //netif_carrier_off(pWlanDev);
7021
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7023 {
7024 pAdapter = hdd_get_adapter(pHddCtx,
7025 WLAN_HDD_SOFTAP);
7026 }
7027 else
7028 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007029 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007030 {
7031 pAdapter = hdd_get_adapter(pHddCtx,
7032 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007033 if (pAdapter == NULL)
7034 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007035 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007036 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007037 /* DeRegister with platform driver as client for Suspend/Resume */
7038 vosStatus = hddDeregisterPmOps(pHddCtx);
7039 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7040 {
7041 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7042 VOS_ASSERT(0);
7043 }
7044
7045 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7046 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7047 {
7048 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7049 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007050
7051 // Cancel any outstanding scan requests. We are about to close all
7052 // of our adapters, but an adapter structure is what SME passes back
7053 // to our callback function. Hence if there are any outstanding scan
7054 // requests then there is a race condition between when the adapter
7055 // is closed and when the callback is invoked. We try to resolve that
7056 // race condition here by canceling any outstanding scans before we
7057 // close the adapters.
7058 // Note that the scans may be cancelled in an asynchronous manner, so
7059 // ideally there needs to be some kind of synchronization. Rather than
7060 // introduce a new synchronization here, we will utilize the fact that
7061 // we are about to Request Full Power, and since that is synchronized,
7062 // the expectation is that by the time Request Full Power has completed,
7063 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007064 if (NULL != pAdapter)
7065 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7066 else
7067 hddLog(VOS_TRACE_LEVEL_ERROR,
7068 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007069
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007070 //Stop the traffic monitor timer
7071 if ( VOS_TIMER_STATE_RUNNING ==
7072 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7073 {
7074 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7075 }
7076
7077 // Destroy the traffic monitor timer
7078 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7079 &pHddCtx->tx_rx_trafficTmr)))
7080 {
7081 hddLog(VOS_TRACE_LEVEL_ERROR,
7082 "%s: Cannot deallocate Traffic monitor timer", __func__);
7083 }
7084
Jeff Johnson295189b2012-06-20 16:38:30 -07007085 //Disable IMPS/BMPS as we do not want the device to enter any power
7086 //save mode during shutdown
7087 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7088 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7089 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7090
7091 //Ensure that device is in full power as we will touch H/W during vos_Stop
7092 init_completion(&powerContext.completion);
7093 powerContext.magic = POWER_CONTEXT_MAGIC;
7094
7095 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7096 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7097
7098 if (eHAL_STATUS_SUCCESS != halStatus)
7099 {
7100 if (eHAL_STATUS_PMC_PENDING == halStatus)
7101 {
7102 /* request was sent -- wait for the response */
7103 lrc = wait_for_completion_interruptible_timeout(
7104 &powerContext.completion,
7105 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007106 if (lrc <= 0)
7107 {
7108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007109 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007110 }
7111 }
7112 else
7113 {
7114 hddLog(VOS_TRACE_LEVEL_ERROR,
7115 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007116 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007117 /* continue -- need to clean up as much as possible */
7118 }
7119 }
7120
Jeff Johnson72a40512013-12-19 10:14:15 -08007121 /* either we never sent a request, we sent a request and received a
7122 response or we sent a request and timed out. if we never sent a
7123 request or if we sent a request and got a response, we want to
7124 clear the magic out of paranoia. if we timed out there is a
7125 race condition such that the callback function could be
7126 executing at the same time we are. of primary concern is if the
7127 callback function had already verified the "magic" but had not
7128 yet set the completion variable when a timeout occurred. we
7129 serialize these activities by invalidating the magic while
7130 holding a shared spinlock which will cause us to block if the
7131 callback is currently executing */
7132 spin_lock(&hdd_context_lock);
7133 powerContext.magic = 0;
7134 spin_unlock(&hdd_context_lock);
7135
Yue Ma0d4891e2013-08-06 17:01:45 -07007136 hdd_debugfs_exit(pHddCtx);
7137
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 // Unregister the Net Device Notifier
7139 unregister_netdevice_notifier(&hdd_netdev_notifier);
7140
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 hdd_stop_all_adapters( pHddCtx );
7142
Jeff Johnson295189b2012-06-20 16:38:30 -07007143#ifdef WLAN_BTAMP_FEATURE
7144 vosStatus = WLANBAP_Stop(pVosContext);
7145 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7146 {
7147 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7148 "%s: Failed to stop BAP",__func__);
7149 }
7150#endif //WLAN_BTAMP_FEATURE
7151
7152 //Stop all the modules
7153 vosStatus = vos_stop( pVosContext );
7154 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7155 {
7156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7157 "%s: Failed to stop VOSS",__func__);
7158 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7159 }
7160
Jeff Johnson295189b2012-06-20 16:38:30 -07007161 //Assert Deep sleep signal now to put Libra HW in lowest power state
7162 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7163 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7164
7165 //Vote off any PMIC voltage supplies
7166 vos_chipPowerDown(NULL, NULL, NULL);
7167
7168 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7169
Leo Chang59cdc7e2013-07-10 10:08:21 -07007170
Jeff Johnson295189b2012-06-20 16:38:30 -07007171 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007172 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007173
7174 //Close the scheduler before calling vos_close to make sure no thread is
7175 // scheduled after the each module close is called i.e after all the data
7176 // structures are freed.
7177 vosStatus = vos_sched_close( pVosContext );
7178 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7179 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7180 "%s: Failed to close VOSS Scheduler",__func__);
7181 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7182 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007183#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007184#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7185 /* Destroy the wake lock */
7186 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7187#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007188 /* Destroy the wake lock */
7189 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007190#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007191
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307192#ifdef CONFIG_ENABLE_LINUX_REG
7193 vosStatus = vos_nv_close();
7194 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7195 {
7196 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7197 "%s: Failed to close NV", __func__);
7198 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7199 }
7200#endif
7201
Jeff Johnson295189b2012-06-20 16:38:30 -07007202 //Close VOSS
7203 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7204 vos_close(pVosContext);
7205
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 //Close Watchdog
7207 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7208 vos_watchdog_close(pVosContext);
7209
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307210 //Clean up HDD Nlink Service
7211 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007212#ifdef WLAN_KD_READY_NOTIFIER
7213 nl_srv_exit(pHddCtx->ptt_pid);
7214#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307215 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007216#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307217
Jeff Johnson295189b2012-06-20 16:38:30 -07007218 /* Cancel the vote for XO Core ON.
7219 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7220 * exited at this point
7221 */
7222 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007223 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7225 {
7226 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7227 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007228 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007229 }
7230
7231 hdd_close_all_adapters( pHddCtx );
7232
7233
7234 //Free up dynamically allocated members inside HDD Adapter
7235 kfree(pHddCtx->cfg_ini);
7236 pHddCtx->cfg_ini= NULL;
7237
7238 /* free the power on lock from platform driver */
7239 if (free_riva_power_on_lock("wlan"))
7240 {
7241 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7242 __func__);
7243 }
7244
Jeff Johnson88ba7742013-02-27 14:36:02 -08007245free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007246 /* FTM mode, WIPHY did not registered
7247 If un-register here, system crash will happen */
7248 if (VOS_FTM_MODE != hdd_get_conparam())
7249 {
7250 wiphy_unregister(wiphy) ;
7251 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007252 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007253 if (hdd_is_ssr_required())
7254 {
7255 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007256 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007257 msleep(5000);
7258 }
7259 hdd_set_ssr_required (VOS_FALSE);
7260}
7261
7262
7263/**---------------------------------------------------------------------------
7264
7265 \brief hdd_update_config_from_nv() - Function to update the contents of
7266 the running configuration with parameters taken from NV storage
7267
7268 \param - pHddCtx - Pointer to the HDD global context
7269
7270 \return - VOS_STATUS_SUCCESS if successful
7271
7272 --------------------------------------------------------------------------*/
7273static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7274{
Jeff Johnson295189b2012-06-20 16:38:30 -07007275 v_BOOL_t itemIsValid = VOS_FALSE;
7276 VOS_STATUS status;
7277 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7278 v_U8_t macLoop;
7279
7280 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7281 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7282 if(status != VOS_STATUS_SUCCESS)
7283 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007284 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007285 return VOS_STATUS_E_FAILURE;
7286 }
7287
7288 if (itemIsValid == VOS_TRUE)
7289 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007290 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007291 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7292 VOS_MAX_CONCURRENCY_PERSONA);
7293 if(status != VOS_STATUS_SUCCESS)
7294 {
7295 /* Get MAC from NV fail, not update CFG info
7296 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007297 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007298 return VOS_STATUS_E_FAILURE;
7299 }
7300
7301 /* If first MAC is not valid, treat all others are not valid
7302 * Then all MACs will be got from ini file */
7303 if(vos_is_macaddr_zero(&macFromNV[0]))
7304 {
7305 /* MAC address in NV file is not configured yet */
7306 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7307 return VOS_STATUS_E_INVAL;
7308 }
7309
7310 /* Get MAC address from NV, update CFG info */
7311 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7312 {
7313 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7314 {
7315 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7316 /* This MAC is not valid, skip it
7317 * This MAC will be got from ini file */
7318 }
7319 else
7320 {
7321 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7322 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7323 VOS_MAC_ADDR_SIZE);
7324 }
7325 }
7326 }
7327 else
7328 {
7329 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7330 return VOS_STATUS_E_FAILURE;
7331 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007332
Jeff Johnson295189b2012-06-20 16:38:30 -07007333
7334 return VOS_STATUS_SUCCESS;
7335}
7336
7337/**---------------------------------------------------------------------------
7338
7339 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7340
7341 \param - pAdapter - Pointer to the HDD
7342
7343 \return - None
7344
7345 --------------------------------------------------------------------------*/
7346VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7347{
7348 eHalStatus halStatus;
7349 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307350 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007351
Jeff Johnson295189b2012-06-20 16:38:30 -07007352
7353 // Send ready indication to the HDD. This will kick off the MAC
7354 // into a 'running' state and should kick off an initial scan.
7355 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7356 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7357 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307358 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007359 "code %08d [x%08x]",__func__, halStatus, halStatus );
7360 return VOS_STATUS_E_FAILURE;
7361 }
7362
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307363 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007364 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7365 // And RIVA will crash
7366 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7367 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307368 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7369 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7370
7371
Jeff Johnson295189b2012-06-20 16:38:30 -07007372 return VOS_STATUS_SUCCESS;
7373}
7374
Jeff Johnson295189b2012-06-20 16:38:30 -07007375/* wake lock APIs for HDD */
7376void hdd_prevent_suspend(void)
7377{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007378#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007379 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007380#else
7381 wcnss_prevent_suspend();
7382#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007383}
7384
7385void hdd_allow_suspend(void)
7386{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007387#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007389#else
7390 wcnss_allow_suspend();
7391#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007392}
7393
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007394void hdd_allow_suspend_timeout(v_U32_t timeout)
7395{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007396#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007397 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007398#else
7399 /* Do nothing as there is no API in wcnss for timeout*/
7400#endif
7401}
7402
Jeff Johnson295189b2012-06-20 16:38:30 -07007403/**---------------------------------------------------------------------------
7404
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007405 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7406 information between Host and Riva
7407
7408 This function gets reported version of FW
7409 It also finds the version of Riva headers used to compile the host
7410 It compares the above two and prints a warning if they are different
7411 It gets the SW and HW version string
7412 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7413 indicating the features they support through a bitmap
7414
7415 \param - pHddCtx - Pointer to HDD context
7416
7417 \return - void
7418
7419 --------------------------------------------------------------------------*/
7420
7421void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7422{
7423
7424 tSirVersionType versionCompiled;
7425 tSirVersionType versionReported;
7426 tSirVersionString versionString;
7427 tANI_U8 fwFeatCapsMsgSupported = 0;
7428 VOS_STATUS vstatus;
7429
7430 /* retrieve and display WCNSS version information */
7431 do {
7432
7433 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7434 &versionCompiled);
7435 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7436 {
7437 hddLog(VOS_TRACE_LEVEL_FATAL,
7438 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007439 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007440 break;
7441 }
7442
7443 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7444 &versionReported);
7445 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7446 {
7447 hddLog(VOS_TRACE_LEVEL_FATAL,
7448 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007449 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007450 break;
7451 }
7452
7453 if ((versionCompiled.major != versionReported.major) ||
7454 (versionCompiled.minor != versionReported.minor) ||
7455 (versionCompiled.version != versionReported.version) ||
7456 (versionCompiled.revision != versionReported.revision))
7457 {
7458 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7459 "Host expected %u.%u.%u.%u\n",
7460 WLAN_MODULE_NAME,
7461 (int)versionReported.major,
7462 (int)versionReported.minor,
7463 (int)versionReported.version,
7464 (int)versionReported.revision,
7465 (int)versionCompiled.major,
7466 (int)versionCompiled.minor,
7467 (int)versionCompiled.version,
7468 (int)versionCompiled.revision);
7469 }
7470 else
7471 {
7472 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7473 WLAN_MODULE_NAME,
7474 (int)versionReported.major,
7475 (int)versionReported.minor,
7476 (int)versionReported.version,
7477 (int)versionReported.revision);
7478 }
7479
7480 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7481 versionString,
7482 sizeof(versionString));
7483 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7484 {
7485 hddLog(VOS_TRACE_LEVEL_FATAL,
7486 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007487 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007488 break;
7489 }
7490
7491 pr_info("%s: WCNSS software version %s\n",
7492 WLAN_MODULE_NAME, versionString);
7493
7494 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7495 versionString,
7496 sizeof(versionString));
7497 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7498 {
7499 hddLog(VOS_TRACE_LEVEL_FATAL,
7500 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007501 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007502 break;
7503 }
7504
7505 pr_info("%s: WCNSS hardware version %s\n",
7506 WLAN_MODULE_NAME, versionString);
7507
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007508 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7509 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007510 send the message only if it the riva is 1.1
7511 minor numbers for different riva branches:
7512 0 -> (1.0)Mainline Build
7513 1 -> (1.1)Mainline Build
7514 2->(1.04) Stability Build
7515 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007516 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007517 ((versionReported.minor>=1) && (versionReported.version>=1)))
7518 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7519 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007520
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007521 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007522 {
7523#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7524 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7525 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7526#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007527 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7528 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7529 {
7530 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7531 }
7532
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007533 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007534 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007535
7536 } while (0);
7537
7538}
7539
7540/**---------------------------------------------------------------------------
7541
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307542 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7543
7544 \param - pHddCtx - Pointer to the hdd context
7545
7546 \return - true if hardware supports 5GHz
7547
7548 --------------------------------------------------------------------------*/
7549static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7550{
7551 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7552 * then hardware support 5Ghz.
7553 */
7554 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7555 {
7556 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7557 return true;
7558 }
7559 else
7560 {
7561 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7562 __func__);
7563 return false;
7564 }
7565}
7566
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307567/**---------------------------------------------------------------------------
7568
7569 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7570 generate function
7571
7572 This is generate the random mac address for WLAN interface
7573
7574 \param - pHddCtx - Pointer to HDD context
7575 idx - Start interface index to get auto
7576 generated mac addr.
7577 mac_addr - Mac address
7578
7579 \return - 0 for success, < 0 for failure
7580
7581 --------------------------------------------------------------------------*/
7582
7583static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7584 int idx, v_MACADDR_t mac_addr)
7585{
7586 int i;
7587 unsigned int serialno;
7588 serialno = wcnss_get_serial_number();
7589
7590 if (0 != serialno)
7591 {
7592 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7593 bytes of the serial number that can be used to generate
7594 the other 3 bytes of the MAC address. Mask off all but
7595 the lower 3 bytes (this will also make sure we don't
7596 overflow in the next step) */
7597 serialno &= 0x00FFFFFF;
7598
7599 /* we need a unique address for each session */
7600 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7601
7602 /* autogen other Mac addresses */
7603 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7604 {
7605 /* start with the entire default address */
7606 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7607 /* then replace the lower 3 bytes */
7608 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7609 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7610 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7611
7612 serialno++;
7613 hddLog(VOS_TRACE_LEVEL_ERROR,
7614 "%s: Derived Mac Addr: "
7615 MAC_ADDRESS_STR, __func__,
7616 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7617 }
7618
7619 }
7620 else
7621 {
7622 hddLog(LOGE, FL("Failed to Get Serial NO"));
7623 return -1;
7624 }
7625 return 0;
7626}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307627
7628/**---------------------------------------------------------------------------
7629
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 \brief hdd_wlan_startup() - HDD init function
7631
7632 This is the driver startup code executed once a WLAN device has been detected
7633
7634 \param - dev - Pointer to the underlying device
7635
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007636 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007637
7638 --------------------------------------------------------------------------*/
7639
7640int hdd_wlan_startup(struct device *dev )
7641{
7642 VOS_STATUS status;
7643 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007644 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007645 hdd_context_t *pHddCtx = NULL;
7646 v_CONTEXT_t pVosContext= NULL;
7647#ifdef WLAN_BTAMP_FEATURE
7648 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7649 WLANBAP_ConfigType btAmpConfig;
7650 hdd_config_t *pConfig;
7651#endif
7652 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007653 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307654 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007655
7656 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 /*
7658 * cfg80211: wiphy allocation
7659 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307660 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007661
7662 if(wiphy == NULL)
7663 {
7664 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007665 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007666 }
7667
7668 pHddCtx = wiphy_priv(wiphy);
7669
Jeff Johnson295189b2012-06-20 16:38:30 -07007670 //Initialize the adapter context to zeros.
7671 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7672
Jeff Johnson295189b2012-06-20 16:38:30 -07007673 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007674 hdd_prevent_suspend();
7675 pHddCtx->isLoadUnloadInProgress = TRUE;
7676
7677 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7678
7679 /*Get vos context here bcoz vos_open requires it*/
7680 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7681
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007682 if(pVosContext == NULL)
7683 {
7684 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7685 goto err_free_hdd_context;
7686 }
7687
Jeff Johnson295189b2012-06-20 16:38:30 -07007688 //Save the Global VOSS context in adapter context for future.
7689 pHddCtx->pvosContext = pVosContext;
7690
7691 //Save the adapter context in global context for future.
7692 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7693
Jeff Johnson295189b2012-06-20 16:38:30 -07007694 pHddCtx->parent_dev = dev;
7695
7696 init_completion(&pHddCtx->full_pwr_comp_var);
7697 init_completion(&pHddCtx->standby_comp_var);
7698 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007699 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007700 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307701 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007702
7703#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007704 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007705#else
7706 init_completion(&pHddCtx->driver_crda_req);
7707#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007708
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307709 spin_lock_init(&pHddCtx->schedScan_lock);
7710
Jeff Johnson295189b2012-06-20 16:38:30 -07007711 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7712
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307713#ifdef FEATURE_WLAN_TDLS
7714 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7715 * invoked by other instances also) to protect the concurrent
7716 * access for the Adapters by TDLS module.
7717 */
7718 mutex_init(&pHddCtx->tdls_lock);
7719#endif
7720
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307721 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007722 // Load all config first as TL config is needed during vos_open
7723 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7724 if(pHddCtx->cfg_ini == NULL)
7725 {
7726 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7727 goto err_free_hdd_context;
7728 }
7729
7730 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7731
7732 // Read and parse the qcom_cfg.ini file
7733 status = hdd_parse_config_ini( pHddCtx );
7734 if ( VOS_STATUS_SUCCESS != status )
7735 {
7736 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7737 __func__, WLAN_INI_FILE);
7738 goto err_config;
7739 }
Arif Hussaind5218912013-12-05 01:10:55 -08007740#ifdef MEMORY_DEBUG
7741 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7742 vos_mem_init();
7743
7744 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7745 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7746#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007747
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307748 /* INI has been read, initialise the configuredMcastBcastFilter with
7749 * INI value as this will serve as the default value
7750 */
7751 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7752 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7753 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307754
7755 if (false == hdd_is_5g_supported(pHddCtx))
7756 {
7757 //5Ghz is not supported.
7758 if (1 != pHddCtx->cfg_ini->nBandCapability)
7759 {
7760 hddLog(VOS_TRACE_LEVEL_INFO,
7761 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7762 pHddCtx->cfg_ini->nBandCapability = 1;
7763 }
7764 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307765
7766 /* If SNR Monitoring is enabled, FW has to parse all beacons
7767 * for calcaluting and storing the average SNR, so set Nth beacon
7768 * filter to 1 to enable FW to parse all the beaocons
7769 */
7770 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7771 {
7772 /* The log level is deliberately set to WARN as overriding
7773 * nthBeaconFilter to 1 will increase power cosumption and this
7774 * might just prove helpful to detect the power issue.
7775 */
7776 hddLog(VOS_TRACE_LEVEL_WARN,
7777 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7778 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7779 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007780 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307781 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307783 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 {
7785 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307786 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7787 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007788 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007789
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007790 // Update VOS trace levels based upon the cfg.ini
7791 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7792 pHddCtx->cfg_ini->vosTraceEnableBAP);
7793 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7794 pHddCtx->cfg_ini->vosTraceEnableTL);
7795 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7796 pHddCtx->cfg_ini->vosTraceEnableWDI);
7797 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7798 pHddCtx->cfg_ini->vosTraceEnableHDD);
7799 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7800 pHddCtx->cfg_ini->vosTraceEnableSME);
7801 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7802 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307803 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7804 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007805 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7806 pHddCtx->cfg_ini->vosTraceEnableWDA);
7807 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7808 pHddCtx->cfg_ini->vosTraceEnableSYS);
7809 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7810 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007811 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7812 pHddCtx->cfg_ini->vosTraceEnableSAP);
7813 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7814 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007815
Jeff Johnson295189b2012-06-20 16:38:30 -07007816 // Update WDI trace levels based upon the cfg.ini
7817 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7818 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7819 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7820 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7821 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7822 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7823 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7824 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007825
Jeff Johnson88ba7742013-02-27 14:36:02 -08007826 if (VOS_FTM_MODE == hdd_get_conparam())
7827 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007828 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7829 {
7830 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7831 goto err_free_hdd_context;
7832 }
7833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7834 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007836
Jeff Johnson88ba7742013-02-27 14:36:02 -08007837 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7839 {
7840 status = vos_watchdog_open(pVosContext,
7841 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7842
7843 if(!VOS_IS_STATUS_SUCCESS( status ))
7844 {
7845 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307846 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007847 }
7848 }
7849
7850 pHddCtx->isLogpInProgress = FALSE;
7851 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7852
Jeff Johnson295189b2012-06-20 16:38:30 -07007853 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7854 if(!VOS_IS_STATUS_SUCCESS(status))
7855 {
7856 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007857 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007858 }
7859
Amar Singhala49cbc52013-10-08 18:37:44 -07007860#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007861 /* initialize the NV module. This is required so that
7862 we can initialize the channel information in wiphy
7863 from the NV.bin data. The channel information in
7864 wiphy needs to be initialized before wiphy registration */
7865
7866 status = vos_nv_open();
7867 if (!VOS_IS_STATUS_SUCCESS(status))
7868 {
7869 /* NV module cannot be initialized */
7870 hddLog( VOS_TRACE_LEVEL_FATAL,
7871 "%s: vos_nv_open failed", __func__);
7872 goto err_clkvote;
7873 }
7874
7875 status = vos_init_wiphy_from_nv_bin();
7876 if (!VOS_IS_STATUS_SUCCESS(status))
7877 {
7878 /* NV module cannot be initialized */
7879 hddLog( VOS_TRACE_LEVEL_FATAL,
7880 "%s: vos_init_wiphy failed", __func__);
7881 goto err_vos_nv_close;
7882 }
7883
Amar Singhala49cbc52013-10-08 18:37:44 -07007884 /* registration of wiphy dev with cfg80211 */
7885 if (0 > wlan_hdd_cfg80211_register(wiphy))
7886 {
7887 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007888 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007889 }
7890#endif
7891
Jeff Johnson295189b2012-06-20 16:38:30 -07007892 status = vos_open( &pVosContext, 0);
7893 if ( !VOS_IS_STATUS_SUCCESS( status ))
7894 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007895 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007896 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007897 }
7898
Jeff Johnson295189b2012-06-20 16:38:30 -07007899 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7900
7901 if ( NULL == pHddCtx->hHal )
7902 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007904 goto err_vosclose;
7905 }
7906
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007907 status = vos_preStart( pHddCtx->pvosContext );
7908 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7909 {
7910 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7911 goto err_vosclose;
7912 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007913
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007914 /* Note that the vos_preStart() sequence triggers the cfg download.
7915 The cfg download must occur before we update the SME config
7916 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007917 status = hdd_set_sme_config( pHddCtx );
7918
7919 if ( VOS_STATUS_SUCCESS != status )
7920 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007921 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7922 goto err_vosclose;
7923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007924
7925 //Initialize the WMM module
7926 status = hdd_wmm_init(pHddCtx);
7927 if (!VOS_IS_STATUS_SUCCESS(status))
7928 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007929 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 goto err_vosclose;
7931 }
7932
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 /* In the integrated architecture we update the configuration from
7934 the INI file and from NV before vOSS has been started so that
7935 the final contents are available to send down to the cCPU */
7936
Arif Hussain66559122013-11-21 10:11:40 -08007937 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7938 {
7939 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7940 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7941 __func__, enable_dfs_chan_scan);
7942 }
7943 if (0 == enable_11d || 1 == enable_11d)
7944 {
7945 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7946 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7947 __func__, enable_11d);
7948 }
7949
Jeff Johnson295189b2012-06-20 16:38:30 -07007950 // Apply the cfg.ini to cfg.dat
7951 if (FALSE == hdd_update_config_dat(pHddCtx))
7952 {
7953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7954 goto err_vosclose;
7955 }
7956
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307957 // Get mac addr from platform driver
7958 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
7959
7960 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07007961 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307962 /* Store the mac addr for first interface */
7963 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
7964
7965 hddLog(VOS_TRACE_LEVEL_ERROR,
7966 "%s: WLAN Mac Addr: "
7967 MAC_ADDRESS_STR, __func__,
7968 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7969
7970 /* Here, passing Arg2 as 1 because we do not want to change the
7971 last 3 bytes (means non OUI bytes) of first interface mac
7972 addr.
7973 */
7974 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
7975 {
7976 hddLog(VOS_TRACE_LEVEL_ERROR,
7977 "%s: Failed to generate wlan interface mac addr "
7978 "using MAC from ini file ", __func__);
7979 }
7980 }
7981 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7982 {
7983 // Apply the NV to cfg.dat
7984 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07007985#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7986 /* There was not a valid set of MAC Addresses in NV. See if the
7987 default addresses were modified by the cfg.ini settings. If so,
7988 we'll use them, but if not, we'll autogenerate a set of MAC
7989 addresses based upon the device serial number */
7990
7991 static const v_MACADDR_t default_address =
7992 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07007993
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307994 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7995 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07007996 {
7997 /* cfg.ini has the default address, invoke autogen logic */
7998
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307999 /* Here, passing Arg2 as 0 because we want to change the
8000 last 3 bytes (means non OUI bytes) of all the interfaces
8001 mac addr.
8002 */
8003 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8004 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308006 hddLog(VOS_TRACE_LEVEL_ERROR,
8007 "%s: Failed to generate wlan interface mac addr "
8008 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8009 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008011 }
8012 else
8013#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8014 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008015 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 "%s: Invalid MAC address in NV, using MAC from ini file "
8017 MAC_ADDRESS_STR, __func__,
8018 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8019 }
8020 }
8021 {
8022 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308023
8024 /* Set the MAC Address Currently this is used by HAL to
8025 * add self sta. Remove this once self sta is added as
8026 * part of session open.
8027 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008028 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8029 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8030 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308031
Jeff Johnson295189b2012-06-20 16:38:30 -07008032 if (!HAL_STATUS_SUCCESS( halStatus ))
8033 {
8034 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8035 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08008036 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008037 }
8038 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008039
8040 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8041 Note: Firmware image will be read and downloaded inside vos_start API */
8042 status = vos_start( pHddCtx->pvosContext );
8043 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8044 {
8045 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
8046 goto err_vosclose;
8047 }
8048
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008049 /* Exchange capability info between Host and FW and also get versioning info from FW */
8050 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008051
8052 status = hdd_post_voss_start_config( pHddCtx );
8053 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8054 {
8055 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8056 __func__);
8057 goto err_vosstop;
8058 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008059
8060#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308061 wlan_hdd_cfg80211_update_reg_info( wiphy );
8062
8063 /* registration of wiphy dev with cfg80211 */
8064 if (0 > wlan_hdd_cfg80211_register(wiphy))
8065 {
8066 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8067 goto err_vosstop;
8068 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008069#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008070
Jeff Johnson295189b2012-06-20 16:38:30 -07008071 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8072 {
8073 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8074 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8075 }
8076 else
8077 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008078 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8079 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8080 if (pAdapter != NULL)
8081 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308082 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008083 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308084 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8085 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8086 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008087
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308088 /* Generate the P2P Device Address. This consists of the device's
8089 * primary MAC address with the locally administered bit set.
8090 */
8091 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008092 }
8093 else
8094 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308095 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8096 if (p2p_dev_addr != NULL)
8097 {
8098 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8099 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8100 }
8101 else
8102 {
8103 hddLog(VOS_TRACE_LEVEL_FATAL,
8104 "%s: Failed to allocate mac_address for p2p_device",
8105 __func__);
8106 goto err_close_adapter;
8107 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008109
8110 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8111 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8112 if ( NULL == pP2pAdapter )
8113 {
8114 hddLog(VOS_TRACE_LEVEL_FATAL,
8115 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008116 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008117 goto err_close_adapter;
8118 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008119 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008121
8122 if( pAdapter == NULL )
8123 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008124 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8125 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008126 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008127
Arif Hussain66559122013-11-21 10:11:40 -08008128 if (country_code)
8129 {
8130 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008131 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008132 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8133#ifndef CONFIG_ENABLE_LINUX_REG
8134 hdd_checkandupdate_phymode(pAdapter, country_code);
8135#endif
8136 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8137 country_code,
8138 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308139 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008140 if (eHAL_STATUS_SUCCESS == ret)
8141 {
Arif Hussaincb607082013-12-20 11:57:42 -08008142 ret = wait_for_completion_interruptible_timeout(
8143 &pAdapter->change_country_code,
8144 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8145
8146 if (0 >= ret)
8147 {
8148 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8149 "%s: SME while setting country code timed out", __func__);
8150 }
Arif Hussain66559122013-11-21 10:11:40 -08008151 }
8152 else
8153 {
Arif Hussaincb607082013-12-20 11:57:42 -08008154 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8155 "%s: SME Change Country code from module param fail ret=%d",
8156 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008157 }
8158 }
8159
Jeff Johnson295189b2012-06-20 16:38:30 -07008160#ifdef WLAN_BTAMP_FEATURE
8161 vStatus = WLANBAP_Open(pVosContext);
8162 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8163 {
8164 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8165 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008166 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008167 }
8168
8169 vStatus = BSL_Init(pVosContext);
8170 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8171 {
8172 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8173 "%s: Failed to Init BSL",__func__);
8174 goto err_bap_close;
8175 }
8176 vStatus = WLANBAP_Start(pVosContext);
8177 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8178 {
8179 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8180 "%s: Failed to start TL",__func__);
8181 goto err_bap_close;
8182 }
8183
8184 pConfig = pHddCtx->cfg_ini;
8185 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8186 status = WLANBAP_SetConfig(&btAmpConfig);
8187
8188#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008189
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008190#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8191 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8192 {
8193 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8194 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8195 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8196 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8197 }
8198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008199#ifdef FEATURE_WLAN_SCAN_PNO
8200 /*SME must send channel update configuration to RIVA*/
8201 sme_UpdateChannelConfig(pHddCtx->hHal);
8202#endif
8203
Jeff Johnson295189b2012-06-20 16:38:30 -07008204 /* Register with platform driver as client for Suspend/Resume */
8205 status = hddRegisterPmOps(pHddCtx);
8206 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8207 {
8208 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8209#ifdef WLAN_BTAMP_FEATURE
8210 goto err_bap_stop;
8211#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008212 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008213#endif //WLAN_BTAMP_FEATURE
8214 }
8215
Yue Ma0d4891e2013-08-06 17:01:45 -07008216 /* Open debugfs interface */
8217 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8218 {
8219 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8220 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008221 }
8222
Jeff Johnson295189b2012-06-20 16:38:30 -07008223 /* Register TM level change handler function to the platform */
8224 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8225 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8226 {
8227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8228 goto err_unregister_pmops;
8229 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008230
8231 /* register for riva power on lock to platform driver */
8232 if (req_riva_power_on_lock("wlan"))
8233 {
8234 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8235 __func__);
8236 goto err_unregister_pmops;
8237 }
8238
Jeff Johnson295189b2012-06-20 16:38:30 -07008239 // register net device notifier for device change notification
8240 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8241
8242 if(ret < 0)
8243 {
8244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8245 goto err_free_power_on_lock;
8246 }
8247
8248 //Initialize the nlink service
8249 if(nl_srv_init() != 0)
8250 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008252 goto err_reg_netdev;
8253 }
8254
Leo Chang4ce1cc52013-10-21 18:27:15 -07008255#ifdef WLAN_KD_READY_NOTIFIER
8256 pHddCtx->kd_nl_init = 1;
8257#endif /* WLAN_KD_READY_NOTIFIER */
8258
Jeff Johnson295189b2012-06-20 16:38:30 -07008259 //Initialize the BTC service
8260 if(btc_activate_service(pHddCtx) != 0)
8261 {
8262 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8263 goto err_nl_srv;
8264 }
8265
8266#ifdef PTT_SOCK_SVC_ENABLE
8267 //Initialize the PTT service
8268 if(ptt_sock_activate_svc(pHddCtx) != 0)
8269 {
8270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8271 goto err_nl_srv;
8272 }
8273#endif
8274
Jeff Johnson295189b2012-06-20 16:38:30 -07008275 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008276 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008278 /* Action frame registered in one adapter which will
8279 * applicable to all interfaces
8280 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008281 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008282 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008283
8284 mutex_init(&pHddCtx->sap_lock);
8285
8286 pHddCtx->isLoadUnloadInProgress = FALSE;
8287
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008288#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008289#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8290 /* Initialize the wake lcok */
8291 wake_lock_init(&pHddCtx->rx_wake_lock,
8292 WAKE_LOCK_SUSPEND,
8293 "qcom_rx_wakelock");
8294#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008295 /* Initialize the wake lcok */
8296 wake_lock_init(&pHddCtx->sap_wake_lock,
8297 WAKE_LOCK_SUSPEND,
8298 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008299#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008300
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008301 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8302 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008303
8304 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8305 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308306#ifndef CONFIG_ENABLE_LINUX_REG
8307 /*updating wiphy so that regulatory user hints can be processed*/
8308 if (wiphy)
8309 {
8310 regulatory_hint(wiphy, "00");
8311 }
8312#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008313 // Initialize the restart logic
8314 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308315
Leo Chang0b0e45a2013-12-15 15:18:55 -08008316#ifdef FEATURE_WLAN_CH_AVOID
8317 /* Plug in avoid channel notification callback */
8318 sme_AddChAvoidCallback(pHddCtx->hHal,
8319 hdd_hostapd_ch_avoid_cb);
8320#endif /* FEATURE_WLAN_CH_AVOID */
8321
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008322 //Register the traffic monitor timer now
8323 if ( pHddCtx->cfg_ini->dynSplitscan)
8324 {
8325 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8326 VOS_TIMER_TYPE_SW,
8327 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8328 (void *)pHddCtx);
8329 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008330 goto success;
8331
8332err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008333#ifdef WLAN_KD_READY_NOTIFIER
8334 nl_srv_exit(pHddCtx->ptt_pid);
8335#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008336 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008337#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008338err_reg_netdev:
8339 unregister_netdevice_notifier(&hdd_netdev_notifier);
8340
8341err_free_power_on_lock:
8342 free_riva_power_on_lock("wlan");
8343
8344err_unregister_pmops:
8345 hddDevTmUnregisterNotifyCallback(pHddCtx);
8346 hddDeregisterPmOps(pHddCtx);
8347
Yue Ma0d4891e2013-08-06 17:01:45 -07008348 hdd_debugfs_exit(pHddCtx);
8349
Jeff Johnson295189b2012-06-20 16:38:30 -07008350#ifdef WLAN_BTAMP_FEATURE
8351err_bap_stop:
8352 WLANBAP_Stop(pVosContext);
8353#endif
8354
8355#ifdef WLAN_BTAMP_FEATURE
8356err_bap_close:
8357 WLANBAP_Close(pVosContext);
8358#endif
8359
Jeff Johnson295189b2012-06-20 16:38:30 -07008360err_close_adapter:
8361 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008362
8363#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308364 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008365#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008366
8367err_vosstop:
8368 vos_stop(pVosContext);
8369
Amar Singhala49cbc52013-10-08 18:37:44 -07008370err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008371 status = vos_sched_close( pVosContext );
8372 if (!VOS_IS_STATUS_SUCCESS(status)) {
8373 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8374 "%s: Failed to close VOSS Scheduler", __func__);
8375 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8376 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008377 vos_close(pVosContext );
8378
8379err_wiphy_unregister:
8380
8381#ifdef CONFIG_ENABLE_LINUX_REG
8382 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008383
Amar Singhal0a402232013-10-11 20:57:16 -07008384err_vos_nv_close:
8385
8386 vos_nv_close();
8387
Jeff Johnson295189b2012-06-20 16:38:30 -07008388err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008389#endif
8390
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008391 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008392
8393err_wdclose:
8394 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8395 vos_watchdog_close(pVosContext);
8396
Jeff Johnson295189b2012-06-20 16:38:30 -07008397err_config:
8398 kfree(pHddCtx->cfg_ini);
8399 pHddCtx->cfg_ini= NULL;
8400
8401err_free_hdd_context:
8402 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008403 wiphy_free(wiphy) ;
8404 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008405 VOS_BUG(1);
8406
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008407 if (hdd_is_ssr_required())
8408 {
8409 /* WDI timeout had happened during load, so SSR is needed here */
8410 subsystem_restart("wcnss");
8411 msleep(5000);
8412 }
8413 hdd_set_ssr_required (VOS_FALSE);
8414
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008415 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008416
8417success:
8418 EXIT();
8419 return 0;
8420}
8421
8422/**---------------------------------------------------------------------------
8423
Jeff Johnson32d95a32012-09-10 13:15:23 -07008424 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008425
Jeff Johnson32d95a32012-09-10 13:15:23 -07008426 This is the driver entry point - called in different timeline depending
8427 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008428
8429 \param - None
8430
8431 \return - 0 for success, non zero for failure
8432
8433 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008434static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008435{
8436 VOS_STATUS status;
8437 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008438 struct device *dev = NULL;
8439 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008440#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8441 int max_retries = 0;
8442#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008443
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308444#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8445 vos_wconn_trace_init();
8446#endif
8447
Jeff Johnson295189b2012-06-20 16:38:30 -07008448 ENTER();
8449
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008450#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008451 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008452#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008453
8454 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8455 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8456
8457 //Power Up Libra WLAN card first if not already powered up
8458 status = vos_chipPowerUp(NULL,NULL,NULL);
8459 if (!VOS_IS_STATUS_SUCCESS(status))
8460 {
8461 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8462 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308463#ifdef WLAN_OPEN_SOURCE
8464 wake_lock_destroy(&wlan_wake_lock);
8465#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008466 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008467 }
8468
Jeff Johnson295189b2012-06-20 16:38:30 -07008469#ifdef ANI_BUS_TYPE_PCI
8470
8471 dev = wcnss_wlan_get_device();
8472
8473#endif // ANI_BUS_TYPE_PCI
8474
8475#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008476
8477#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8478 /* wait until WCNSS driver downloads NV */
8479 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8480 msleep(1000);
8481 }
8482 if (max_retries >= 5) {
8483 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308484#ifdef WLAN_OPEN_SOURCE
8485 wake_lock_destroy(&wlan_wake_lock);
8486#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008487 return -ENODEV;
8488 }
8489#endif
8490
Jeff Johnson295189b2012-06-20 16:38:30 -07008491 dev = wcnss_wlan_get_device();
8492#endif // ANI_BUS_TYPE_PLATFORM
8493
8494
8495 do {
8496 if (NULL == dev) {
8497 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8498 ret_status = -1;
8499 break;
8500 }
8501
Jeff Johnson295189b2012-06-20 16:38:30 -07008502#ifdef TIMER_MANAGER
8503 vos_timer_manager_init();
8504#endif
8505
8506 /* Preopen VOSS so that it is ready to start at least SAL */
8507 status = vos_preOpen(&pVosContext);
8508
8509 if (!VOS_IS_STATUS_SUCCESS(status))
8510 {
8511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8512 ret_status = -1;
8513 break;
8514 }
8515
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008516#ifndef MODULE
8517 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8518 */
8519 hdd_set_conparam((v_UINT_t)con_mode);
8520#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008521
8522 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008523 if (hdd_wlan_startup(dev))
8524 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008526 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008527 vos_preClose( &pVosContext );
8528 ret_status = -1;
8529 break;
8530 }
8531
8532 /* Cancel the vote for XO Core ON
8533 * This is done here for safety purposes in case we re-initialize without turning
8534 * it OFF in any error scenario.
8535 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008536 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008537 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008538 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008539 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8540 {
8541 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008542 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008543 }
8544 } while (0);
8545
8546 if (0 != ret_status)
8547 {
8548 //Assert Deep sleep signal now to put Libra HW in lowest power state
8549 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8550 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8551
8552 //Vote off any PMIC voltage supplies
8553 vos_chipPowerDown(NULL, NULL, NULL);
8554#ifdef TIMER_MANAGER
8555 vos_timer_exit();
8556#endif
8557#ifdef MEMORY_DEBUG
8558 vos_mem_exit();
8559#endif
8560
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008561#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008563#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008564 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8565 }
8566 else
8567 {
8568 //Send WLAN UP indication to Nlink Service
8569 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8570
8571 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008572 }
8573
8574 EXIT();
8575
8576 return ret_status;
8577}
8578
Jeff Johnson32d95a32012-09-10 13:15:23 -07008579/**---------------------------------------------------------------------------
8580
8581 \brief hdd_module_init() - Init Function
8582
8583 This is the driver entry point (invoked when module is loaded using insmod)
8584
8585 \param - None
8586
8587 \return - 0 for success, non zero for failure
8588
8589 --------------------------------------------------------------------------*/
8590#ifdef MODULE
8591static int __init hdd_module_init ( void)
8592{
8593 return hdd_driver_init();
8594}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008595#else /* #ifdef MODULE */
8596static int __init hdd_module_init ( void)
8597{
8598 /* Driver initialization is delayed to fwpath_changed_handler */
8599 return 0;
8600}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008601#endif /* #ifdef MODULE */
8602
Jeff Johnson295189b2012-06-20 16:38:30 -07008603
8604/**---------------------------------------------------------------------------
8605
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008606 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008607
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008608 This is the driver exit point (invoked when module is unloaded using rmmod
8609 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008610
8611 \param - None
8612
8613 \return - None
8614
8615 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008616static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008617{
8618 hdd_context_t *pHddCtx = NULL;
8619 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008620 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008621
8622 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8623
8624 //Get the global vos context
8625 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8626
8627 if(!pVosContext)
8628 {
8629 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8630 goto done;
8631 }
8632
8633 //Get the HDD context.
8634 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8635
8636 if(!pHddCtx)
8637 {
8638 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8639 }
8640 else
8641 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008642 while(isWDresetInProgress()) {
8643 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8644 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008645 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008646
8647 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8648 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8649 "%s:SSR never completed, fatal error", __func__);
8650 VOS_BUG(0);
8651 }
8652 }
8653
Jeff Johnson295189b2012-06-20 16:38:30 -07008654
8655 pHddCtx->isLoadUnloadInProgress = TRUE;
8656 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8657
8658 //Do all the cleanup before deregistering the driver
8659 hdd_wlan_exit(pHddCtx);
8660 }
8661
Jeff Johnson295189b2012-06-20 16:38:30 -07008662 vos_preClose( &pVosContext );
8663
8664#ifdef TIMER_MANAGER
8665 vos_timer_exit();
8666#endif
8667#ifdef MEMORY_DEBUG
8668 vos_mem_exit();
8669#endif
8670
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308671#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8672 vos_wconn_trace_exit();
8673#endif
8674
Jeff Johnson295189b2012-06-20 16:38:30 -07008675done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008676#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008677 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008678#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008679 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8680}
8681
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008682/**---------------------------------------------------------------------------
8683
8684 \brief hdd_module_exit() - Exit function
8685
8686 This is the driver exit point (invoked when module is unloaded using rmmod)
8687
8688 \param - None
8689
8690 \return - None
8691
8692 --------------------------------------------------------------------------*/
8693static void __exit hdd_module_exit(void)
8694{
8695 hdd_driver_exit();
8696}
8697
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008698#ifdef MODULE
8699static int fwpath_changed_handler(const char *kmessage,
8700 struct kernel_param *kp)
8701{
Jeff Johnson76052702013-04-16 13:55:05 -07008702 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008703}
8704
8705static int con_mode_handler(const char *kmessage,
8706 struct kernel_param *kp)
8707{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008708 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008709}
8710#else /* #ifdef MODULE */
8711/**---------------------------------------------------------------------------
8712
Jeff Johnson76052702013-04-16 13:55:05 -07008713 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008714
Jeff Johnson76052702013-04-16 13:55:05 -07008715 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008716 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008717 - invoked when module parameter fwpath is modified from userspace to signal
8718 initializing the WLAN driver or when con_mode is modified from userspace
8719 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008720
8721 \return - 0 for success, non zero for failure
8722
8723 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008724static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008725{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008726 int ret_status;
8727
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008728 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008729 ret_status = hdd_driver_init();
8730 wlan_hdd_inited = ret_status ? 0 : 1;
8731 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008732 }
8733
8734 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008735
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008736 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008737
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008738 ret_status = hdd_driver_init();
8739 wlan_hdd_inited = ret_status ? 0 : 1;
8740 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008741}
8742
Jeff Johnson295189b2012-06-20 16:38:30 -07008743/**---------------------------------------------------------------------------
8744
Jeff Johnson76052702013-04-16 13:55:05 -07008745 \brief fwpath_changed_handler() - Handler Function
8746
8747 Handle changes to the fwpath parameter
8748
8749 \return - 0 for success, non zero for failure
8750
8751 --------------------------------------------------------------------------*/
8752static int fwpath_changed_handler(const char *kmessage,
8753 struct kernel_param *kp)
8754{
8755 int ret;
8756
8757 ret = param_set_copystring(kmessage, kp);
8758 if (0 == ret)
8759 ret = kickstart_driver();
8760 return ret;
8761}
8762
8763/**---------------------------------------------------------------------------
8764
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008765 \brief con_mode_handler() -
8766
8767 Handler function for module param con_mode when it is changed by userspace
8768 Dynamically linked - do nothing
8769 Statically linked - exit and init driver, as in rmmod and insmod
8770
Jeff Johnson76052702013-04-16 13:55:05 -07008771 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008772
Jeff Johnson76052702013-04-16 13:55:05 -07008773 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008774
8775 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008776static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008777{
Jeff Johnson76052702013-04-16 13:55:05 -07008778 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008779
Jeff Johnson76052702013-04-16 13:55:05 -07008780 ret = param_set_int(kmessage, kp);
8781 if (0 == ret)
8782 ret = kickstart_driver();
8783 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008784}
8785#endif /* #ifdef MODULE */
8786
8787/**---------------------------------------------------------------------------
8788
Jeff Johnson295189b2012-06-20 16:38:30 -07008789 \brief hdd_get_conparam() -
8790
8791 This is the driver exit point (invoked when module is unloaded using rmmod)
8792
8793 \param - None
8794
8795 \return - tVOS_CON_MODE
8796
8797 --------------------------------------------------------------------------*/
8798tVOS_CON_MODE hdd_get_conparam ( void )
8799{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008800#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008801 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008802#else
8803 return (tVOS_CON_MODE)curr_con_mode;
8804#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008805}
8806void hdd_set_conparam ( v_UINT_t newParam )
8807{
8808 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008809#ifndef MODULE
8810 curr_con_mode = con_mode;
8811#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008812}
8813/**---------------------------------------------------------------------------
8814
8815 \brief hdd_softap_sta_deauth() - function
8816
8817 This to take counter measure to handle deauth req from HDD
8818
8819 \param - pAdapter - Pointer to the HDD
8820
8821 \param - enable - boolean value
8822
8823 \return - None
8824
8825 --------------------------------------------------------------------------*/
8826
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008827VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008828{
Jeff Johnson295189b2012-06-20 16:38:30 -07008829 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008830 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008831
8832 ENTER();
8833
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008834 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8835 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008836
8837 //Ignore request to deauth bcmc station
8838 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008839 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008840
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008841 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008842
8843 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008844 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008845}
8846
8847/**---------------------------------------------------------------------------
8848
8849 \brief hdd_softap_sta_disassoc() - function
8850
8851 This to take counter measure to handle deauth req from HDD
8852
8853 \param - pAdapter - Pointer to the HDD
8854
8855 \param - enable - boolean value
8856
8857 \return - None
8858
8859 --------------------------------------------------------------------------*/
8860
8861void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8862{
8863 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8864
8865 ENTER();
8866
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308867 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008868
8869 //Ignore request to disassoc bcmc station
8870 if( pDestMacAddress[0] & 0x1 )
8871 return;
8872
8873 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8874}
8875
8876void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8877{
8878 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8879
8880 ENTER();
8881
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308882 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008883
8884 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8885}
8886
Jeff Johnson295189b2012-06-20 16:38:30 -07008887/**---------------------------------------------------------------------------
8888 *
8889 * \brief hdd_get__concurrency_mode() -
8890 *
8891 *
8892 * \param - None
8893 *
8894 * \return - CONCURRENCY MODE
8895 *
8896 * --------------------------------------------------------------------------*/
8897tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8898{
8899 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8900 hdd_context_t *pHddCtx;
8901
8902 if (NULL != pVosContext)
8903 {
8904 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8905 if (NULL != pHddCtx)
8906 {
8907 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8908 }
8909 }
8910
8911 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008912 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008913 return VOS_STA;
8914}
8915
8916/* Decide whether to allow/not the apps power collapse.
8917 * Allow apps power collapse if we are in connected state.
8918 * if not, allow only if we are in IMPS */
8919v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8920{
8921 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008922 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008923 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008924 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8925 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8926 hdd_adapter_t *pAdapter = NULL;
8927 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008928 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008929
Jeff Johnson295189b2012-06-20 16:38:30 -07008930 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8931 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008932
Yathish9f22e662012-12-10 14:21:35 -08008933 concurrent_state = hdd_get_concurrency_mode();
8934
8935#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8936 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8937 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8938 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8939 return TRUE;
8940#endif
8941
Jeff Johnson295189b2012-06-20 16:38:30 -07008942 /*loop through all adapters. TBD fix for Concurrency */
8943 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8944 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8945 {
8946 pAdapter = pAdapterNode->pAdapter;
8947 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8948 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8949 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008950 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008951 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008952 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008953 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8954 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008955 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008956 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008957 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8958 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008959 return FALSE;
8960 }
8961 }
8962 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8963 pAdapterNode = pNext;
8964 }
8965 return TRUE;
8966}
8967
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008968/* Decides whether to send suspend notification to Riva
8969 * if any adapter is in BMPS; then it is required */
8970v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8971{
8972 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8973 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8974
8975 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8976 {
8977 return TRUE;
8978 }
8979 return FALSE;
8980}
8981
Jeff Johnson295189b2012-06-20 16:38:30 -07008982void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8983{
8984 switch(mode)
8985 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008986 case VOS_STA_MODE:
8987 case VOS_P2P_CLIENT_MODE:
8988 case VOS_P2P_GO_MODE:
8989 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008990 pHddCtx->concurrency_mode |= (1 << mode);
8991 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008992 break;
8993 default:
8994 break;
8995
8996 }
8997 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8998 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8999}
9000
9001
9002void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9003{
9004 switch(mode)
9005 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009006 case VOS_STA_MODE:
9007 case VOS_P2P_CLIENT_MODE:
9008 case VOS_P2P_GO_MODE:
9009 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009010 pHddCtx->no_of_sessions[mode]--;
9011 if (!(pHddCtx->no_of_sessions[mode]))
9012 pHddCtx->concurrency_mode &= (~(1 << mode));
9013 break;
9014 default:
9015 break;
9016 }
9017 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9018 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9019}
9020
Jeff Johnsone7245742012-09-05 17:12:55 -07009021/**---------------------------------------------------------------------------
9022 *
9023 * \brief wlan_hdd_restart_init
9024 *
9025 * This function initalizes restart timer/flag. An internal function.
9026 *
9027 * \param - pHddCtx
9028 *
9029 * \return - None
9030 *
9031 * --------------------------------------------------------------------------*/
9032
9033static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9034{
9035 /* Initialize */
9036 pHddCtx->hdd_restart_retries = 0;
9037 atomic_set(&pHddCtx->isRestartInProgress, 0);
9038 vos_timer_init(&pHddCtx->hdd_restart_timer,
9039 VOS_TIMER_TYPE_SW,
9040 wlan_hdd_restart_timer_cb,
9041 pHddCtx);
9042}
9043/**---------------------------------------------------------------------------
9044 *
9045 * \brief wlan_hdd_restart_deinit
9046 *
9047 * This function cleans up the resources used. An internal function.
9048 *
9049 * \param - pHddCtx
9050 *
9051 * \return - None
9052 *
9053 * --------------------------------------------------------------------------*/
9054
9055static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9056{
9057
9058 VOS_STATUS vos_status;
9059 /* Block any further calls */
9060 atomic_set(&pHddCtx->isRestartInProgress, 1);
9061 /* Cleanup */
9062 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9063 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009064 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009065 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9066 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009067 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009068
9069}
9070
9071/**---------------------------------------------------------------------------
9072 *
9073 * \brief wlan_hdd_framework_restart
9074 *
9075 * This function uses a cfg80211 API to start a framework initiated WLAN
9076 * driver module unload/load.
9077 *
9078 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9079 *
9080 *
9081 * \param - pHddCtx
9082 *
9083 * \return - VOS_STATUS_SUCCESS: Success
9084 * VOS_STATUS_E_EMPTY: Adapter is Empty
9085 * VOS_STATUS_E_NOMEM: No memory
9086
9087 * --------------------------------------------------------------------------*/
9088
9089static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9090{
9091 VOS_STATUS status = VOS_STATUS_SUCCESS;
9092 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009093 int len = (sizeof (struct ieee80211_mgmt));
9094 struct ieee80211_mgmt *mgmt = NULL;
9095
9096 /* Prepare the DEAUTH managment frame with reason code */
9097 mgmt = kzalloc(len, GFP_KERNEL);
9098 if(mgmt == NULL)
9099 {
9100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9101 "%s: memory allocation failed (%d bytes)", __func__, len);
9102 return VOS_STATUS_E_NOMEM;
9103 }
9104 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009105
9106 /* Iterate over all adapters/devices */
9107 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9108 do
9109 {
9110 if( (status == VOS_STATUS_SUCCESS) &&
9111 pAdapterNode &&
9112 pAdapterNode->pAdapter)
9113 {
9114 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9115 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9116 pAdapterNode->pAdapter->dev->name,
9117 pAdapterNode->pAdapter->device_mode,
9118 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009119 /*
9120 * CFG80211 event to restart the driver
9121 *
9122 * 'cfg80211_send_unprot_deauth' sends a
9123 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9124 * of SME(Linux Kernel) state machine.
9125 *
9126 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9127 * the driver.
9128 *
9129 */
9130
9131 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009132 }
9133 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9134 pAdapterNode = pNext;
9135 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9136
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009137
9138 /* Free the allocated management frame */
9139 kfree(mgmt);
9140
Jeff Johnsone7245742012-09-05 17:12:55 -07009141 /* Retry until we unload or reach max count */
9142 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9143 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9144
9145 return status;
9146
9147}
9148/**---------------------------------------------------------------------------
9149 *
9150 * \brief wlan_hdd_restart_timer_cb
9151 *
9152 * Restart timer callback. An internal function.
9153 *
9154 * \param - User data:
9155 *
9156 * \return - None
9157 *
9158 * --------------------------------------------------------------------------*/
9159
9160void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9161{
9162 hdd_context_t *pHddCtx = usrDataForCallback;
9163 wlan_hdd_framework_restart(pHddCtx);
9164 return;
9165
9166}
9167
9168
9169/**---------------------------------------------------------------------------
9170 *
9171 * \brief wlan_hdd_restart_driver
9172 *
9173 * This function sends an event to supplicant to restart the WLAN driver.
9174 *
9175 * This function is called from vos_wlanRestart.
9176 *
9177 * \param - pHddCtx
9178 *
9179 * \return - VOS_STATUS_SUCCESS: Success
9180 * VOS_STATUS_E_EMPTY: Adapter is Empty
9181 * VOS_STATUS_E_ALREADY: Request already in progress
9182
9183 * --------------------------------------------------------------------------*/
9184VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9185{
9186 VOS_STATUS status = VOS_STATUS_SUCCESS;
9187
9188 /* A tight check to make sure reentrancy */
9189 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9190 {
9191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9192 "%s: WLAN restart is already in progress", __func__);
9193
9194 return VOS_STATUS_E_ALREADY;
9195 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009196 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009197#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009198 wcnss_reset_intr();
9199#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009200
Jeff Johnsone7245742012-09-05 17:12:55 -07009201 return status;
9202}
9203
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009204/*
9205 * API to find if there is any STA or P2P-Client is connected
9206 */
9207VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9208{
9209 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9210}
Jeff Johnsone7245742012-09-05 17:12:55 -07009211
Jeff Johnson295189b2012-06-20 16:38:30 -07009212//Register the module init/exit functions
9213module_init(hdd_module_init);
9214module_exit(hdd_module_exit);
9215
9216MODULE_LICENSE("Dual BSD/GPL");
9217MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9218MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9219
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009220module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9221 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009222
Jeff Johnson76052702013-04-16 13:55:05 -07009223module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009224 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009225
9226module_param(enable_dfs_chan_scan, int,
9227 S_IRUSR | S_IRGRP | S_IROTH);
9228
9229module_param(enable_11d, int,
9230 S_IRUSR | S_IRGRP | S_IROTH);
9231
9232module_param(country_code, charp,
9233 S_IRUSR | S_IRGRP | S_IROTH);