blob: 95fb6ec4c98b4763830c983a0e8e272df1e9d3b6 [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{
5492 struct net_device *pWlanDev = pAdapter->dev;
5493
Rajeev79dbe4c2013-10-05 11:03:42 +05305494#ifdef FEATURE_WLAN_BATCH_SCAN
5495 tHddBatchScanRsp *pNode;
5496 tHddBatchScanRsp *pPrev;
5497 if (pAdapter)
5498 {
Rajeev79dbe4c2013-10-05 11:03:42 +05305499 pNode = pAdapter->pBatchScanRsp;
5500 while (pNode)
5501 {
5502 pPrev = pNode;
5503 pNode = pNode->pNext;
5504 vos_mem_free((v_VOID_t * )pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005505 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305506 }
5507 pAdapter->pBatchScanRsp = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305508 }
5509#endif
5510
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5512 if( rtnl_held )
5513 {
5514 unregister_netdevice(pWlanDev);
5515 }
5516 else
5517 {
5518 unregister_netdev(pWlanDev);
5519 }
5520 // note that the pAdapter is no longer valid at this point
5521 // since the memory has been reclaimed
5522 }
5523
5524}
5525
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005526void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5527{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305528 VOS_STATUS status;
5529 hdd_adapter_t *pAdapter = NULL;
5530 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005531
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305532 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005533
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305534 /*loop through all adapters.*/
5535 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005536 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305537 pAdapter = pAdapterNode->pAdapter;
5538 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5539 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005540
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305541 { // we skip this registration for modes other than STA and P2P client modes.
5542 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5543 pAdapterNode = pNext;
5544 continue;
5545 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005546
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305547 //Apply Dynamic DTIM For P2P
5548 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5549 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5550 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5551 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5552 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5553 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5554 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5555 (eConnectionState_Associated ==
5556 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5557 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5558 {
5559 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005560
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305561 powerRequest.uIgnoreDTIM = 1;
5562 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5563
5564 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5565 {
5566 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5567 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5568 }
5569 else
5570 {
5571 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5572 }
5573
5574 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5575 * specified during Enter/Exit BMPS when LCD off*/
5576 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5577 NULL, eANI_BOOLEAN_FALSE);
5578 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5579 NULL, eANI_BOOLEAN_FALSE);
5580
5581 /* switch to the DTIM specified in cfg.ini */
5582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5583 "Switch to DTIM %d", powerRequest.uListenInterval);
5584 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5585 break;
5586
5587 }
5588
5589 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5590 pAdapterNode = pNext;
5591 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005592}
5593
5594void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5595{
5596 /*Switch back to DTIM 1*/
5597 tSirSetPowerParamsReq powerRequest = { 0 };
5598
5599 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5600 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005601 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005602
5603 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5604 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5605 NULL, eANI_BOOLEAN_FALSE);
5606 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5607 NULL, eANI_BOOLEAN_FALSE);
5608
5609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5610 "Switch to DTIM%d",powerRequest.uListenInterval);
5611 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5612
5613}
5614
Jeff Johnson295189b2012-06-20 16:38:30 -07005615VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5616{
5617 VOS_STATUS status = VOS_STATUS_SUCCESS;
5618
5619 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5620 {
5621 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5622 }
5623
5624 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5625 {
5626 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5627 }
5628
5629 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5630 {
5631 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5632 }
5633
5634 return status;
5635}
5636
5637VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5638{
5639 hdd_adapter_t *pAdapter = NULL;
5640 eHalStatus halStatus;
5641 VOS_STATUS status = VOS_STATUS_E_INVAL;
5642 v_BOOL_t disableBmps = FALSE;
5643 v_BOOL_t disableImps = FALSE;
5644
5645 switch(session_type)
5646 {
5647 case WLAN_HDD_INFRA_STATION:
5648 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005649 case WLAN_HDD_P2P_CLIENT:
5650 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005651 //Exit BMPS -> Is Sta/P2P Client is already connected
5652 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5653 if((NULL != pAdapter)&&
5654 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5655 {
5656 disableBmps = TRUE;
5657 }
5658
5659 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5660 if((NULL != pAdapter)&&
5661 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5662 {
5663 disableBmps = TRUE;
5664 }
5665
5666 //Exit both Bmps and Imps incase of Go/SAP Mode
5667 if((WLAN_HDD_SOFTAP == session_type) ||
5668 (WLAN_HDD_P2P_GO == session_type))
5669 {
5670 disableBmps = TRUE;
5671 disableImps = TRUE;
5672 }
5673
5674 if(TRUE == disableImps)
5675 {
5676 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5677 {
5678 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5679 }
5680 }
5681
5682 if(TRUE == disableBmps)
5683 {
5684 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5685 {
5686 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5687
5688 if(eHAL_STATUS_SUCCESS != halStatus)
5689 {
5690 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005691 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 VOS_ASSERT(0);
5693 return status;
5694 }
5695 }
5696
5697 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5698 {
5699 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5700
5701 if(eHAL_STATUS_SUCCESS != halStatus)
5702 {
5703 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005704 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005705 VOS_ASSERT(0);
5706 return status;
5707 }
5708 }
5709 }
5710
5711 if((TRUE == disableBmps) ||
5712 (TRUE == disableImps))
5713 {
5714 /* Now, get the chip into Full Power now */
5715 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5716 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5717 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5718
5719 if(halStatus != eHAL_STATUS_SUCCESS)
5720 {
5721 if(halStatus == eHAL_STATUS_PMC_PENDING)
5722 {
5723 //Block on a completion variable. Can't wait forever though
5724 wait_for_completion_interruptible_timeout(
5725 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5726 }
5727 else
5728 {
5729 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005730 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005731 VOS_ASSERT(0);
5732 return status;
5733 }
5734 }
5735
5736 status = VOS_STATUS_SUCCESS;
5737 }
5738
5739 break;
5740 }
5741 return status;
5742}
5743
5744hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005745 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005746 tANI_U8 rtnl_held )
5747{
5748 hdd_adapter_t *pAdapter = NULL;
5749 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5750 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5751 VOS_STATUS exitbmpsStatus;
5752
Arif Hussain6d2a3322013-11-17 19:50:10 -08005753 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005754
5755 //Disable BMPS incase of Concurrency
5756 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5757
5758 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5759 {
5760 //Fail to Exit BMPS
5761 VOS_ASSERT(0);
5762 return NULL;
5763 }
5764
5765 switch(session_type)
5766 {
5767 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005768 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005769 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 {
5771 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5772
5773 if( NULL == pAdapter )
5774 return NULL;
5775
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305776#ifdef FEATURE_WLAN_TDLS
5777 /* A Mutex Lock is introduced while changing/initializing the mode to
5778 * protect the concurrent access for the Adapters by TDLS module.
5779 */
5780 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5781 {
5782 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5783 "%s: unable to lock list", __func__);
5784 return NULL;
5785 }
5786#endif
5787
Jeff Johnsone7245742012-09-05 17:12:55 -07005788 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5789 NL80211_IFTYPE_P2P_CLIENT:
5790 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005791
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305793#ifdef FEATURE_WLAN_TDLS
5794 mutex_unlock(&pHddCtx->tdls_lock);
5795#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305796
5797 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 if( VOS_STATUS_SUCCESS != status )
5799 goto err_free_netdev;
5800
5801 status = hdd_register_interface( pAdapter, rtnl_held );
5802 if( VOS_STATUS_SUCCESS != status )
5803 {
5804 hdd_deinit_adapter(pHddCtx, pAdapter);
5805 goto err_free_netdev;
5806 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305807
5808#ifdef WLAN_NS_OFFLOAD
5809 // Workqueue which gets scheduled in IPv6 notification callback.
5810 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5811#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 //Stop the Interface TX queue.
5813 netif_tx_disable(pAdapter->dev);
5814 //netif_tx_disable(pWlanDev);
5815 netif_carrier_off(pAdapter->dev);
5816
5817 break;
5818 }
5819
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 case WLAN_HDD_SOFTAP:
5822 {
5823 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5824 if( NULL == pAdapter )
5825 return NULL;
5826
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5828 NL80211_IFTYPE_AP:
5829 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 pAdapter->device_mode = session_type;
5831
5832 status = hdd_init_ap_mode(pAdapter);
5833 if( VOS_STATUS_SUCCESS != status )
5834 goto err_free_netdev;
5835
5836 status = hdd_register_hostapd( pAdapter, rtnl_held );
5837 if( VOS_STATUS_SUCCESS != status )
5838 {
5839 hdd_deinit_adapter(pHddCtx, pAdapter);
5840 goto err_free_netdev;
5841 }
5842
5843 netif_tx_disable(pAdapter->dev);
5844 netif_carrier_off(pAdapter->dev);
5845
5846 hdd_set_conparam( 1 );
5847 break;
5848 }
5849 case WLAN_HDD_MONITOR:
5850 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5852 if( NULL == pAdapter )
5853 return NULL;
5854
5855 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5856 pAdapter->device_mode = session_type;
5857 status = hdd_register_interface( pAdapter, rtnl_held );
5858#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5859 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5860#else
5861 pAdapter->dev->open = hdd_mon_open;
5862 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5863#endif
5864 hdd_init_tx_rx( pAdapter );
5865 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5866 //Set adapter to be used for data tx. It will use either GO or softap.
5867 pAdapter->sessionCtx.monitor.pAdapterForTx =
5868 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5870 {
5871 pAdapter->sessionCtx.monitor.pAdapterForTx =
5872 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5873 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005874 /* This workqueue will be used to transmit management packet over
5875 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005876 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5877 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5878 return NULL;
5879 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005880
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5882 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 }
5884 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 case WLAN_HDD_FTM:
5886 {
5887 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5888
5889 if( NULL == pAdapter )
5890 return NULL;
5891 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5892 * message while loading driver in FTM mode. */
5893 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5894 pAdapter->device_mode = session_type;
5895 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305896
5897 hdd_init_tx_rx( pAdapter );
5898
5899 //Stop the Interface TX queue.
5900 netif_tx_disable(pAdapter->dev);
5901 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 }
5903 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 default:
5905 {
5906 VOS_ASSERT(0);
5907 return NULL;
5908 }
5909 }
5910
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 if( VOS_STATUS_SUCCESS == status )
5912 {
5913 //Add it to the hdd's session list.
5914 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5915 if( NULL == pHddAdapterNode )
5916 {
5917 status = VOS_STATUS_E_NOMEM;
5918 }
5919 else
5920 {
5921 pHddAdapterNode->pAdapter = pAdapter;
5922 status = hdd_add_adapter_back ( pHddCtx,
5923 pHddAdapterNode );
5924 }
5925 }
5926
5927 if( VOS_STATUS_SUCCESS != status )
5928 {
5929 if( NULL != pAdapter )
5930 {
5931 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5932 pAdapter = NULL;
5933 }
5934 if( NULL != pHddAdapterNode )
5935 {
5936 vos_mem_free( pHddAdapterNode );
5937 }
5938
5939 goto resume_bmps;
5940 }
5941
5942 if(VOS_STATUS_SUCCESS == status)
5943 {
5944 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5945
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005946 //Initialize the WoWL service
5947 if(!hdd_init_wowl(pAdapter))
5948 {
5949 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5950 goto err_free_netdev;
5951 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 return pAdapter;
5954
5955err_free_netdev:
5956 free_netdev(pAdapter->dev);
5957 wlan_hdd_release_intf_addr( pHddCtx,
5958 pAdapter->macAddressCurrent.bytes );
5959
5960resume_bmps:
5961 //If bmps disabled enable it
5962 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5963 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305964 if (pHddCtx->hdd_wlan_suspended)
5965 {
5966 hdd_set_pwrparams(pHddCtx);
5967 }
5968 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 }
5970 return NULL;
5971}
5972
5973VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5974 tANI_U8 rtnl_held )
5975{
5976 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5977 VOS_STATUS status;
5978
5979 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5980 if( VOS_STATUS_SUCCESS != status )
5981 return status;
5982
5983 while ( pCurrent->pAdapter != pAdapter )
5984 {
5985 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5986 if( VOS_STATUS_SUCCESS != status )
5987 break;
5988
5989 pCurrent = pNext;
5990 }
5991 pAdapterNode = pCurrent;
5992 if( VOS_STATUS_SUCCESS == status )
5993 {
5994 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5995 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305996
5997#ifdef FEATURE_WLAN_TDLS
5998
5999 /* A Mutex Lock is introduced while changing/initializing the mode to
6000 * protect the concurrent access for the Adapters by TDLS module.
6001 */
6002 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6003 {
6004 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6005 "%s: unable to lock list", __func__);
6006 return VOS_STATUS_E_FAILURE;
6007 }
6008#endif
6009
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 hdd_remove_adapter( pHddCtx, pAdapterNode );
6011 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006012 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006013
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306014#ifdef FEATURE_WLAN_TDLS
6015 mutex_unlock(&pHddCtx->tdls_lock);
6016#endif
6017
Jeff Johnson295189b2012-06-20 16:38:30 -07006018
6019 /* If there is a single session of STA/P2P client, re-enable BMPS */
6020 if ((!vos_concurrent_sessions_running()) &&
6021 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6022 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6023 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306024 if (pHddCtx->hdd_wlan_suspended)
6025 {
6026 hdd_set_pwrparams(pHddCtx);
6027 }
6028 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 }
6030
6031 return VOS_STATUS_SUCCESS;
6032 }
6033
6034 return VOS_STATUS_E_FAILURE;
6035}
6036
6037VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6038{
6039 hdd_adapter_list_node_t *pHddAdapterNode;
6040 VOS_STATUS status;
6041
6042 ENTER();
6043
6044 do
6045 {
6046 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6047 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6048 {
6049 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6050 vos_mem_free( pHddAdapterNode );
6051 }
6052 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6053
6054 EXIT();
6055
6056 return VOS_STATUS_SUCCESS;
6057}
6058
6059void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6060{
6061 v_U8_t addIE[1] = {0};
6062
6063 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6064 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6065 eANI_BOOLEAN_FALSE) )
6066 {
6067 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006068 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 }
6070
6071 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6072 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6073 eANI_BOOLEAN_FALSE) )
6074 {
6075 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006076 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006077 }
6078
6079 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6080 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6081 eANI_BOOLEAN_FALSE) )
6082 {
6083 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006084 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 }
6086}
6087
6088VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6089{
6090 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6091 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6092 union iwreq_data wrqu;
6093
6094 ENTER();
6095
6096 switch(pAdapter->device_mode)
6097 {
6098 case WLAN_HDD_INFRA_STATION:
6099 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006100 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006101 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6102 {
6103 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6104 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6105 pAdapter->sessionId,
6106 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6107 else
6108 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6109 pAdapter->sessionId,
6110 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6111 //success implies disconnect command got queued up successfully
6112 if(halStatus == eHAL_STATUS_SUCCESS)
6113 {
6114 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6115 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6116 }
6117 memset(&wrqu, '\0', sizeof(wrqu));
6118 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6119 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6120 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6121 }
6122 else
6123 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306124 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306126#ifdef WLAN_OPEN_SOURCE
6127#ifdef WLAN_NS_OFFLOAD
6128 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6129#endif
6130#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006131
6132 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6133 {
6134 INIT_COMPLETION(pAdapter->session_close_comp_var);
6135 if (eHAL_STATUS_SUCCESS ==
6136 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6137 hdd_smeCloseSessionCallback, pAdapter))
6138 {
6139 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006140 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 &pAdapter->session_close_comp_var,
6142 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6143 }
6144 }
6145
6146 break;
6147
6148 case WLAN_HDD_SOFTAP:
6149 case WLAN_HDD_P2P_GO:
6150 //Any softap specific cleanup here...
6151 mutex_lock(&pHddCtx->sap_lock);
6152 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6153 {
6154 VOS_STATUS status;
6155 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6156
6157 //Stop Bss.
6158 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6159 if (VOS_IS_STATUS_SUCCESS(status))
6160 {
6161 hdd_hostapd_state_t *pHostapdState =
6162 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6163
6164 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6165
6166 if (!VOS_IS_STATUS_SUCCESS(status))
6167 {
6168 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006169 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 }
6171 }
6172 else
6173 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006174 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 }
6176 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6177
6178 if (eHAL_STATUS_FAILURE ==
6179 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6180 0, NULL, eANI_BOOLEAN_FALSE))
6181 {
6182 hddLog(LOGE,
6183 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006184 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006185 }
6186
6187 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6188 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6189 eANI_BOOLEAN_FALSE) )
6190 {
6191 hddLog(LOGE,
6192 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6193 }
6194
6195 // Reset WNI_CFG_PROBE_RSP Flags
6196 wlan_hdd_reset_prob_rspies(pAdapter);
6197 kfree(pAdapter->sessionCtx.ap.beacon);
6198 pAdapter->sessionCtx.ap.beacon = NULL;
6199 }
6200 mutex_unlock(&pHddCtx->sap_lock);
6201 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006202
Jeff Johnson295189b2012-06-20 16:38:30 -07006203 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006204#ifdef WLAN_OPEN_SOURCE
6205 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6206#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006207 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006208
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 default:
6210 break;
6211 }
6212
6213 EXIT();
6214 return VOS_STATUS_SUCCESS;
6215}
6216
6217VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6218{
6219 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6220 VOS_STATUS status;
6221 hdd_adapter_t *pAdapter;
6222
6223 ENTER();
6224
6225 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6226
6227 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6228 {
6229 pAdapter = pAdapterNode->pAdapter;
6230 netif_tx_disable(pAdapter->dev);
6231 netif_carrier_off(pAdapter->dev);
6232
6233 hdd_stop_adapter( pHddCtx, pAdapter );
6234
6235 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6236 pAdapterNode = pNext;
6237 }
6238
6239 EXIT();
6240
6241 return VOS_STATUS_SUCCESS;
6242}
6243
6244VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6245{
6246 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6247 VOS_STATUS status;
6248 hdd_adapter_t *pAdapter;
6249
6250 ENTER();
6251
6252 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6253
6254 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6255 {
6256 pAdapter = pAdapterNode->pAdapter;
6257 netif_tx_disable(pAdapter->dev);
6258 netif_carrier_off(pAdapter->dev);
6259
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006260 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6261
Jeff Johnson295189b2012-06-20 16:38:30 -07006262 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306263 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6264 {
6265 hdd_wmm_adapter_close( pAdapter );
6266 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6267 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006268
6269 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6270 pAdapterNode = pNext;
6271 }
6272
6273 EXIT();
6274
6275 return VOS_STATUS_SUCCESS;
6276}
6277
6278VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6279{
6280 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6281 VOS_STATUS status;
6282 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306283 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006284
6285 ENTER();
6286
6287 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6288
6289 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6290 {
6291 pAdapter = pAdapterNode->pAdapter;
6292
6293 switch(pAdapter->device_mode)
6294 {
6295 case WLAN_HDD_INFRA_STATION:
6296 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006297 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306298
6299 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6300
Jeff Johnson295189b2012-06-20 16:38:30 -07006301 hdd_init_station_mode(pAdapter);
6302 /* Open the gates for HDD to receive Wext commands */
6303 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006304 pHddCtx->scan_info.mScanPending = FALSE;
6305 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006306
6307 //Trigger the initial scan
6308 hdd_wlan_initial_scan(pAdapter);
6309
6310 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306311 if (eConnectionState_Associated == connState ||
6312 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006313 {
6314 union iwreq_data wrqu;
6315 memset(&wrqu, '\0', sizeof(wrqu));
6316 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6317 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6318 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006319 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006320
Jeff Johnson295189b2012-06-20 16:38:30 -07006321 /* indicate disconnected event to nl80211 */
6322 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6323 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006324 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306325 else if (eConnectionState_Connecting == connState)
6326 {
6327 /*
6328 * Indicate connect failure to supplicant if we were in the
6329 * process of connecting
6330 */
6331 cfg80211_connect_result(pAdapter->dev, NULL,
6332 NULL, 0, NULL, 0,
6333 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6334 GFP_KERNEL);
6335 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006336 break;
6337
6338 case WLAN_HDD_SOFTAP:
6339 /* softAP can handle SSR */
6340 break;
6341
6342 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006343 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006344 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006345 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006346 break;
6347
6348 case WLAN_HDD_MONITOR:
6349 /* monitor interface start */
6350 break;
6351 default:
6352 break;
6353 }
6354
6355 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6356 pAdapterNode = pNext;
6357 }
6358
6359 EXIT();
6360
6361 return VOS_STATUS_SUCCESS;
6362}
6363
6364VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6365{
6366 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6367 hdd_adapter_t *pAdapter;
6368 VOS_STATUS status;
6369 v_U32_t roamId;
6370
6371 ENTER();
6372
6373 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6374
6375 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6376 {
6377 pAdapter = pAdapterNode->pAdapter;
6378
6379 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6380 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6381 {
6382 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6383 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6384
6385 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6386 init_completion(&pAdapter->disconnect_comp_var);
6387 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6388 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6389
6390 wait_for_completion_interruptible_timeout(
6391 &pAdapter->disconnect_comp_var,
6392 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6393
6394 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6395 pHddCtx->isAmpAllowed = VOS_FALSE;
6396 sme_RoamConnect(pHddCtx->hHal,
6397 pAdapter->sessionId, &(pWextState->roamProfile),
6398 &roamId);
6399 }
6400
6401 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6402 pAdapterNode = pNext;
6403 }
6404
6405 EXIT();
6406
6407 return VOS_STATUS_SUCCESS;
6408}
6409
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006410void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6411{
6412 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6413 VOS_STATUS status;
6414 hdd_adapter_t *pAdapter;
6415 hdd_station_ctx_t *pHddStaCtx;
6416 hdd_ap_ctx_t *pHddApCtx;
6417 hdd_hostapd_state_t * pHostapdState;
6418 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6419 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6420 const char *p2pMode = "DEV";
6421 const char *ccMode = "Standalone";
6422 int n;
6423
6424 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6425 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6426 {
6427 pAdapter = pAdapterNode->pAdapter;
6428 switch (pAdapter->device_mode) {
6429 case WLAN_HDD_INFRA_STATION:
6430 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6431 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6432 staChannel = pHddStaCtx->conn_info.operationChannel;
6433 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6434 }
6435 break;
6436 case WLAN_HDD_P2P_CLIENT:
6437 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6438 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6439 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6440 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6441 p2pMode = "CLI";
6442 }
6443 break;
6444 case WLAN_HDD_P2P_GO:
6445 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6446 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6447 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6448 p2pChannel = pHddApCtx->operatingChannel;
6449 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6450 }
6451 p2pMode = "GO";
6452 break;
6453 case WLAN_HDD_SOFTAP:
6454 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6455 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6456 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6457 apChannel = pHddApCtx->operatingChannel;
6458 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6459 }
6460 break;
6461 default:
6462 break;
6463 }
6464 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6465 pAdapterNode = pNext;
6466 }
6467 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6468 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6469 }
6470 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6471 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6472 if (p2pChannel > 0) {
6473 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6474 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6475 }
6476 if (apChannel > 0) {
6477 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6478 apChannel, MAC_ADDR_ARRAY(apBssid));
6479 }
6480
6481 if (p2pChannel > 0 && apChannel > 0) {
6482 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6483 }
6484}
6485
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006486bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006487{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006488 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006489}
6490
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006491/* Once SSR is disabled then it cannot be set. */
6492void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006493{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006494 if (HDD_SSR_DISABLED == isSsrRequired)
6495 return;
6496
Jeff Johnson295189b2012-06-20 16:38:30 -07006497 isSsrRequired = value;
6498}
6499
6500VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6501 hdd_adapter_list_node_t** ppAdapterNode)
6502{
6503 VOS_STATUS status;
6504 spin_lock(&pHddCtx->hddAdapters.lock);
6505 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6506 (hdd_list_node_t**) ppAdapterNode );
6507 spin_unlock(&pHddCtx->hddAdapters.lock);
6508 return status;
6509}
6510
6511VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6512 hdd_adapter_list_node_t* pAdapterNode,
6513 hdd_adapter_list_node_t** pNextAdapterNode)
6514{
6515 VOS_STATUS status;
6516 spin_lock(&pHddCtx->hddAdapters.lock);
6517 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6518 (hdd_list_node_t*) pAdapterNode,
6519 (hdd_list_node_t**)pNextAdapterNode );
6520
6521 spin_unlock(&pHddCtx->hddAdapters.lock);
6522 return status;
6523}
6524
6525VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6526 hdd_adapter_list_node_t* pAdapterNode)
6527{
6528 VOS_STATUS status;
6529 spin_lock(&pHddCtx->hddAdapters.lock);
6530 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6531 &pAdapterNode->node );
6532 spin_unlock(&pHddCtx->hddAdapters.lock);
6533 return status;
6534}
6535
6536VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6537 hdd_adapter_list_node_t** ppAdapterNode)
6538{
6539 VOS_STATUS status;
6540 spin_lock(&pHddCtx->hddAdapters.lock);
6541 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6542 (hdd_list_node_t**) ppAdapterNode );
6543 spin_unlock(&pHddCtx->hddAdapters.lock);
6544 return status;
6545}
6546
6547VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6548 hdd_adapter_list_node_t* pAdapterNode)
6549{
6550 VOS_STATUS status;
6551 spin_lock(&pHddCtx->hddAdapters.lock);
6552 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6553 (hdd_list_node_t*) pAdapterNode );
6554 spin_unlock(&pHddCtx->hddAdapters.lock);
6555 return status;
6556}
6557
6558VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6559 hdd_adapter_list_node_t* pAdapterNode)
6560{
6561 VOS_STATUS status;
6562 spin_lock(&pHddCtx->hddAdapters.lock);
6563 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6564 (hdd_list_node_t*) pAdapterNode );
6565 spin_unlock(&pHddCtx->hddAdapters.lock);
6566 return status;
6567}
6568
6569hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6570 tSirMacAddr macAddr )
6571{
6572 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6573 hdd_adapter_t *pAdapter;
6574 VOS_STATUS status;
6575
6576 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6577
6578 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6579 {
6580 pAdapter = pAdapterNode->pAdapter;
6581
6582 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6583 macAddr, sizeof(tSirMacAddr) ) )
6584 {
6585 return pAdapter;
6586 }
6587 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6588 pAdapterNode = pNext;
6589 }
6590
6591 return NULL;
6592
6593}
6594
6595hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6596{
6597 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6598 hdd_adapter_t *pAdapter;
6599 VOS_STATUS status;
6600
6601 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6602
6603 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6604 {
6605 pAdapter = pAdapterNode->pAdapter;
6606
6607 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6608 IFNAMSIZ ) )
6609 {
6610 return pAdapter;
6611 }
6612 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6613 pAdapterNode = pNext;
6614 }
6615
6616 return NULL;
6617
6618}
6619
6620hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6621{
6622 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6623 hdd_adapter_t *pAdapter;
6624 VOS_STATUS status;
6625
6626 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6627
6628 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6629 {
6630 pAdapter = pAdapterNode->pAdapter;
6631
6632 if( pAdapter && (mode == pAdapter->device_mode) )
6633 {
6634 return pAdapter;
6635 }
6636 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6637 pAdapterNode = pNext;
6638 }
6639
6640 return NULL;
6641
6642}
6643
6644//Remove this function later
6645hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6646{
6647 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6648 hdd_adapter_t *pAdapter;
6649 VOS_STATUS status;
6650
6651 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6652
6653 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6654 {
6655 pAdapter = pAdapterNode->pAdapter;
6656
6657 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6658 {
6659 return pAdapter;
6660 }
6661
6662 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6663 pAdapterNode = pNext;
6664 }
6665
6666 return NULL;
6667
6668}
6669
Jeff Johnson295189b2012-06-20 16:38:30 -07006670/**---------------------------------------------------------------------------
6671
6672 \brief hdd_set_monitor_tx_adapter() -
6673
6674 This API initializes the adapter to be used while transmitting on monitor
6675 adapter.
6676
6677 \param - pHddCtx - Pointer to the HDD context.
6678 pAdapter - Adapter that will used for TX. This can be NULL.
6679 \return - None.
6680 --------------------------------------------------------------------------*/
6681void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6682{
6683 hdd_adapter_t *pMonAdapter;
6684
6685 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6686
6687 if( NULL != pMonAdapter )
6688 {
6689 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6690 }
6691}
Jeff Johnson295189b2012-06-20 16:38:30 -07006692/**---------------------------------------------------------------------------
6693
6694 \brief hdd_select_queue() -
6695
6696 This API returns the operating channel of the requested device mode
6697
6698 \param - pHddCtx - Pointer to the HDD context.
6699 - mode - Device mode for which operating channel is required
6700 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6701 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6702 \return - channel number. "0" id the requested device is not found OR it is not connected.
6703 --------------------------------------------------------------------------*/
6704v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6705{
6706 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6707 VOS_STATUS status;
6708 hdd_adapter_t *pAdapter;
6709 v_U8_t operatingChannel = 0;
6710
6711 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6712
6713 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6714 {
6715 pAdapter = pAdapterNode->pAdapter;
6716
6717 if( mode == pAdapter->device_mode )
6718 {
6719 switch(pAdapter->device_mode)
6720 {
6721 case WLAN_HDD_INFRA_STATION:
6722 case WLAN_HDD_P2P_CLIENT:
6723 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6724 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6725 break;
6726 case WLAN_HDD_SOFTAP:
6727 case WLAN_HDD_P2P_GO:
6728 /*softap connection info */
6729 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6730 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6731 break;
6732 default:
6733 break;
6734 }
6735
6736 break; //Found the device of interest. break the loop
6737 }
6738
6739 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6740 pAdapterNode = pNext;
6741 }
6742 return operatingChannel;
6743}
6744
6745#ifdef WLAN_FEATURE_PACKET_FILTERING
6746/**---------------------------------------------------------------------------
6747
6748 \brief hdd_set_multicast_list() -
6749
6750 This used to set the multicast address list.
6751
6752 \param - dev - Pointer to the WLAN device.
6753 - skb - Pointer to OS packet (sk_buff).
6754 \return - success/fail
6755
6756 --------------------------------------------------------------------------*/
6757static void hdd_set_multicast_list(struct net_device *dev)
6758{
6759 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006760 int mc_count;
6761 int i = 0;
6762 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306763
6764 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 {
6766 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306767 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006768 return;
6769 }
6770
6771 if (dev->flags & IFF_ALLMULTI)
6772 {
6773 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006774 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306775 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 }
6777 else
6778 {
6779 mc_count = netdev_mc_count(dev);
6780 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006781 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006782 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6783 {
6784 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006785 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306786 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006787 return;
6788 }
6789
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306790 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006791
6792 netdev_for_each_mc_addr(ha, dev) {
6793 if (i == mc_count)
6794 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306795 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6796 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006797 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006798 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306799 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006800 i++;
6801 }
6802 }
6803 return;
6804}
6805#endif
6806
6807/**---------------------------------------------------------------------------
6808
6809 \brief hdd_select_queue() -
6810
6811 This function is registered with the Linux OS for network
6812 core to decide which queue to use first.
6813
6814 \param - dev - Pointer to the WLAN device.
6815 - skb - Pointer to OS packet (sk_buff).
6816 \return - ac, Queue Index/access category corresponding to UP in IP header
6817
6818 --------------------------------------------------------------------------*/
6819v_U16_t hdd_select_queue(struct net_device *dev,
6820 struct sk_buff *skb)
6821{
6822 return hdd_wmm_select_queue(dev, skb);
6823}
6824
6825
6826/**---------------------------------------------------------------------------
6827
6828 \brief hdd_wlan_initial_scan() -
6829
6830 This function triggers the initial scan
6831
6832 \param - pAdapter - Pointer to the HDD adapter.
6833
6834 --------------------------------------------------------------------------*/
6835void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6836{
6837 tCsrScanRequest scanReq;
6838 tCsrChannelInfo channelInfo;
6839 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006840 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006841 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6842
6843 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6844 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6845 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6846
6847 if(sme_Is11dSupported(pHddCtx->hHal))
6848 {
6849 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6850 if ( HAL_STATUS_SUCCESS( halStatus ) )
6851 {
6852 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6853 if( !scanReq.ChannelInfo.ChannelList )
6854 {
6855 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6856 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006857 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006858 return;
6859 }
6860 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6861 channelInfo.numOfChannels);
6862 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6863 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006864 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 }
6866
6867 scanReq.scanType = eSIR_PASSIVE_SCAN;
6868 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6869 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6870 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6871 }
6872 else
6873 {
6874 scanReq.scanType = eSIR_ACTIVE_SCAN;
6875 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6876 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6877 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6878 }
6879
6880 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6881 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6882 {
6883 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6884 __func__, halStatus );
6885 }
6886
6887 if(sme_Is11dSupported(pHddCtx->hHal))
6888 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6889}
6890
Jeff Johnson295189b2012-06-20 16:38:30 -07006891/**---------------------------------------------------------------------------
6892
6893 \brief hdd_full_power_callback() - HDD full power callback function
6894
6895 This is the function invoked by SME to inform the result of a full power
6896 request issued by HDD
6897
6898 \param - callbackcontext - Pointer to cookie
6899 \param - status - result of request
6900
6901 \return - None
6902
6903 --------------------------------------------------------------------------*/
6904static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6905{
Jeff Johnson72a40512013-12-19 10:14:15 -08006906 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07006907
6908 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306909 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006910
6911 if (NULL == callbackContext)
6912 {
6913 hddLog(VOS_TRACE_LEVEL_ERROR,
6914 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006915 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006916 return;
6917 }
6918
Jeff Johnson72a40512013-12-19 10:14:15 -08006919 /* there is a race condition that exists between this callback
6920 function and the caller since the caller could time out either
6921 before or while this code is executing. we use a spinlock to
6922 serialize these actions */
6923 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006924
6925 if (POWER_CONTEXT_MAGIC != pContext->magic)
6926 {
6927 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006928 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006929 hddLog(VOS_TRACE_LEVEL_WARN,
6930 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006931 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006932 return;
6933 }
6934
Jeff Johnson72a40512013-12-19 10:14:15 -08006935 /* context is valid so caller is still waiting */
6936
6937 /* paranoia: invalidate the magic */
6938 pContext->magic = 0;
6939
6940 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006942
6943 /* serialization is complete */
6944 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07006945}
6946
6947/**---------------------------------------------------------------------------
6948
6949 \brief hdd_wlan_exit() - HDD WLAN exit function
6950
6951 This is the driver exit point (invoked during rmmod)
6952
6953 \param - pHddCtx - Pointer to the HDD Context
6954
6955 \return - None
6956
6957 --------------------------------------------------------------------------*/
6958void hdd_wlan_exit(hdd_context_t *pHddCtx)
6959{
6960 eHalStatus halStatus;
6961 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6962 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306963 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006964 hdd_adapter_t* pAdapter;
Jeff Johnson72a40512013-12-19 10:14:15 -08006965 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 long lrc;
6967
6968 ENTER();
6969
Jeff Johnson88ba7742013-02-27 14:36:02 -08006970 if (VOS_FTM_MODE != hdd_get_conparam())
6971 {
6972 // Unloading, restart logic is no more required.
6973 wlan_hdd_restart_deinit(pHddCtx);
6974 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006975
Jeff Johnson295189b2012-06-20 16:38:30 -07006976 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006977 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006978 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 {
6980 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6981 WLAN_HDD_INFRA_STATION);
6982 if (pAdapter == NULL)
6983 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6984
6985 if (pAdapter != NULL)
6986 {
6987 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6988 hdd_UnregisterWext(pAdapter->dev);
6989 }
6990 }
6991 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006992
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006994 {
6995 wlan_hdd_ftm_close(pHddCtx);
6996 goto free_hdd_ctx;
6997 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 //Stop the Interface TX queue.
6999 //netif_tx_disable(pWlanDev);
7000 //netif_carrier_off(pWlanDev);
7001
Jeff Johnson295189b2012-06-20 16:38:30 -07007002 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7003 {
7004 pAdapter = hdd_get_adapter(pHddCtx,
7005 WLAN_HDD_SOFTAP);
7006 }
7007 else
7008 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007009 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007010 {
7011 pAdapter = hdd_get_adapter(pHddCtx,
7012 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007013 if (pAdapter == NULL)
7014 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007015 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007016 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 /* DeRegister with platform driver as client for Suspend/Resume */
7018 vosStatus = hddDeregisterPmOps(pHddCtx);
7019 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7020 {
7021 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7022 VOS_ASSERT(0);
7023 }
7024
7025 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7026 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7027 {
7028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7029 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007030
7031 // Cancel any outstanding scan requests. We are about to close all
7032 // of our adapters, but an adapter structure is what SME passes back
7033 // to our callback function. Hence if there are any outstanding scan
7034 // requests then there is a race condition between when the adapter
7035 // is closed and when the callback is invoked. We try to resolve that
7036 // race condition here by canceling any outstanding scans before we
7037 // close the adapters.
7038 // Note that the scans may be cancelled in an asynchronous manner, so
7039 // ideally there needs to be some kind of synchronization. Rather than
7040 // introduce a new synchronization here, we will utilize the fact that
7041 // we are about to Request Full Power, and since that is synchronized,
7042 // the expectation is that by the time Request Full Power has completed,
7043 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007044 if (NULL != pAdapter)
7045 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7046 else
7047 hddLog(VOS_TRACE_LEVEL_ERROR,
7048 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007049
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007050 //Stop the traffic monitor timer
7051 if ( VOS_TIMER_STATE_RUNNING ==
7052 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7053 {
7054 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7055 }
7056
7057 // Destroy the traffic monitor timer
7058 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7059 &pHddCtx->tx_rx_trafficTmr)))
7060 {
7061 hddLog(VOS_TRACE_LEVEL_ERROR,
7062 "%s: Cannot deallocate Traffic monitor timer", __func__);
7063 }
7064
Jeff Johnson295189b2012-06-20 16:38:30 -07007065 //Disable IMPS/BMPS as we do not want the device to enter any power
7066 //save mode during shutdown
7067 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7068 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7069 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7070
7071 //Ensure that device is in full power as we will touch H/W during vos_Stop
7072 init_completion(&powerContext.completion);
7073 powerContext.magic = POWER_CONTEXT_MAGIC;
7074
7075 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7076 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7077
7078 if (eHAL_STATUS_SUCCESS != halStatus)
7079 {
7080 if (eHAL_STATUS_PMC_PENDING == halStatus)
7081 {
7082 /* request was sent -- wait for the response */
7083 lrc = wait_for_completion_interruptible_timeout(
7084 &powerContext.completion,
7085 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 if (lrc <= 0)
7087 {
7088 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007089 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 }
7091 }
7092 else
7093 {
7094 hddLog(VOS_TRACE_LEVEL_ERROR,
7095 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007096 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007097 /* continue -- need to clean up as much as possible */
7098 }
7099 }
7100
Jeff Johnson72a40512013-12-19 10:14:15 -08007101 /* either we never sent a request, we sent a request and received a
7102 response or we sent a request and timed out. if we never sent a
7103 request or if we sent a request and got a response, we want to
7104 clear the magic out of paranoia. if we timed out there is a
7105 race condition such that the callback function could be
7106 executing at the same time we are. of primary concern is if the
7107 callback function had already verified the "magic" but had not
7108 yet set the completion variable when a timeout occurred. we
7109 serialize these activities by invalidating the magic while
7110 holding a shared spinlock which will cause us to block if the
7111 callback is currently executing */
7112 spin_lock(&hdd_context_lock);
7113 powerContext.magic = 0;
7114 spin_unlock(&hdd_context_lock);
7115
Yue Ma0d4891e2013-08-06 17:01:45 -07007116 hdd_debugfs_exit(pHddCtx);
7117
Jeff Johnson295189b2012-06-20 16:38:30 -07007118 // Unregister the Net Device Notifier
7119 unregister_netdevice_notifier(&hdd_netdev_notifier);
7120
Jeff Johnson295189b2012-06-20 16:38:30 -07007121 hdd_stop_all_adapters( pHddCtx );
7122
Jeff Johnson295189b2012-06-20 16:38:30 -07007123#ifdef WLAN_BTAMP_FEATURE
7124 vosStatus = WLANBAP_Stop(pVosContext);
7125 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7126 {
7127 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7128 "%s: Failed to stop BAP",__func__);
7129 }
7130#endif //WLAN_BTAMP_FEATURE
7131
7132 //Stop all the modules
7133 vosStatus = vos_stop( pVosContext );
7134 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7135 {
7136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7137 "%s: Failed to stop VOSS",__func__);
7138 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7139 }
7140
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 //Assert Deep sleep signal now to put Libra HW in lowest power state
7142 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7143 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7144
7145 //Vote off any PMIC voltage supplies
7146 vos_chipPowerDown(NULL, NULL, NULL);
7147
7148 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7149
Leo Chang59cdc7e2013-07-10 10:08:21 -07007150
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007152 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007153
7154 //Close the scheduler before calling vos_close to make sure no thread is
7155 // scheduled after the each module close is called i.e after all the data
7156 // structures are freed.
7157 vosStatus = vos_sched_close( pVosContext );
7158 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7159 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7160 "%s: Failed to close VOSS Scheduler",__func__);
7161 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7162 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007163#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007164#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7165 /* Destroy the wake lock */
7166 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7167#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007168 /* Destroy the wake lock */
7169 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007171
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307172#ifdef CONFIG_ENABLE_LINUX_REG
7173 vosStatus = vos_nv_close();
7174 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7175 {
7176 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7177 "%s: Failed to close NV", __func__);
7178 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7179 }
7180#endif
7181
Jeff Johnson295189b2012-06-20 16:38:30 -07007182 //Close VOSS
7183 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7184 vos_close(pVosContext);
7185
Jeff Johnson295189b2012-06-20 16:38:30 -07007186 //Close Watchdog
7187 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7188 vos_watchdog_close(pVosContext);
7189
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307190 //Clean up HDD Nlink Service
7191 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007192#ifdef WLAN_KD_READY_NOTIFIER
7193 nl_srv_exit(pHddCtx->ptt_pid);
7194#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307195 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007196#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307197
Jeff Johnson295189b2012-06-20 16:38:30 -07007198 /* Cancel the vote for XO Core ON.
7199 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7200 * exited at this point
7201 */
7202 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007203 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007204 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7205 {
7206 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7207 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007208 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 }
7210
7211 hdd_close_all_adapters( pHddCtx );
7212
7213
7214 //Free up dynamically allocated members inside HDD Adapter
7215 kfree(pHddCtx->cfg_ini);
7216 pHddCtx->cfg_ini= NULL;
7217
7218 /* free the power on lock from platform driver */
7219 if (free_riva_power_on_lock("wlan"))
7220 {
7221 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7222 __func__);
7223 }
7224
Jeff Johnson88ba7742013-02-27 14:36:02 -08007225free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007226 /* FTM mode, WIPHY did not registered
7227 If un-register here, system crash will happen */
7228 if (VOS_FTM_MODE != hdd_get_conparam())
7229 {
7230 wiphy_unregister(wiphy) ;
7231 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007232 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007233 if (hdd_is_ssr_required())
7234 {
7235 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007236 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 msleep(5000);
7238 }
7239 hdd_set_ssr_required (VOS_FALSE);
7240}
7241
7242
7243/**---------------------------------------------------------------------------
7244
7245 \brief hdd_update_config_from_nv() - Function to update the contents of
7246 the running configuration with parameters taken from NV storage
7247
7248 \param - pHddCtx - Pointer to the HDD global context
7249
7250 \return - VOS_STATUS_SUCCESS if successful
7251
7252 --------------------------------------------------------------------------*/
7253static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7254{
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 v_BOOL_t itemIsValid = VOS_FALSE;
7256 VOS_STATUS status;
7257 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7258 v_U8_t macLoop;
7259
7260 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7261 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7262 if(status != VOS_STATUS_SUCCESS)
7263 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007264 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007265 return VOS_STATUS_E_FAILURE;
7266 }
7267
7268 if (itemIsValid == VOS_TRUE)
7269 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007270 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007271 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7272 VOS_MAX_CONCURRENCY_PERSONA);
7273 if(status != VOS_STATUS_SUCCESS)
7274 {
7275 /* Get MAC from NV fail, not update CFG info
7276 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007277 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007278 return VOS_STATUS_E_FAILURE;
7279 }
7280
7281 /* If first MAC is not valid, treat all others are not valid
7282 * Then all MACs will be got from ini file */
7283 if(vos_is_macaddr_zero(&macFromNV[0]))
7284 {
7285 /* MAC address in NV file is not configured yet */
7286 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7287 return VOS_STATUS_E_INVAL;
7288 }
7289
7290 /* Get MAC address from NV, update CFG info */
7291 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7292 {
7293 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7294 {
7295 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7296 /* This MAC is not valid, skip it
7297 * This MAC will be got from ini file */
7298 }
7299 else
7300 {
7301 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7302 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7303 VOS_MAC_ADDR_SIZE);
7304 }
7305 }
7306 }
7307 else
7308 {
7309 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7310 return VOS_STATUS_E_FAILURE;
7311 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007312
Jeff Johnson295189b2012-06-20 16:38:30 -07007313
7314 return VOS_STATUS_SUCCESS;
7315}
7316
7317/**---------------------------------------------------------------------------
7318
7319 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7320
7321 \param - pAdapter - Pointer to the HDD
7322
7323 \return - None
7324
7325 --------------------------------------------------------------------------*/
7326VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7327{
7328 eHalStatus halStatus;
7329 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307330 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007331
Jeff Johnson295189b2012-06-20 16:38:30 -07007332
7333 // Send ready indication to the HDD. This will kick off the MAC
7334 // into a 'running' state and should kick off an initial scan.
7335 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7336 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7337 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307338 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007339 "code %08d [x%08x]",__func__, halStatus, halStatus );
7340 return VOS_STATUS_E_FAILURE;
7341 }
7342
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307343 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007344 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7345 // And RIVA will crash
7346 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7347 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307348 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7349 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7350
7351
Jeff Johnson295189b2012-06-20 16:38:30 -07007352 return VOS_STATUS_SUCCESS;
7353}
7354
Jeff Johnson295189b2012-06-20 16:38:30 -07007355/* wake lock APIs for HDD */
7356void hdd_prevent_suspend(void)
7357{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007358#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007359 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007360#else
7361 wcnss_prevent_suspend();
7362#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007363}
7364
7365void hdd_allow_suspend(void)
7366{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007367#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007368 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007369#else
7370 wcnss_allow_suspend();
7371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007372}
7373
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007374void hdd_allow_suspend_timeout(v_U32_t timeout)
7375{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007376#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007377 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007378#else
7379 /* Do nothing as there is no API in wcnss for timeout*/
7380#endif
7381}
7382
Jeff Johnson295189b2012-06-20 16:38:30 -07007383/**---------------------------------------------------------------------------
7384
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007385 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7386 information between Host and Riva
7387
7388 This function gets reported version of FW
7389 It also finds the version of Riva headers used to compile the host
7390 It compares the above two and prints a warning if they are different
7391 It gets the SW and HW version string
7392 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7393 indicating the features they support through a bitmap
7394
7395 \param - pHddCtx - Pointer to HDD context
7396
7397 \return - void
7398
7399 --------------------------------------------------------------------------*/
7400
7401void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7402{
7403
7404 tSirVersionType versionCompiled;
7405 tSirVersionType versionReported;
7406 tSirVersionString versionString;
7407 tANI_U8 fwFeatCapsMsgSupported = 0;
7408 VOS_STATUS vstatus;
7409
7410 /* retrieve and display WCNSS version information */
7411 do {
7412
7413 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7414 &versionCompiled);
7415 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7416 {
7417 hddLog(VOS_TRACE_LEVEL_FATAL,
7418 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007419 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007420 break;
7421 }
7422
7423 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7424 &versionReported);
7425 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7426 {
7427 hddLog(VOS_TRACE_LEVEL_FATAL,
7428 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007429 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007430 break;
7431 }
7432
7433 if ((versionCompiled.major != versionReported.major) ||
7434 (versionCompiled.minor != versionReported.minor) ||
7435 (versionCompiled.version != versionReported.version) ||
7436 (versionCompiled.revision != versionReported.revision))
7437 {
7438 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7439 "Host expected %u.%u.%u.%u\n",
7440 WLAN_MODULE_NAME,
7441 (int)versionReported.major,
7442 (int)versionReported.minor,
7443 (int)versionReported.version,
7444 (int)versionReported.revision,
7445 (int)versionCompiled.major,
7446 (int)versionCompiled.minor,
7447 (int)versionCompiled.version,
7448 (int)versionCompiled.revision);
7449 }
7450 else
7451 {
7452 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7453 WLAN_MODULE_NAME,
7454 (int)versionReported.major,
7455 (int)versionReported.minor,
7456 (int)versionReported.version,
7457 (int)versionReported.revision);
7458 }
7459
7460 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7461 versionString,
7462 sizeof(versionString));
7463 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7464 {
7465 hddLog(VOS_TRACE_LEVEL_FATAL,
7466 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007467 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007468 break;
7469 }
7470
7471 pr_info("%s: WCNSS software version %s\n",
7472 WLAN_MODULE_NAME, versionString);
7473
7474 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7475 versionString,
7476 sizeof(versionString));
7477 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7478 {
7479 hddLog(VOS_TRACE_LEVEL_FATAL,
7480 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007481 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007482 break;
7483 }
7484
7485 pr_info("%s: WCNSS hardware version %s\n",
7486 WLAN_MODULE_NAME, versionString);
7487
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007488 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7489 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007490 send the message only if it the riva is 1.1
7491 minor numbers for different riva branches:
7492 0 -> (1.0)Mainline Build
7493 1 -> (1.1)Mainline Build
7494 2->(1.04) Stability Build
7495 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007496 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007497 ((versionReported.minor>=1) && (versionReported.version>=1)))
7498 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7499 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007500
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007501 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007502 {
7503#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7504 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7505 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7506#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007507 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7508 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7509 {
7510 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7511 }
7512
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007513 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007514 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007515
7516 } while (0);
7517
7518}
7519
7520/**---------------------------------------------------------------------------
7521
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307522 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7523
7524 \param - pHddCtx - Pointer to the hdd context
7525
7526 \return - true if hardware supports 5GHz
7527
7528 --------------------------------------------------------------------------*/
7529static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7530{
7531 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7532 * then hardware support 5Ghz.
7533 */
7534 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7535 {
7536 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7537 return true;
7538 }
7539 else
7540 {
7541 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7542 __func__);
7543 return false;
7544 }
7545}
7546
7547
7548/**---------------------------------------------------------------------------
7549
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 \brief hdd_wlan_startup() - HDD init function
7551
7552 This is the driver startup code executed once a WLAN device has been detected
7553
7554 \param - dev - Pointer to the underlying device
7555
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007556 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007557
7558 --------------------------------------------------------------------------*/
7559
7560int hdd_wlan_startup(struct device *dev )
7561{
7562 VOS_STATUS status;
7563 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007564 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 hdd_context_t *pHddCtx = NULL;
7566 v_CONTEXT_t pVosContext= NULL;
7567#ifdef WLAN_BTAMP_FEATURE
7568 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7569 WLANBAP_ConfigType btAmpConfig;
7570 hdd_config_t *pConfig;
7571#endif
7572 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007573 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007574
7575 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007576 /*
7577 * cfg80211: wiphy allocation
7578 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307579 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007580
7581 if(wiphy == NULL)
7582 {
7583 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007584 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007585 }
7586
7587 pHddCtx = wiphy_priv(wiphy);
7588
Jeff Johnson295189b2012-06-20 16:38:30 -07007589 //Initialize the adapter context to zeros.
7590 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7591
Jeff Johnson295189b2012-06-20 16:38:30 -07007592 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007593 hdd_prevent_suspend();
7594 pHddCtx->isLoadUnloadInProgress = TRUE;
7595
7596 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7597
7598 /*Get vos context here bcoz vos_open requires it*/
7599 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7600
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007601 if(pVosContext == NULL)
7602 {
7603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7604 goto err_free_hdd_context;
7605 }
7606
Jeff Johnson295189b2012-06-20 16:38:30 -07007607 //Save the Global VOSS context in adapter context for future.
7608 pHddCtx->pvosContext = pVosContext;
7609
7610 //Save the adapter context in global context for future.
7611 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7612
Jeff Johnson295189b2012-06-20 16:38:30 -07007613 pHddCtx->parent_dev = dev;
7614
7615 init_completion(&pHddCtx->full_pwr_comp_var);
7616 init_completion(&pHddCtx->standby_comp_var);
7617 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007618 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007619 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307620 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007621
7622#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007623 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007624#else
7625 init_completion(&pHddCtx->driver_crda_req);
7626#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007627
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307628 spin_lock_init(&pHddCtx->schedScan_lock);
7629
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7631
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307632#ifdef FEATURE_WLAN_TDLS
7633 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7634 * invoked by other instances also) to protect the concurrent
7635 * access for the Adapters by TDLS module.
7636 */
7637 mutex_init(&pHddCtx->tdls_lock);
7638#endif
7639
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307640 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007641 // Load all config first as TL config is needed during vos_open
7642 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7643 if(pHddCtx->cfg_ini == NULL)
7644 {
7645 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7646 goto err_free_hdd_context;
7647 }
7648
7649 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7650
7651 // Read and parse the qcom_cfg.ini file
7652 status = hdd_parse_config_ini( pHddCtx );
7653 if ( VOS_STATUS_SUCCESS != status )
7654 {
7655 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7656 __func__, WLAN_INI_FILE);
7657 goto err_config;
7658 }
Arif Hussaind5218912013-12-05 01:10:55 -08007659#ifdef MEMORY_DEBUG
7660 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7661 vos_mem_init();
7662
7663 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7664 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7665#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007666
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307667 /* INI has been read, initialise the configuredMcastBcastFilter with
7668 * INI value as this will serve as the default value
7669 */
7670 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7671 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7672 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307673
7674 if (false == hdd_is_5g_supported(pHddCtx))
7675 {
7676 //5Ghz is not supported.
7677 if (1 != pHddCtx->cfg_ini->nBandCapability)
7678 {
7679 hddLog(VOS_TRACE_LEVEL_INFO,
7680 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7681 pHddCtx->cfg_ini->nBandCapability = 1;
7682 }
7683 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307684
7685 /* If SNR Monitoring is enabled, FW has to parse all beacons
7686 * for calcaluting and storing the average SNR, so set Nth beacon
7687 * filter to 1 to enable FW to parse all the beaocons
7688 */
7689 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7690 {
7691 /* The log level is deliberately set to WARN as overriding
7692 * nthBeaconFilter to 1 will increase power cosumption and this
7693 * might just prove helpful to detect the power issue.
7694 */
7695 hddLog(VOS_TRACE_LEVEL_WARN,
7696 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7697 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7698 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307700 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307702 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007703 {
7704 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307705 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7706 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007708
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007709 // Update VOS trace levels based upon the cfg.ini
7710 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7711 pHddCtx->cfg_ini->vosTraceEnableBAP);
7712 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7713 pHddCtx->cfg_ini->vosTraceEnableTL);
7714 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7715 pHddCtx->cfg_ini->vosTraceEnableWDI);
7716 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7717 pHddCtx->cfg_ini->vosTraceEnableHDD);
7718 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7719 pHddCtx->cfg_ini->vosTraceEnableSME);
7720 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7721 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307722 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7723 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007724 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7725 pHddCtx->cfg_ini->vosTraceEnableWDA);
7726 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7727 pHddCtx->cfg_ini->vosTraceEnableSYS);
7728 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7729 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007730 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7731 pHddCtx->cfg_ini->vosTraceEnableSAP);
7732 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7733 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007734
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 // Update WDI trace levels based upon the cfg.ini
7736 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7737 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7738 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7739 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7740 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7741 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7742 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7743 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007744
Jeff Johnson88ba7742013-02-27 14:36:02 -08007745 if (VOS_FTM_MODE == hdd_get_conparam())
7746 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007747 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7748 {
7749 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7750 goto err_free_hdd_context;
7751 }
7752 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7753 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007754 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007755
Jeff Johnson88ba7742013-02-27 14:36:02 -08007756 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007757 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7758 {
7759 status = vos_watchdog_open(pVosContext,
7760 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7761
7762 if(!VOS_IS_STATUS_SUCCESS( status ))
7763 {
7764 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307765 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007766 }
7767 }
7768
7769 pHddCtx->isLogpInProgress = FALSE;
7770 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7771
Jeff Johnson295189b2012-06-20 16:38:30 -07007772 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7773 if(!VOS_IS_STATUS_SUCCESS(status))
7774 {
7775 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007777 }
7778
Amar Singhala49cbc52013-10-08 18:37:44 -07007779#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007780 /* initialize the NV module. This is required so that
7781 we can initialize the channel information in wiphy
7782 from the NV.bin data. The channel information in
7783 wiphy needs to be initialized before wiphy registration */
7784
7785 status = vos_nv_open();
7786 if (!VOS_IS_STATUS_SUCCESS(status))
7787 {
7788 /* NV module cannot be initialized */
7789 hddLog( VOS_TRACE_LEVEL_FATAL,
7790 "%s: vos_nv_open failed", __func__);
7791 goto err_clkvote;
7792 }
7793
7794 status = vos_init_wiphy_from_nv_bin();
7795 if (!VOS_IS_STATUS_SUCCESS(status))
7796 {
7797 /* NV module cannot be initialized */
7798 hddLog( VOS_TRACE_LEVEL_FATAL,
7799 "%s: vos_init_wiphy failed", __func__);
7800 goto err_vos_nv_close;
7801 }
7802
Amar Singhala49cbc52013-10-08 18:37:44 -07007803 /* registration of wiphy dev with cfg80211 */
7804 if (0 > wlan_hdd_cfg80211_register(wiphy))
7805 {
7806 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007807 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007808 }
7809#endif
7810
Jeff Johnson295189b2012-06-20 16:38:30 -07007811 status = vos_open( &pVosContext, 0);
7812 if ( !VOS_IS_STATUS_SUCCESS( status ))
7813 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007815 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007816 }
7817
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7819
7820 if ( NULL == pHddCtx->hHal )
7821 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007822 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007823 goto err_vosclose;
7824 }
7825
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007826 status = vos_preStart( pHddCtx->pvosContext );
7827 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7828 {
7829 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7830 goto err_vosclose;
7831 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007832
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007833 /* Note that the vos_preStart() sequence triggers the cfg download.
7834 The cfg download must occur before we update the SME config
7835 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 status = hdd_set_sme_config( pHddCtx );
7837
7838 if ( VOS_STATUS_SUCCESS != status )
7839 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007840 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7841 goto err_vosclose;
7842 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007843
7844 //Initialize the WMM module
7845 status = hdd_wmm_init(pHddCtx);
7846 if (!VOS_IS_STATUS_SUCCESS(status))
7847 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007849 goto err_vosclose;
7850 }
7851
Jeff Johnson295189b2012-06-20 16:38:30 -07007852 /* In the integrated architecture we update the configuration from
7853 the INI file and from NV before vOSS has been started so that
7854 the final contents are available to send down to the cCPU */
7855
Arif Hussain66559122013-11-21 10:11:40 -08007856 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7857 {
7858 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7859 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7860 __func__, enable_dfs_chan_scan);
7861 }
7862 if (0 == enable_11d || 1 == enable_11d)
7863 {
7864 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7865 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7866 __func__, enable_11d);
7867 }
7868
Jeff Johnson295189b2012-06-20 16:38:30 -07007869 // Apply the cfg.ini to cfg.dat
7870 if (FALSE == hdd_update_config_dat(pHddCtx))
7871 {
7872 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7873 goto err_vosclose;
7874 }
7875
7876 // Apply the NV to cfg.dat
7877 /* Prima Update MAC address only at here */
7878 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7879 {
7880#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7881 /* There was not a valid set of MAC Addresses in NV. See if the
7882 default addresses were modified by the cfg.ini settings. If so,
7883 we'll use them, but if not, we'll autogenerate a set of MAC
7884 addresses based upon the device serial number */
7885
7886 static const v_MACADDR_t default_address =
7887 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7888 unsigned int serialno;
7889 int i;
7890
7891 serialno = wcnss_get_serial_number();
7892 if ((0 != serialno) &&
7893 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7894 sizeof(default_address))))
7895 {
7896 /* cfg.ini has the default address, invoke autogen logic */
7897
7898 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7899 bytes of the serial number that can be used to generate
7900 the other 3 bytes of the MAC address. Mask off all but
7901 the lower 3 bytes (this will also make sure we don't
7902 overflow in the next step) */
7903 serialno &= 0x00FFFFFF;
7904
7905 /* we need a unique address for each session */
7906 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7907
7908 /* autogen all addresses */
7909 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7910 {
7911 /* start with the entire default address */
7912 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7913 /* then replace the lower 3 bytes */
7914 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7915 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7916 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7917
7918 serialno++;
7919 }
7920
7921 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7922 MAC_ADDRESS_STR,
7923 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7924 }
7925 else
7926#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7927 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007928 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007929 "%s: Invalid MAC address in NV, using MAC from ini file "
7930 MAC_ADDRESS_STR, __func__,
7931 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7932 }
7933 }
7934 {
7935 eHalStatus halStatus;
7936 // Set the MAC Address
7937 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7938 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7939 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7940 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7941
7942 if (!HAL_STATUS_SUCCESS( halStatus ))
7943 {
7944 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7945 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007946 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007947 }
7948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007949
7950 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7951 Note: Firmware image will be read and downloaded inside vos_start API */
7952 status = vos_start( pHddCtx->pvosContext );
7953 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7954 {
7955 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7956 goto err_vosclose;
7957 }
7958
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007959 /* Exchange capability info between Host and FW and also get versioning info from FW */
7960 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007961
7962 status = hdd_post_voss_start_config( pHddCtx );
7963 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7964 {
7965 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7966 __func__);
7967 goto err_vosstop;
7968 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007969
7970#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307971 wlan_hdd_cfg80211_update_reg_info( wiphy );
7972
7973 /* registration of wiphy dev with cfg80211 */
7974 if (0 > wlan_hdd_cfg80211_register(wiphy))
7975 {
7976 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7977 goto err_vosstop;
7978 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007979#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007980
Jeff Johnson295189b2012-06-20 16:38:30 -07007981 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7982 {
7983 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7984 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7985 }
7986 else
7987 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007988 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7989 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7990 if (pAdapter != NULL)
7991 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307992 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007993 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307994 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7995 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7996 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007997
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307998 /* Generate the P2P Device Address. This consists of the device's
7999 * primary MAC address with the locally administered bit set.
8000 */
8001 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008002 }
8003 else
8004 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308005 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8006 if (p2p_dev_addr != NULL)
8007 {
8008 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8009 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8010 }
8011 else
8012 {
8013 hddLog(VOS_TRACE_LEVEL_FATAL,
8014 "%s: Failed to allocate mac_address for p2p_device",
8015 __func__);
8016 goto err_close_adapter;
8017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008018 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008019
8020 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8021 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8022 if ( NULL == pP2pAdapter )
8023 {
8024 hddLog(VOS_TRACE_LEVEL_FATAL,
8025 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008026 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008027 goto err_close_adapter;
8028 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008029 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008030 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008031
8032 if( pAdapter == NULL )
8033 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008034 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8035 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008037
Arif Hussain66559122013-11-21 10:11:40 -08008038 if (country_code)
8039 {
8040 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008041 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008042 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8043#ifndef CONFIG_ENABLE_LINUX_REG
8044 hdd_checkandupdate_phymode(pAdapter, country_code);
8045#endif
8046 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8047 country_code,
8048 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308049 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008050 if (eHAL_STATUS_SUCCESS == ret)
8051 {
Arif Hussaincb607082013-12-20 11:57:42 -08008052 ret = wait_for_completion_interruptible_timeout(
8053 &pAdapter->change_country_code,
8054 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8055
8056 if (0 >= ret)
8057 {
8058 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8059 "%s: SME while setting country code timed out", __func__);
8060 }
Arif Hussain66559122013-11-21 10:11:40 -08008061 }
8062 else
8063 {
Arif Hussaincb607082013-12-20 11:57:42 -08008064 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8065 "%s: SME Change Country code from module param fail ret=%d",
8066 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008067 }
8068 }
8069
Jeff Johnson295189b2012-06-20 16:38:30 -07008070#ifdef WLAN_BTAMP_FEATURE
8071 vStatus = WLANBAP_Open(pVosContext);
8072 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8073 {
8074 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8075 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008076 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008077 }
8078
8079 vStatus = BSL_Init(pVosContext);
8080 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8081 {
8082 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8083 "%s: Failed to Init BSL",__func__);
8084 goto err_bap_close;
8085 }
8086 vStatus = WLANBAP_Start(pVosContext);
8087 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8088 {
8089 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8090 "%s: Failed to start TL",__func__);
8091 goto err_bap_close;
8092 }
8093
8094 pConfig = pHddCtx->cfg_ini;
8095 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8096 status = WLANBAP_SetConfig(&btAmpConfig);
8097
8098#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008099
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008100#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8101 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8102 {
8103 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8104 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8105 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8106 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8107 }
8108#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008109#ifdef FEATURE_WLAN_SCAN_PNO
8110 /*SME must send channel update configuration to RIVA*/
8111 sme_UpdateChannelConfig(pHddCtx->hHal);
8112#endif
8113
Jeff Johnson295189b2012-06-20 16:38:30 -07008114 /* Register with platform driver as client for Suspend/Resume */
8115 status = hddRegisterPmOps(pHddCtx);
8116 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8117 {
8118 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8119#ifdef WLAN_BTAMP_FEATURE
8120 goto err_bap_stop;
8121#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008122 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008123#endif //WLAN_BTAMP_FEATURE
8124 }
8125
Yue Ma0d4891e2013-08-06 17:01:45 -07008126 /* Open debugfs interface */
8127 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8128 {
8129 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8130 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008131 }
8132
Jeff Johnson295189b2012-06-20 16:38:30 -07008133 /* Register TM level change handler function to the platform */
8134 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8135 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8136 {
8137 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8138 goto err_unregister_pmops;
8139 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008140
8141 /* register for riva power on lock to platform driver */
8142 if (req_riva_power_on_lock("wlan"))
8143 {
8144 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8145 __func__);
8146 goto err_unregister_pmops;
8147 }
8148
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 // register net device notifier for device change notification
8150 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8151
8152 if(ret < 0)
8153 {
8154 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8155 goto err_free_power_on_lock;
8156 }
8157
8158 //Initialize the nlink service
8159 if(nl_srv_init() != 0)
8160 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308161 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008162 goto err_reg_netdev;
8163 }
8164
Leo Chang4ce1cc52013-10-21 18:27:15 -07008165#ifdef WLAN_KD_READY_NOTIFIER
8166 pHddCtx->kd_nl_init = 1;
8167#endif /* WLAN_KD_READY_NOTIFIER */
8168
Jeff Johnson295189b2012-06-20 16:38:30 -07008169 //Initialize the BTC service
8170 if(btc_activate_service(pHddCtx) != 0)
8171 {
8172 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8173 goto err_nl_srv;
8174 }
8175
8176#ifdef PTT_SOCK_SVC_ENABLE
8177 //Initialize the PTT service
8178 if(ptt_sock_activate_svc(pHddCtx) != 0)
8179 {
8180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8181 goto err_nl_srv;
8182 }
8183#endif
8184
Jeff Johnson295189b2012-06-20 16:38:30 -07008185 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008186 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008187 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008188 /* Action frame registered in one adapter which will
8189 * applicable to all interfaces
8190 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008191 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008192 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008193
8194 mutex_init(&pHddCtx->sap_lock);
8195
8196 pHddCtx->isLoadUnloadInProgress = FALSE;
8197
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008198#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008199#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8200 /* Initialize the wake lcok */
8201 wake_lock_init(&pHddCtx->rx_wake_lock,
8202 WAKE_LOCK_SUSPEND,
8203 "qcom_rx_wakelock");
8204#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008205 /* Initialize the wake lcok */
8206 wake_lock_init(&pHddCtx->sap_wake_lock,
8207 WAKE_LOCK_SUSPEND,
8208 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008209#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008210
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008211 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8212 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008213
8214 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8215 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308216#ifndef CONFIG_ENABLE_LINUX_REG
8217 /*updating wiphy so that regulatory user hints can be processed*/
8218 if (wiphy)
8219 {
8220 regulatory_hint(wiphy, "00");
8221 }
8222#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008223 // Initialize the restart logic
8224 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308225
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008226 //Register the traffic monitor timer now
8227 if ( pHddCtx->cfg_ini->dynSplitscan)
8228 {
8229 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8230 VOS_TIMER_TYPE_SW,
8231 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8232 (void *)pHddCtx);
8233 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008234 goto success;
8235
8236err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008237#ifdef WLAN_KD_READY_NOTIFIER
8238 nl_srv_exit(pHddCtx->ptt_pid);
8239#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008240 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008241#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008242err_reg_netdev:
8243 unregister_netdevice_notifier(&hdd_netdev_notifier);
8244
8245err_free_power_on_lock:
8246 free_riva_power_on_lock("wlan");
8247
8248err_unregister_pmops:
8249 hddDevTmUnregisterNotifyCallback(pHddCtx);
8250 hddDeregisterPmOps(pHddCtx);
8251
Yue Ma0d4891e2013-08-06 17:01:45 -07008252 hdd_debugfs_exit(pHddCtx);
8253
Jeff Johnson295189b2012-06-20 16:38:30 -07008254#ifdef WLAN_BTAMP_FEATURE
8255err_bap_stop:
8256 WLANBAP_Stop(pVosContext);
8257#endif
8258
8259#ifdef WLAN_BTAMP_FEATURE
8260err_bap_close:
8261 WLANBAP_Close(pVosContext);
8262#endif
8263
Jeff Johnson295189b2012-06-20 16:38:30 -07008264err_close_adapter:
8265 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008266
8267#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308268 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008269#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008270
8271err_vosstop:
8272 vos_stop(pVosContext);
8273
Amar Singhala49cbc52013-10-08 18:37:44 -07008274err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008275 status = vos_sched_close( pVosContext );
8276 if (!VOS_IS_STATUS_SUCCESS(status)) {
8277 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8278 "%s: Failed to close VOSS Scheduler", __func__);
8279 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8280 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008281 vos_close(pVosContext );
8282
8283err_wiphy_unregister:
8284
8285#ifdef CONFIG_ENABLE_LINUX_REG
8286 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008287
Amar Singhal0a402232013-10-11 20:57:16 -07008288err_vos_nv_close:
8289
8290 vos_nv_close();
8291
Jeff Johnson295189b2012-06-20 16:38:30 -07008292err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008293#endif
8294
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008295 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008296
8297err_wdclose:
8298 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8299 vos_watchdog_close(pVosContext);
8300
Jeff Johnson295189b2012-06-20 16:38:30 -07008301err_config:
8302 kfree(pHddCtx->cfg_ini);
8303 pHddCtx->cfg_ini= NULL;
8304
8305err_free_hdd_context:
8306 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008307 wiphy_free(wiphy) ;
8308 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008309 VOS_BUG(1);
8310
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008311 if (hdd_is_ssr_required())
8312 {
8313 /* WDI timeout had happened during load, so SSR is needed here */
8314 subsystem_restart("wcnss");
8315 msleep(5000);
8316 }
8317 hdd_set_ssr_required (VOS_FALSE);
8318
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008319 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008320
8321success:
8322 EXIT();
8323 return 0;
8324}
8325
8326/**---------------------------------------------------------------------------
8327
Jeff Johnson32d95a32012-09-10 13:15:23 -07008328 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008329
Jeff Johnson32d95a32012-09-10 13:15:23 -07008330 This is the driver entry point - called in different timeline depending
8331 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008332
8333 \param - None
8334
8335 \return - 0 for success, non zero for failure
8336
8337 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008338static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008339{
8340 VOS_STATUS status;
8341 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008342 struct device *dev = NULL;
8343 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008344#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8345 int max_retries = 0;
8346#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008347
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308348#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8349 vos_wconn_trace_init();
8350#endif
8351
Jeff Johnson295189b2012-06-20 16:38:30 -07008352 ENTER();
8353
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008354#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008355 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008356#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008357
8358 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8359 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8360
8361 //Power Up Libra WLAN card first if not already powered up
8362 status = vos_chipPowerUp(NULL,NULL,NULL);
8363 if (!VOS_IS_STATUS_SUCCESS(status))
8364 {
8365 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8366 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308367#ifdef WLAN_OPEN_SOURCE
8368 wake_lock_destroy(&wlan_wake_lock);
8369#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008370 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008371 }
8372
Jeff Johnson295189b2012-06-20 16:38:30 -07008373#ifdef ANI_BUS_TYPE_PCI
8374
8375 dev = wcnss_wlan_get_device();
8376
8377#endif // ANI_BUS_TYPE_PCI
8378
8379#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008380
8381#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8382 /* wait until WCNSS driver downloads NV */
8383 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8384 msleep(1000);
8385 }
8386 if (max_retries >= 5) {
8387 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308388#ifdef WLAN_OPEN_SOURCE
8389 wake_lock_destroy(&wlan_wake_lock);
8390#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008391 return -ENODEV;
8392 }
8393#endif
8394
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 dev = wcnss_wlan_get_device();
8396#endif // ANI_BUS_TYPE_PLATFORM
8397
8398
8399 do {
8400 if (NULL == dev) {
8401 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8402 ret_status = -1;
8403 break;
8404 }
8405
Jeff Johnson295189b2012-06-20 16:38:30 -07008406#ifdef TIMER_MANAGER
8407 vos_timer_manager_init();
8408#endif
8409
8410 /* Preopen VOSS so that it is ready to start at least SAL */
8411 status = vos_preOpen(&pVosContext);
8412
8413 if (!VOS_IS_STATUS_SUCCESS(status))
8414 {
8415 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8416 ret_status = -1;
8417 break;
8418 }
8419
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008420#ifndef MODULE
8421 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8422 */
8423 hdd_set_conparam((v_UINT_t)con_mode);
8424#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008425
8426 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008427 if (hdd_wlan_startup(dev))
8428 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008429 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008430 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008431 vos_preClose( &pVosContext );
8432 ret_status = -1;
8433 break;
8434 }
8435
8436 /* Cancel the vote for XO Core ON
8437 * This is done here for safety purposes in case we re-initialize without turning
8438 * it OFF in any error scenario.
8439 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008440 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008441 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008442 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008443 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8444 {
8445 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008446 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008447 }
8448 } while (0);
8449
8450 if (0 != ret_status)
8451 {
8452 //Assert Deep sleep signal now to put Libra HW in lowest power state
8453 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8454 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8455
8456 //Vote off any PMIC voltage supplies
8457 vos_chipPowerDown(NULL, NULL, NULL);
8458#ifdef TIMER_MANAGER
8459 vos_timer_exit();
8460#endif
8461#ifdef MEMORY_DEBUG
8462 vos_mem_exit();
8463#endif
8464
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008465#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008467#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008468 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8469 }
8470 else
8471 {
8472 //Send WLAN UP indication to Nlink Service
8473 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8474
8475 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008476 }
8477
8478 EXIT();
8479
8480 return ret_status;
8481}
8482
Jeff Johnson32d95a32012-09-10 13:15:23 -07008483/**---------------------------------------------------------------------------
8484
8485 \brief hdd_module_init() - Init Function
8486
8487 This is the driver entry point (invoked when module is loaded using insmod)
8488
8489 \param - None
8490
8491 \return - 0 for success, non zero for failure
8492
8493 --------------------------------------------------------------------------*/
8494#ifdef MODULE
8495static int __init hdd_module_init ( void)
8496{
8497 return hdd_driver_init();
8498}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008499#else /* #ifdef MODULE */
8500static int __init hdd_module_init ( void)
8501{
8502 /* Driver initialization is delayed to fwpath_changed_handler */
8503 return 0;
8504}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008505#endif /* #ifdef MODULE */
8506
Jeff Johnson295189b2012-06-20 16:38:30 -07008507
8508/**---------------------------------------------------------------------------
8509
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008510 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008511
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008512 This is the driver exit point (invoked when module is unloaded using rmmod
8513 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008514
8515 \param - None
8516
8517 \return - None
8518
8519 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008520static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008521{
8522 hdd_context_t *pHddCtx = NULL;
8523 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008524 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008525
8526 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8527
8528 //Get the global vos context
8529 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8530
8531 if(!pVosContext)
8532 {
8533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8534 goto done;
8535 }
8536
8537 //Get the HDD context.
8538 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8539
8540 if(!pHddCtx)
8541 {
8542 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8543 }
8544 else
8545 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008546 while(isWDresetInProgress()) {
8547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8548 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008549 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008550
8551 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8553 "%s:SSR never completed, fatal error", __func__);
8554 VOS_BUG(0);
8555 }
8556 }
8557
Jeff Johnson295189b2012-06-20 16:38:30 -07008558
8559 pHddCtx->isLoadUnloadInProgress = TRUE;
8560 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8561
8562 //Do all the cleanup before deregistering the driver
8563 hdd_wlan_exit(pHddCtx);
8564 }
8565
Jeff Johnson295189b2012-06-20 16:38:30 -07008566 vos_preClose( &pVosContext );
8567
8568#ifdef TIMER_MANAGER
8569 vos_timer_exit();
8570#endif
8571#ifdef MEMORY_DEBUG
8572 vos_mem_exit();
8573#endif
8574
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308575#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8576 vos_wconn_trace_exit();
8577#endif
8578
Jeff Johnson295189b2012-06-20 16:38:30 -07008579done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008580#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008581 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008582#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008583 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8584}
8585
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008586/**---------------------------------------------------------------------------
8587
8588 \brief hdd_module_exit() - Exit function
8589
8590 This is the driver exit point (invoked when module is unloaded using rmmod)
8591
8592 \param - None
8593
8594 \return - None
8595
8596 --------------------------------------------------------------------------*/
8597static void __exit hdd_module_exit(void)
8598{
8599 hdd_driver_exit();
8600}
8601
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008602#ifdef MODULE
8603static int fwpath_changed_handler(const char *kmessage,
8604 struct kernel_param *kp)
8605{
Jeff Johnson76052702013-04-16 13:55:05 -07008606 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008607}
8608
8609static int con_mode_handler(const char *kmessage,
8610 struct kernel_param *kp)
8611{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008612 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008613}
8614#else /* #ifdef MODULE */
8615/**---------------------------------------------------------------------------
8616
Jeff Johnson76052702013-04-16 13:55:05 -07008617 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008618
Jeff Johnson76052702013-04-16 13:55:05 -07008619 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008620 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008621 - invoked when module parameter fwpath is modified from userspace to signal
8622 initializing the WLAN driver or when con_mode is modified from userspace
8623 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008624
8625 \return - 0 for success, non zero for failure
8626
8627 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008628static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008629{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008630 int ret_status;
8631
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008632 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008633 ret_status = hdd_driver_init();
8634 wlan_hdd_inited = ret_status ? 0 : 1;
8635 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008636 }
8637
8638 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008639
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008640 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008641
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008642 ret_status = hdd_driver_init();
8643 wlan_hdd_inited = ret_status ? 0 : 1;
8644 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008645}
8646
Jeff Johnson295189b2012-06-20 16:38:30 -07008647/**---------------------------------------------------------------------------
8648
Jeff Johnson76052702013-04-16 13:55:05 -07008649 \brief fwpath_changed_handler() - Handler Function
8650
8651 Handle changes to the fwpath parameter
8652
8653 \return - 0 for success, non zero for failure
8654
8655 --------------------------------------------------------------------------*/
8656static int fwpath_changed_handler(const char *kmessage,
8657 struct kernel_param *kp)
8658{
8659 int ret;
8660
8661 ret = param_set_copystring(kmessage, kp);
8662 if (0 == ret)
8663 ret = kickstart_driver();
8664 return ret;
8665}
8666
8667/**---------------------------------------------------------------------------
8668
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008669 \brief con_mode_handler() -
8670
8671 Handler function for module param con_mode when it is changed by userspace
8672 Dynamically linked - do nothing
8673 Statically linked - exit and init driver, as in rmmod and insmod
8674
Jeff Johnson76052702013-04-16 13:55:05 -07008675 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008676
Jeff Johnson76052702013-04-16 13:55:05 -07008677 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008678
8679 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008680static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008681{
Jeff Johnson76052702013-04-16 13:55:05 -07008682 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008683
Jeff Johnson76052702013-04-16 13:55:05 -07008684 ret = param_set_int(kmessage, kp);
8685 if (0 == ret)
8686 ret = kickstart_driver();
8687 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008688}
8689#endif /* #ifdef MODULE */
8690
8691/**---------------------------------------------------------------------------
8692
Jeff Johnson295189b2012-06-20 16:38:30 -07008693 \brief hdd_get_conparam() -
8694
8695 This is the driver exit point (invoked when module is unloaded using rmmod)
8696
8697 \param - None
8698
8699 \return - tVOS_CON_MODE
8700
8701 --------------------------------------------------------------------------*/
8702tVOS_CON_MODE hdd_get_conparam ( void )
8703{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008704#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008705 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008706#else
8707 return (tVOS_CON_MODE)curr_con_mode;
8708#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008709}
8710void hdd_set_conparam ( v_UINT_t newParam )
8711{
8712 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008713#ifndef MODULE
8714 curr_con_mode = con_mode;
8715#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008716}
8717/**---------------------------------------------------------------------------
8718
8719 \brief hdd_softap_sta_deauth() - function
8720
8721 This to take counter measure to handle deauth req from HDD
8722
8723 \param - pAdapter - Pointer to the HDD
8724
8725 \param - enable - boolean value
8726
8727 \return - None
8728
8729 --------------------------------------------------------------------------*/
8730
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008731VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008732{
Jeff Johnson295189b2012-06-20 16:38:30 -07008733 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008734 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008735
8736 ENTER();
8737
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008738 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8739 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008740
8741 //Ignore request to deauth bcmc station
8742 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008743 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008744
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008745 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008746
8747 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008748 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008749}
8750
8751/**---------------------------------------------------------------------------
8752
8753 \brief hdd_softap_sta_disassoc() - function
8754
8755 This to take counter measure to handle deauth req from HDD
8756
8757 \param - pAdapter - Pointer to the HDD
8758
8759 \param - enable - boolean value
8760
8761 \return - None
8762
8763 --------------------------------------------------------------------------*/
8764
8765void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8766{
8767 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8768
8769 ENTER();
8770
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308771 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008772
8773 //Ignore request to disassoc bcmc station
8774 if( pDestMacAddress[0] & 0x1 )
8775 return;
8776
8777 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8778}
8779
8780void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8781{
8782 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8783
8784 ENTER();
8785
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308786 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008787
8788 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8789}
8790
Jeff Johnson295189b2012-06-20 16:38:30 -07008791/**---------------------------------------------------------------------------
8792 *
8793 * \brief hdd_get__concurrency_mode() -
8794 *
8795 *
8796 * \param - None
8797 *
8798 * \return - CONCURRENCY MODE
8799 *
8800 * --------------------------------------------------------------------------*/
8801tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8802{
8803 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8804 hdd_context_t *pHddCtx;
8805
8806 if (NULL != pVosContext)
8807 {
8808 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8809 if (NULL != pHddCtx)
8810 {
8811 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8812 }
8813 }
8814
8815 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008816 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008817 return VOS_STA;
8818}
8819
8820/* Decide whether to allow/not the apps power collapse.
8821 * Allow apps power collapse if we are in connected state.
8822 * if not, allow only if we are in IMPS */
8823v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8824{
8825 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008826 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008827 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008828 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8829 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8830 hdd_adapter_t *pAdapter = NULL;
8831 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008832 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008833
Jeff Johnson295189b2012-06-20 16:38:30 -07008834 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8835 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008836
Yathish9f22e662012-12-10 14:21:35 -08008837 concurrent_state = hdd_get_concurrency_mode();
8838
8839#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8840 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8841 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8842 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8843 return TRUE;
8844#endif
8845
Jeff Johnson295189b2012-06-20 16:38:30 -07008846 /*loop through all adapters. TBD fix for Concurrency */
8847 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8848 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8849 {
8850 pAdapter = pAdapterNode->pAdapter;
8851 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8852 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8853 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008854 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008855 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008856 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008857 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8858 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008859 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008860 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008861 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8862 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008863 return FALSE;
8864 }
8865 }
8866 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8867 pAdapterNode = pNext;
8868 }
8869 return TRUE;
8870}
8871
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008872/* Decides whether to send suspend notification to Riva
8873 * if any adapter is in BMPS; then it is required */
8874v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8875{
8876 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8877 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8878
8879 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8880 {
8881 return TRUE;
8882 }
8883 return FALSE;
8884}
8885
Jeff Johnson295189b2012-06-20 16:38:30 -07008886void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8887{
8888 switch(mode)
8889 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008890 case VOS_STA_MODE:
8891 case VOS_P2P_CLIENT_MODE:
8892 case VOS_P2P_GO_MODE:
8893 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008894 pHddCtx->concurrency_mode |= (1 << mode);
8895 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008896 break;
8897 default:
8898 break;
8899
8900 }
8901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8902 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8903}
8904
8905
8906void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8907{
8908 switch(mode)
8909 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008910 case VOS_STA_MODE:
8911 case VOS_P2P_CLIENT_MODE:
8912 case VOS_P2P_GO_MODE:
8913 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008914 pHddCtx->no_of_sessions[mode]--;
8915 if (!(pHddCtx->no_of_sessions[mode]))
8916 pHddCtx->concurrency_mode &= (~(1 << mode));
8917 break;
8918 default:
8919 break;
8920 }
8921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8922 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8923}
8924
Jeff Johnsone7245742012-09-05 17:12:55 -07008925/**---------------------------------------------------------------------------
8926 *
8927 * \brief wlan_hdd_restart_init
8928 *
8929 * This function initalizes restart timer/flag. An internal function.
8930 *
8931 * \param - pHddCtx
8932 *
8933 * \return - None
8934 *
8935 * --------------------------------------------------------------------------*/
8936
8937static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8938{
8939 /* Initialize */
8940 pHddCtx->hdd_restart_retries = 0;
8941 atomic_set(&pHddCtx->isRestartInProgress, 0);
8942 vos_timer_init(&pHddCtx->hdd_restart_timer,
8943 VOS_TIMER_TYPE_SW,
8944 wlan_hdd_restart_timer_cb,
8945 pHddCtx);
8946}
8947/**---------------------------------------------------------------------------
8948 *
8949 * \brief wlan_hdd_restart_deinit
8950 *
8951 * This function cleans up the resources used. An internal function.
8952 *
8953 * \param - pHddCtx
8954 *
8955 * \return - None
8956 *
8957 * --------------------------------------------------------------------------*/
8958
8959static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8960{
8961
8962 VOS_STATUS vos_status;
8963 /* Block any further calls */
8964 atomic_set(&pHddCtx->isRestartInProgress, 1);
8965 /* Cleanup */
8966 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8967 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008968 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008969 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8970 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008971 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008972
8973}
8974
8975/**---------------------------------------------------------------------------
8976 *
8977 * \brief wlan_hdd_framework_restart
8978 *
8979 * This function uses a cfg80211 API to start a framework initiated WLAN
8980 * driver module unload/load.
8981 *
8982 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8983 *
8984 *
8985 * \param - pHddCtx
8986 *
8987 * \return - VOS_STATUS_SUCCESS: Success
8988 * VOS_STATUS_E_EMPTY: Adapter is Empty
8989 * VOS_STATUS_E_NOMEM: No memory
8990
8991 * --------------------------------------------------------------------------*/
8992
8993static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8994{
8995 VOS_STATUS status = VOS_STATUS_SUCCESS;
8996 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008997 int len = (sizeof (struct ieee80211_mgmt));
8998 struct ieee80211_mgmt *mgmt = NULL;
8999
9000 /* Prepare the DEAUTH managment frame with reason code */
9001 mgmt = kzalloc(len, GFP_KERNEL);
9002 if(mgmt == NULL)
9003 {
9004 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9005 "%s: memory allocation failed (%d bytes)", __func__, len);
9006 return VOS_STATUS_E_NOMEM;
9007 }
9008 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009009
9010 /* Iterate over all adapters/devices */
9011 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9012 do
9013 {
9014 if( (status == VOS_STATUS_SUCCESS) &&
9015 pAdapterNode &&
9016 pAdapterNode->pAdapter)
9017 {
9018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9019 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9020 pAdapterNode->pAdapter->dev->name,
9021 pAdapterNode->pAdapter->device_mode,
9022 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009023 /*
9024 * CFG80211 event to restart the driver
9025 *
9026 * 'cfg80211_send_unprot_deauth' sends a
9027 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9028 * of SME(Linux Kernel) state machine.
9029 *
9030 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9031 * the driver.
9032 *
9033 */
9034
9035 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009036 }
9037 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9038 pAdapterNode = pNext;
9039 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9040
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009041
9042 /* Free the allocated management frame */
9043 kfree(mgmt);
9044
Jeff Johnsone7245742012-09-05 17:12:55 -07009045 /* Retry until we unload or reach max count */
9046 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9047 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9048
9049 return status;
9050
9051}
9052/**---------------------------------------------------------------------------
9053 *
9054 * \brief wlan_hdd_restart_timer_cb
9055 *
9056 * Restart timer callback. An internal function.
9057 *
9058 * \param - User data:
9059 *
9060 * \return - None
9061 *
9062 * --------------------------------------------------------------------------*/
9063
9064void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9065{
9066 hdd_context_t *pHddCtx = usrDataForCallback;
9067 wlan_hdd_framework_restart(pHddCtx);
9068 return;
9069
9070}
9071
9072
9073/**---------------------------------------------------------------------------
9074 *
9075 * \brief wlan_hdd_restart_driver
9076 *
9077 * This function sends an event to supplicant to restart the WLAN driver.
9078 *
9079 * This function is called from vos_wlanRestart.
9080 *
9081 * \param - pHddCtx
9082 *
9083 * \return - VOS_STATUS_SUCCESS: Success
9084 * VOS_STATUS_E_EMPTY: Adapter is Empty
9085 * VOS_STATUS_E_ALREADY: Request already in progress
9086
9087 * --------------------------------------------------------------------------*/
9088VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9089{
9090 VOS_STATUS status = VOS_STATUS_SUCCESS;
9091
9092 /* A tight check to make sure reentrancy */
9093 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9094 {
9095 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9096 "%s: WLAN restart is already in progress", __func__);
9097
9098 return VOS_STATUS_E_ALREADY;
9099 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009100 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009101#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009102 wcnss_reset_intr();
9103#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009104
Jeff Johnsone7245742012-09-05 17:12:55 -07009105 return status;
9106}
9107
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009108/*
9109 * API to find if there is any STA or P2P-Client is connected
9110 */
9111VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9112{
9113 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9114}
Jeff Johnsone7245742012-09-05 17:12:55 -07009115
Jeff Johnson295189b2012-06-20 16:38:30 -07009116//Register the module init/exit functions
9117module_init(hdd_module_init);
9118module_exit(hdd_module_exit);
9119
9120MODULE_LICENSE("Dual BSD/GPL");
9121MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9122MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9123
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009124module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9125 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009126
Jeff Johnson76052702013-04-16 13:55:05 -07009127module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009128 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009129
9130module_param(enable_dfs_chan_scan, int,
9131 S_IRUSR | S_IRGRP | S_IROTH);
9132
9133module_param(enable_11d, int,
9134 S_IRUSR | S_IRGRP | S_IROTH);
9135
9136module_param(country_code, charp,
9137 S_IRUSR | S_IRGRP | S_IROTH);