blob: 640ffbea27ca796331814e16f14a6062329d0d7f [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};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700165
166/*
167 * Size of Driver command strings from upper layer
168 */
169#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
170#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
171
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700172#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
173#define TID_MIN_VALUE 0
174#define TID_MAX_VALUE 15
175static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
176 tAniTrafStrmMetrics* pTsmMetrics);
177#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
178
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700179/*
180 * Driver miracast parameters 0-Disabled
181 * 1-Source, 2-Sink
182 */
183#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
184#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
185
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800186#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700188#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700189/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700190static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700191
192//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700193static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
194static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
195static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
196void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800197void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700198
Jeff Johnson295189b2012-06-20 16:38:30 -0700199v_U16_t hdd_select_queue(struct net_device *dev,
200 struct sk_buff *skb);
201
202#ifdef WLAN_FEATURE_PACKET_FILTERING
203static void hdd_set_multicast_list(struct net_device *dev);
204#endif
205
206void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700207int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700210
Srinivas Girigowdade697412013-02-14 16:31:48 -0800211#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
212void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
213static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700214static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
215 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
216 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700217static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
218 tANI_U8 *pTargetApBssid,
219 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800220#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700221#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
222VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
223#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225static int hdd_netdev_notifier_call(struct notifier_block * nb,
226 unsigned long state,
227 void *ndev)
228{
229 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700230 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700231 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700232#ifdef WLAN_BTAMP_FEATURE
233 VOS_STATUS status;
234 hdd_context_t *pHddCtx;
235#endif
236
237 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700238 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700239 (strncmp(dev->name, "p2p", 3)))
240 return NOTIFY_DONE;
241
242 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700243 return NOTIFY_DONE;
244
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700246 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700247
Jeff Johnson27cee452013-03-27 11:10:24 -0700248 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700249 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800250 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 VOS_ASSERT(0);
252 return NOTIFY_DONE;
253 }
254
Jeff Johnson27cee452013-03-27 11:10:24 -0700255 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
256 if (NULL == pHddCtx)
257 {
258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
259 VOS_ASSERT(0);
260 return NOTIFY_DONE;
261 }
262
263 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
264 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700265
266 switch (state) {
267 case NETDEV_REGISTER:
268 break;
269
270 case NETDEV_UNREGISTER:
271 break;
272
273 case NETDEV_UP:
274 break;
275
276 case NETDEV_DOWN:
277 break;
278
279 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700280 if(TRUE == pAdapter->isLinkUpSvcNeeded)
281 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700282 break;
283
284 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700285 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700286 {
287 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800288 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530289 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700290 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800291 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
293 if(!result)
294 {
295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800296 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700297 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 }
299 }
300 else
301 {
302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700303 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 }
305#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700307 status = WLANBAP_StopAmp();
308 if(VOS_STATUS_SUCCESS != status )
309 {
310 pHddCtx->isAmpAllowed = VOS_TRUE;
311 hddLog(VOS_TRACE_LEVEL_FATAL,
312 "%s: Failed to stop AMP", __func__);
313 }
314 else
315 {
316 //a state m/c implementation in PAL is TBD to avoid this delay
317 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700318 if ( pHddCtx->isAmpAllowed )
319 {
320 WLANBAP_DeregisterFromHCI();
321 pHddCtx->isAmpAllowed = VOS_FALSE;
322 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700323 }
324#endif //WLAN_BTAMP_FEATURE
325 break;
326
327 default:
328 break;
329 }
330
331 return NOTIFY_DONE;
332}
333
334struct notifier_block hdd_netdev_notifier = {
335 .notifier_call = hdd_netdev_notifier_call,
336};
337
338/*---------------------------------------------------------------------------
339 * Function definitions
340 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700341void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
342void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700343//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700344static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700345#ifndef MODULE
346/* current con_mode - used only for statically linked driver
347 * con_mode is changed by userspace to indicate a mode change which will
348 * result in calling the module exit and init functions. The module
349 * exit function will clean up based on the value of con_mode prior to it
350 * being changed by userspace. So curr_con_mode records the current con_mode
351 * for exit when con_mode becomes the next mode for init
352 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700353static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700354#endif
355
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800356/**---------------------------------------------------------------------------
357
358 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
359
360 Called immediately after the cfg.ini is read in order to configure
361 the desired trace levels.
362
363 \param - moduleId - module whose trace level is being configured
364 \param - bitmask - bitmask of log levels to be enabled
365
366 \return - void
367
368 --------------------------------------------------------------------------*/
369static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
370{
371 wpt_tracelevel level;
372
373 /* if the bitmask is the default value, then a bitmask was not
374 specified in cfg.ini, so leave the logging level alone (it
375 will remain at the "compiled in" default value) */
376 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
377 {
378 return;
379 }
380
381 /* a mask was specified. start by disabling all logging */
382 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
383
384 /* now cycle through the bitmask until all "set" bits are serviced */
385 level = VOS_TRACE_LEVEL_FATAL;
386 while (0 != bitmask)
387 {
388 if (bitmask & 1)
389 {
390 vos_trace_setValue(moduleId, level, 1);
391 }
392 level++;
393 bitmask >>= 1;
394 }
395}
396
397
Jeff Johnson295189b2012-06-20 16:38:30 -0700398/**---------------------------------------------------------------------------
399
400 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
401
402 Called immediately after the cfg.ini is read in order to configure
403 the desired trace levels in the WDI.
404
405 \param - moduleId - module whose trace level is being configured
406 \param - bitmask - bitmask of log levels to be enabled
407
408 \return - void
409
410 --------------------------------------------------------------------------*/
411static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
412{
413 wpt_tracelevel level;
414
415 /* if the bitmask is the default value, then a bitmask was not
416 specified in cfg.ini, so leave the logging level alone (it
417 will remain at the "compiled in" default value) */
418 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
419 {
420 return;
421 }
422
423 /* a mask was specified. start by disabling all logging */
424 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
425
426 /* now cycle through the bitmask until all "set" bits are serviced */
427 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
428 while (0 != bitmask)
429 {
430 if (bitmask & 1)
431 {
432 wpalTraceSetLevel(moduleId, level, 1);
433 }
434 level++;
435 bitmask >>= 1;
436 }
437}
Jeff Johnson295189b2012-06-20 16:38:30 -0700438
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530439/*
440 * FUNCTION: wlan_hdd_validate_context
441 * This function is used to check the HDD context
442 */
443int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
444{
445 ENTER();
446
447 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
448 {
449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
450 "%s: HDD context is Null", __func__);
451 return -ENODEV;
452 }
453
454 if (pHddCtx->isLogpInProgress)
455 {
456 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
457 "%s: LOGP in Progress. Ignore!!!", __func__);
458 return -EAGAIN;
459 }
460
461 if (pHddCtx->isLoadUnloadInProgress)
462 {
463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
464 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
465 return -EAGAIN;
466 }
467 return 0;
468}
469
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530470void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
471{
472 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
473 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
474 hdd_config_t *cfg_param;
475 eCsrPhyMode phyMode;
476
477 if (NULL == pHddCtx)
478 {
479 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
480 "HDD Context is null !!");
481 return ;
482 }
483
484 cfg_param = pHddCtx->cfg_ini;
485
486 if (NULL == cfg_param)
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
489 "cfg_params not available !!");
490 return ;
491 }
492
493 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
494
495 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
496 {
497 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
498 (eCSR_DOT11_MODE_11ac == phyMode) ||
499 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
502 "Setting phymode to 11n!!");
503 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
504 }
505 }
506 else
507 {
508 /*New country Supports 11ac as well resetting value back from .ini*/
509 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
510 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
511 return ;
512 }
513
514 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
515 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
516 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
517 {
518 VOS_STATUS vosStatus;
519
520 // need to issue a disconnect to CSR.
521 INIT_COMPLETION(pAdapter->disconnect_comp_var);
522 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
523 pAdapter->sessionId,
524 eCSR_DISCONNECT_REASON_UNSPECIFIED );
525
526 if (VOS_STATUS_SUCCESS == vosStatus)
527 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
528 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
529
530 }
531}
532
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700533void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
534{
535 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
536 hdd_config_t *cfg_param;
537
538 if (NULL == pHddCtx)
539 {
540 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
541 "HDD Context is null !!");
542 return ;
543 }
544
545 cfg_param = pHddCtx->cfg_ini;
546
547 if (NULL == cfg_param)
548 {
549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
550 "cfg_params not available !!");
551 return ;
552 }
553
554 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
555 {
556 /*New country doesn't support DFS */
557 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
558 }
559 else
560 {
561 /*New country Supports DFS as well resetting value back from .ini*/
562 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
563 }
564
565}
566
Rajeev79dbe4c2013-10-05 11:03:42 +0530567#ifdef FEATURE_WLAN_BATCH_SCAN
568
569/**---------------------------------------------------------------------------
570
571 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
572 input string
573
574 This function extracts assigned integer from string in below format:
575 "STRING=10" : extracts integer 10 from this string
576
577 \param - pInPtr Pointer to input string
578 \param - base Base for string to int conversion(10 for decimal 16 for hex)
579 \param - pOutPtr Pointer to variable in which extracted integer needs to be
580 assigned
581 \param - pLastArg to tell whether it is last arguement in input string or
582 not
583
584 \return - NULL for failure cases
585 pointer to next arguement in input string for success cases
586 --------------------------------------------------------------------------*/
587static tANI_U8 *
588hdd_extract_assigned_int_from_str
589(
590 tANI_U8 *pInPtr,
591 tANI_U8 base,
592 tANI_U32 *pOutPtr,
593 tANI_U8 *pLastArg
594)
595{
596 int tempInt;
597 int v = 0;
598 char buf[32];
599 int val = 0;
600 *pLastArg = FALSE;
601
602 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
603 if (NULL == pInPtr)
604 {
605 return NULL;
606 }
607
608 pInPtr++;
609
610 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
611
612 val = sscanf(pInPtr, "%32s ", buf);
613 if (val < 0 && val > strlen(pInPtr))
614 {
615 return NULL;
616 }
617 pInPtr += val;
618 v = kstrtos32(buf, base, &tempInt);
619 if (v < 0)
620 {
621 return NULL;
622 }
623 *pOutPtr = tempInt;
624
625 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
626 if (NULL == pInPtr)
627 {
628 *pLastArg = TRUE;
629 return NULL;
630 }
631 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
632
633 return pInPtr;
634}
635
636/**---------------------------------------------------------------------------
637
638 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
639 input string
640
641 This function extracts assigned character from string in below format:
642 "STRING=A" : extracts char 'A' from this string
643
644 \param - pInPtr Pointer to input string
645 \param - pOutPtr Pointer to variable in which extracted char needs to be
646 assigned
647 \param - pLastArg to tell whether it is last arguement in input string or
648 not
649
650 \return - NULL for failure cases
651 pointer to next arguement in input string for success cases
652 --------------------------------------------------------------------------*/
653static tANI_U8 *
654hdd_extract_assigned_char_from_str
655(
656 tANI_U8 *pInPtr,
657 tANI_U8 *pOutPtr,
658 tANI_U8 *pLastArg
659)
660{
661 *pLastArg = FALSE;
662
663 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
664 if (NULL == pInPtr)
665 {
666 return NULL;
667 }
668
669 pInPtr++;
670
671 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
672
673 *pOutPtr = *pInPtr;
674
675 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
676 if (NULL == pInPtr)
677 {
678 *pLastArg = TRUE;
679 return NULL;
680 }
681 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
682
683 return pInPtr;
684}
685
686
687/**---------------------------------------------------------------------------
688
689 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
690
691 This function parses set batch scan command in below format:
692 WLS_BATCHING_SET <space> followed by below arguements
693 "SCANFREQ=XX" : Optional defaults to 30 sec
694 "MSCAN=XX" : Required number of scans to attempt to batch
695 "BESTN=XX" : Best Network (RSSI) defaults to 16
696 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
697 A. implies only 5 GHz , B. implies only 2.4GHz
698 "RTT=X" : optional defaults to 0
699 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
700 error
701
702 For example input commands:
703 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
704 translated into set batch scan with following parameters:
705 a) Frequence 60 seconds
706 b) Batch 10 scans together
707 c) Best RSSI to be 20
708 d) 5GHz band only
709 e) RTT is equal to 0
710
711 \param - pValue Pointer to input channel list
712 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
713
714 \return - 0 for success non-zero for failure
715
716 --------------------------------------------------------------------------*/
717static int
718hdd_parse_set_batchscan_command
719(
720 tANI_U8 *pValue,
721 tSirSetBatchScanReq *pHddSetBatchScanReq
722)
723{
724 tANI_U8 *inPtr = pValue;
725 tANI_U8 val = 0;
726 tANI_U8 lastArg = 0;
727
728 /*initialize default values*/
729 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
730 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
731 pHddSetBatchScanReq->rtt = 0;
732 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
733
734 /*go to space after WLS_BATCHING_SET command*/
735 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
736 /*no argument after the command*/
737 if (NULL == inPtr)
738 {
739 return -EINVAL;
740 }
741
742 /*no space after the command*/
743 else if (SPACE_ASCII_VALUE != *inPtr)
744 {
745 return -EINVAL;
746 }
747
748 /*removing empty spaces*/
749 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
750
751 /*no argument followed by spaces*/
752 if ('\0' == *inPtr)
753 {
754 return -EINVAL;
755 }
756
757 /*check and parse SCANFREQ*/
758 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
759 {
760 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
761 &pHddSetBatchScanReq->scanFrequency, &lastArg);
762 if ( (NULL == inPtr) || (TRUE == lastArg))
763 {
764 return -EINVAL;
765 }
766 }
767
768 /*check and parse MSCAN*/
769 if ((strncmp(inPtr, "MSCAN", 5) == 0))
770 {
771 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
772 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
773 if (TRUE == lastArg)
774 {
775 goto done;
776 }
777 else if (NULL == inPtr)
778 {
779 return -EINVAL;
780 }
781 }
782 else
783 {
784 return -EINVAL;
785 }
786
787 /*check and parse BESTN*/
788 if ((strncmp(inPtr, "BESTN", 5) == 0))
789 {
790 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
791 &pHddSetBatchScanReq->bestNetwork, &lastArg);
792 if (TRUE == lastArg)
793 {
794 goto done;
795 }
796 else if (NULL == inPtr)
797 {
798 return -EINVAL;
799 }
800 }
801
802 /*check and parse CHANNEL*/
803 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
804 {
805 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
806 if (TRUE == lastArg)
807 {
808 goto done;
809 }
810 else if (NULL == inPtr)
811 {
812 return -EINVAL;
813 }
814 if (('A' == val) || ('a' == val))
815 {
816 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
817 }
818 else if (('B' == val) || ('b' == val))
819 {
820 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
821 }
822 else
823 {
824 return -EINVAL;
825 }
826 }
827
828 /*check and parse RTT*/
829 if ((strncmp(inPtr, "RTT", 3) == 0))
830 {
831 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
832 &pHddSetBatchScanReq->rtt, &lastArg);
833 if (TRUE == lastArg)
834 {
835 goto done;
836 }
837 if (NULL == inPtr)
838 {
839 return -EINVAL;
840 }
841 }
842
843
844done:
845
846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
847 "Received WLS_BATCHING_SET with SCANFREQ=%d "
848 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
849 pHddSetBatchScanReq->scanFrequency,
850 pHddSetBatchScanReq->numberOfScansToBatch,
851 pHddSetBatchScanReq->bestNetwork,
852 pHddSetBatchScanReq->rfBand,
853 pHddSetBatchScanReq->rtt);
854
855 return 0;
856}/*End of hdd_parse_set_batchscan_command*/
857
858/**---------------------------------------------------------------------------
859
860 \brief hdd_set_batch_scan_req_callback () - This function is called after
861 receiving set batch scan response from FW and it saves set batch scan
862 response data FW to HDD context and sets the completion event on
863 which hdd_ioctl is waiting
864
865 \param - callbackContext Pointer to HDD adapter
866 \param - pRsp Pointer to set batch scan response data received from FW
867
868 \return - nothing
869
870 --------------------------------------------------------------------------*/
871static void hdd_set_batch_scan_req_callback
872(
873 void *callbackContext,
874 tSirSetBatchScanRsp *pRsp
875)
876{
877 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
878 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
879
880 /*sanity check*/
881 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
882 {
883 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
884 "%s: Invalid pAdapter magic", __func__);
885 VOS_ASSERT(0);
886 return;
887 }
888 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
889
890 /*save set batch scan response*/
891 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
892
893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
894 "Received set batch scan rsp from FW with nScansToBatch=%d",
895 pHddSetBatchScanRsp->nScansToBatch);
896
897 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
898 complete(&pAdapter->hdd_set_batch_scan_req_var);
899
900 return;
901}/*End of hdd_set_batch_scan_req_callback*/
902
903
904/**---------------------------------------------------------------------------
905
906 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
907 info in hdd batch scan response queue
908
909 \param - pAdapter Pointer to hdd adapter
910 \param - pAPMetaInfo Pointer to access point meta info
911 \param - scanId scan ID of batch scan response
912 \param - isLastAp tells whether AP is last AP in batch scan response or not
913
914 \return - nothing
915
916 --------------------------------------------------------------------------*/
917static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
918 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
919{
920 tHddBatchScanRsp *pHead;
921 tHddBatchScanRsp *pNode;
922 tHddBatchScanRsp *pPrev;
923 tHddBatchScanRsp *pTemp;
924 tANI_U8 ssidLen;
925
926 /*head of hdd batch scan response queue*/
927 pHead = pAdapter->pBatchScanRsp;
928
929 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
930 if (NULL == pNode)
931 {
932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
933 "%s: Could not allocate memory", __func__);
934 VOS_ASSERT(0);
935 return;
936 }
937
938 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
939 sizeof(pNode->ApInfo.bssid));
940 ssidLen = strlen(pApMetaInfo->ssid);
941 if (SIR_MAX_SSID_SIZE < ssidLen)
942 {
943 /*invalid scan result*/
944 vos_mem_free(pNode);
945 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
946 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
947 return;
948 }
949 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
950 /*null terminate ssid*/
951 pNode->ApInfo.ssid[ssidLen] = '\0';
952 pNode->ApInfo.ch = pApMetaInfo->ch;
953 pNode->ApInfo.rssi = pApMetaInfo->rssi;
954 pNode->ApInfo.age = pApMetaInfo->timestamp;
955 pNode->ApInfo.batchId = scanId;
956 pNode->ApInfo.isLastAp = isLastAp;
957
958 pNode->pNext = NULL;
959 if (NULL == pHead)
960 {
961 pAdapter->pBatchScanRsp = pNode;
962 }
963 else
964 {
965 pTemp = pHead;
966 while (NULL != pTemp)
967 {
968 pPrev = pTemp;
969 pTemp = pTemp->pNext;
970 }
971 pPrev->pNext = pNode;
972 }
973
974 return;
975}/*End of hdd_populate_batch_scan_rsp_queue*/
976
977/**---------------------------------------------------------------------------
978
979 \brief hdd_batch_scan_result_ind_callback () - This function is called after
980 receiving batch scan response indication from FW. It saves get batch scan
981 response data in HDD batch scan response queue. This callback sets the
982 completion event on which hdd_ioctl is waiting only after getting complete
983 batch scan response data from FW
984
985 \param - callbackContext Pointer to HDD adapter
986 \param - pRsp Pointer to get batch scan response data received from FW
987
988 \return - nothing
989
990 --------------------------------------------------------------------------*/
991static void hdd_batch_scan_result_ind_callback
992(
993 void *callbackContext,
994 void *pRsp
995)
996{
997 v_BOOL_t isLastAp;
998 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -0700999 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301000 tANI_U32 numberScanList;
1001 tANI_U32 nextScanListOffset;
1002 tANI_U32 nextApMetaInfoOffset;
1003 hdd_adapter_t* pAdapter;
1004 tpSirBatchScanList pScanList;
1005 tpSirBatchScanNetworkInfo pApMetaInfo;
1006 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1007 tSirSetBatchScanReq *pReq;
1008
1009 pAdapter = (hdd_adapter_t *)callbackContext;
1010 /*sanity check*/
1011 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1012 {
1013 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1014 "%s: Invalid pAdapter magic", __func__);
1015 VOS_ASSERT(0);
1016 return;
1017 }
1018
1019 /*initialize locals*/
1020 pReq = &pAdapter->hddSetBatchScanReq;
1021 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1022 isLastAp = FALSE;
1023 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001024 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301025 numberScanList = 0;
1026 nextScanListOffset = 0;
1027 nextApMetaInfoOffset = 0;
1028 pScanList = NULL;
1029 pApMetaInfo = NULL;
1030
1031 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1032 {
1033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1034 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1035 isLastAp = TRUE;
1036 goto done;
1037 }
1038
1039 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1041 "Batch scan rsp: numberScalList %d", numberScanList);
1042
1043 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1044 {
1045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: numberScanList %d", __func__, numberScanList);
1047 isLastAp = TRUE;
1048 goto done;
1049 }
1050
1051 while (numberScanList)
1052 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001053 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301054 nextScanListOffset);
1055 if (NULL == pScanList)
1056 {
1057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1058 "%s: pScanList is %p", __func__, pScanList);
1059 isLastAp = TRUE;
1060 goto done;
1061 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001062 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001064 "Batch scan rsp: numApMetaInfo %d scanId %d",
1065 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301066
1067 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1068 {
1069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1070 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1071 isLastAp = TRUE;
1072 goto done;
1073 }
1074
Rajeev Kumarce651e42013-10-21 18:57:15 -07001075 /*Initialize next AP meta info offset for next scan list*/
1076 nextApMetaInfoOffset = 0;
1077
Rajeev79dbe4c2013-10-05 11:03:42 +05301078 while (numApMetaInfo)
1079 {
1080 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1081 nextApMetaInfoOffset);
1082 if (NULL == pApMetaInfo)
1083 {
1084 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1085 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1086 isLastAp = TRUE;
1087 goto done;
1088 }
1089 /*calculate AP age*/
1090 pApMetaInfo->timestamp =
1091 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1092
1093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1094 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1095 "ch %d rssi %d timestamp %d", __func__,
1096 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1097 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1098 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1099 pApMetaInfo->ch, pApMetaInfo->rssi,
1100 pApMetaInfo->timestamp);
1101
1102 /*mark last AP in batch scan response*/
1103 if ((TRUE == pBatchScanRsp->isLastResult) &&
1104 (1 == numberScanList) && (1 == numApMetaInfo))
1105 {
1106 isLastAp = TRUE;
1107 }
1108
1109 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1110 /*store batch scan repsonse in hdd queue*/
1111 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1112 pScanList->scanId, isLastAp);
1113 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1114
1115 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1116 numApMetaInfo--;
1117 }
1118
Rajeev Kumarce651e42013-10-21 18:57:15 -07001119 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1120 + (sizeof(tSirBatchScanNetworkInfo)
1121 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301122 numberScanList--;
1123 }
1124
1125done:
1126
1127 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1128 requested from hdd_ioctl*/
1129 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1130 (TRUE == isLastAp))
1131 {
1132 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1133 complete(&pAdapter->hdd_get_batch_scan_req_var);
1134 }
1135
1136 return;
1137}/*End of hdd_batch_scan_result_ind_callback*/
1138
1139/**---------------------------------------------------------------------------
1140
1141 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1142 response as per batch scan FR request format by putting proper markers
1143
1144 \param - pDest pointer to destination buffer
1145 \param - cur_len current length
1146 \param - tot_len total remaining size which can be written to user space
1147 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1148 \param - pAdapter Pointer to HDD adapter
1149
1150 \return - ret no of characters written
1151
1152 --------------------------------------------------------------------------*/
1153static tANI_U32
1154hdd_format_batch_scan_rsp
1155(
1156 tANI_U8 *pDest,
1157 tANI_U32 cur_len,
1158 tANI_U32 tot_len,
1159 tHddBatchScanRsp *pApMetaInfo,
1160 hdd_adapter_t* pAdapter
1161)
1162{
1163 tANI_U32 ret = 0;
1164 tANI_U32 rem_len = 0;
1165 tANI_U8 temp_len = 0;
1166 tANI_U8 temp_total_len = 0;
1167 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1168 tANI_U8 *pTemp = temp;
1169
1170 /*Batch scan reponse needs to be returned to user space in
1171 following format:
1172 "scancount=X\n" where X is the number of scans in current batch
1173 batch
1174 "trunc\n" optional present if current scan truncated
1175 "bssid=XX:XX:XX:XX:XX:XX\n"
1176 "ssid=XXXX\n"
1177 "freq=X\n" frequency in Mhz
1178 "level=XX\n"
1179 "age=X\n" ms
1180 "dist=X\n" cm (-1 if not available)
1181 "errror=X\n" (-1if not available)
1182 "====\n" (end of ap marker)
1183 "####\n" (end of scan marker)
1184 "----\n" (end of results)*/
1185 /*send scan result in above format to user space based on
1186 available length*/
1187 /*The GET response may have more data than the driver can return in its
1188 buffer. In that case the buffer should be filled to the nearest complete
1189 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1190 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1191 The final buffer should end with "----\n"*/
1192
1193 /*sanity*/
1194 if (cur_len > tot_len)
1195 {
1196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1197 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1198 return 0;
1199 }
1200 else
1201 {
1202 rem_len = (tot_len - cur_len);
1203 }
1204
1205 /*end scan marker*/
1206 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1207 {
1208 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1209 pTemp += temp_len;
1210 temp_total_len += temp_len;
1211 }
1212
1213 /*bssid*/
1214 temp_len = snprintf(pTemp, sizeof(temp),
1215 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1216 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1217 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1218 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1219 pTemp += temp_len;
1220 temp_total_len += temp_len;
1221
1222 /*ssid*/
1223 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1224 pApMetaInfo->ApInfo.ssid);
1225 pTemp += temp_len;
1226 temp_total_len += temp_len;
1227
1228 /*freq*/
1229 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001230 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301231 pTemp += temp_len;
1232 temp_total_len += temp_len;
1233
1234 /*level*/
1235 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1236 pApMetaInfo->ApInfo.rssi);
1237 pTemp += temp_len;
1238 temp_total_len += temp_len;
1239
1240 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001241 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301242 pApMetaInfo->ApInfo.age);
1243 pTemp += temp_len;
1244 temp_total_len += temp_len;
1245
1246 /*dist*/
1247 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1248 pTemp += temp_len;
1249 temp_total_len += temp_len;
1250
1251 /*error*/
1252 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1253 pTemp += temp_len;
1254 temp_total_len += temp_len;
1255
1256 /*end AP marker*/
1257 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1258 pTemp += temp_len;
1259 temp_total_len += temp_len;
1260
1261 /*last AP in batch scan response*/
1262 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1263 {
1264 /*end scan marker*/
1265 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1266 pTemp += temp_len;
1267 temp_total_len += temp_len;
1268
1269 /*end batch scan result marker*/
1270 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1271 pTemp += temp_len;
1272 temp_total_len += temp_len;
1273 }
1274
1275 if (temp_total_len < rem_len)
1276 {
1277 ret = temp_total_len + 1;
1278 strlcpy(pDest, temp, ret);
1279 pAdapter->isTruncated = FALSE;
1280 }
1281 else
1282 {
1283 pAdapter->isTruncated = TRUE;
1284 if (rem_len >= strlen("%%%%"))
1285 {
1286 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1287 }
1288 {
1289 ret = 0;
1290 }
1291 }
1292
1293 return ret;
1294
1295}/*End of hdd_format_batch_scan_rsp*/
1296
1297/**---------------------------------------------------------------------------
1298
1299 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1300 buffer starting with head of hdd batch scan response queue
1301
1302 \param - pAdapter Pointer to HDD adapter
1303 \param - pDest Pointer to user data buffer
1304 \param - cur_len current offset in user buffer
1305 \param - rem_len remaining no of bytes in user buffer
1306
1307 \return - number of bytes written in user buffer
1308
1309 --------------------------------------------------------------------------*/
1310
1311tANI_U32 hdd_populate_user_batch_scan_rsp
1312(
1313 hdd_adapter_t* pAdapter,
1314 tANI_U8 *pDest,
1315 tANI_U32 cur_len,
1316 tANI_U32 rem_len
1317)
1318{
1319 tHddBatchScanRsp *pHead;
1320 tHddBatchScanRsp *pPrev;
1321 tANI_U32 len;
1322
1323 pAdapter->prev_batch_id = 0;
1324 pAdapter->isTruncated = FALSE;
1325
1326 /*head of hdd batch scan response queue*/
1327 pHead = pAdapter->pBatchScanRsp;
1328 while (pHead)
1329 {
1330 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1331 pAdapter);
1332 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001333 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301334 cur_len += len;
1335 if(TRUE == pAdapter->isTruncated)
1336 {
1337 /*result is truncated return rest of scan rsp in next req*/
1338 cur_len = rem_len;
1339 break;
1340 }
1341 pPrev = pHead;
1342 pHead = pHead->pNext;
1343 pAdapter->pBatchScanRsp = pHead;
1344 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1345 vos_mem_free(pPrev);
1346 }
1347
1348 return cur_len;
1349}/*End of hdd_populate_user_batch_scan_rsp*/
1350
1351/**---------------------------------------------------------------------------
1352
1353 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1354 scan response data from HDD queue to user space
1355 It does following in detail:
1356 a) if HDD has enough data in its queue then it 1st copies data to user
1357 space and then send get batch scan indication message to FW. In this
1358 case it does not wait on any event and batch scan response data will
1359 be populated in HDD response queue in MC thread context after receiving
1360 indication from FW
1361 b) else send get batch scan indication message to FW and wait on an event
1362 which will be set once HDD receives complete batch scan response from
1363 FW and then this function returns batch scan response to user space
1364
1365 \param - pAdapter Pointer to HDD adapter
1366 \param - pPrivData Pointer to priv_data
1367
1368 \return - 0 for success -EFAULT for failure
1369
1370 --------------------------------------------------------------------------*/
1371
1372int hdd_return_batch_scan_rsp_to_user
1373(
1374 hdd_adapter_t* pAdapter,
1375 hdd_priv_data_t *pPrivData,
1376 tANI_U8 *command
1377)
1378{
1379 tANI_U8 *pDest;
1380 tANI_U32 count = 0;
1381 tANI_U32 len = 0;
1382 tANI_U32 cur_len = 0;
1383 tANI_U32 rem_len = 0;
1384 eHalStatus halStatus;
1385 unsigned long rc;
1386 tSirTriggerBatchScanResultInd *pReq;
1387
1388 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1389 pReq->param = 0;/*batch scan client*/
1390 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1391 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1392
1393 cur_len = pPrivData->used_len;
1394 if (pPrivData->total_len > pPrivData->used_len)
1395 {
1396 rem_len = pPrivData->total_len - pPrivData->used_len;
1397 }
1398 else
1399 {
1400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1401 "%s: Invalid user data buffer total_len %d used_len %d",
1402 __func__, pPrivData->total_len, pPrivData->used_len);
1403 return -EFAULT;
1404 }
1405
1406 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1407 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1408 cur_len, rem_len);
1409 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1410
1411 /*enough scan result available in cache to return to user space or
1412 scan result needs to be fetched 1st from fw and then return*/
1413 if (len < rem_len)
1414 {
1415 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1416 halStatus = sme_TriggerBatchScanResultInd(
1417 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1418 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1419 pAdapter);
1420 if ( eHAL_STATUS_SUCCESS == halStatus )
1421 {
1422 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1423 {
1424 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1425 rc = wait_for_completion_timeout(
1426 &pAdapter->hdd_get_batch_scan_req_var,
1427 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1428 if (0 == rc)
1429 {
1430 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1431 "%s: Timeout waiting to fetch batch scan rsp from fw",
1432 __func__);
1433 return -EFAULT;
1434 }
1435 }
1436
1437 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001438 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301439 pDest += len;
1440 cur_len += len;
1441
1442 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1443 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1444 cur_len, rem_len);
1445 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1446
1447 count = 0;
1448 len = (len - pPrivData->used_len);
1449 pDest = (command + pPrivData->used_len);
1450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1451 "BATCH SCAN RESULT:");
1452 while(count < len)
1453 {
1454 printk("%c", *(pDest + count));
1455 count++;
1456 }
1457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1458 "%s: copy %d data to user buffer", __func__, len);
1459 if (copy_to_user(pPrivData->buf, pDest, len))
1460 {
1461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1462 "%s: failed to copy data to user buffer", __func__);
1463 return -EFAULT;
1464 }
1465 }
1466 else
1467 {
1468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1469 "sme_GetBatchScanScan returned failure halStatus %d",
1470 halStatus);
1471 return -EINVAL;
1472 }
1473 }
1474 else
1475 {
1476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1477 "%s: copy %d data to user buffer", __func__, len);
1478 count = 0;
1479 len = (len - pPrivData->used_len);
1480 pDest = (command + pPrivData->used_len);
1481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1482 "BATCH SCAN RESULT:");
1483 while(count < len)
1484 {
1485 printk("%c", *(pDest + count));
1486 count++;
1487 }
1488 if (copy_to_user(pPrivData->buf, pDest, len))
1489 {
1490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1491 "%s: failed to copy data to user buffer", __func__);
1492 return -EFAULT;
1493 }
1494 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1495 halStatus = sme_TriggerBatchScanResultInd(
1496 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1497 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1498 pAdapter);
1499 if ( eHAL_STATUS_SUCCESS != halStatus )
1500 {
1501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1502 "sme_GetBatchScanScan returned failure halStatus %d",
1503 halStatus);
1504 }
1505 }
1506
1507 return 0;
1508} /*End of hdd_return_batch_scan_rsp_to_user*/
1509
1510#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1511
Jeff Johnson295189b2012-06-20 16:38:30 -07001512int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1513{
1514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1515 hdd_priv_data_t priv_data;
1516 tANI_U8 *command = NULL;
1517 int ret = 0;
1518
1519 if (NULL == pAdapter)
1520 {
1521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001522 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 ret = -ENODEV;
1524 goto exit;
1525 }
1526
Jeff Johnsone7245742012-09-05 17:12:55 -07001527 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001528 {
1529 ret = -EINVAL;
1530 goto exit;
1531 }
1532
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001533 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1534 {
1535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1536 "%s:LOGP in Progress. Ignore!!!", __func__);
1537 ret = -EBUSY;
1538 goto exit;
1539 }
1540
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1542 {
1543 ret = -EFAULT;
1544 goto exit;
1545 }
1546
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001547 if (priv_data.total_len <= 0)
1548 {
1549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1550 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1551 priv_data.total_len);
1552 ret = -EINVAL;
1553 goto exit;
1554 }
1555
1556 /* Allocate +1 for '\0' */
1557 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001558 if (!command)
1559 {
1560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001561 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001562 ret = -ENOMEM;
1563 goto exit;
1564 }
1565
1566 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1567 {
1568 ret = -EFAULT;
1569 goto exit;
1570 }
1571
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001572 /* Making sure the command is NUL-terminated */
1573 command[priv_data.total_len] = '\0';
1574
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 if ((SIOCDEVPRIVATE + 1) == cmd)
1576 {
1577 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1578
1579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001580 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001581
1582 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1583 {
1584 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1585 sizeof(tSirMacAddr)))
1586 {
1587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001588 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 ret = -EFAULT;
1590 }
1591 }
Amar Singhal0974e402013-02-12 14:27:46 -08001592 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001593 {
Amar Singhal0974e402013-02-12 14:27:46 -08001594 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001596
Jeff Johnson295189b2012-06-20 16:38:30 -07001597 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001598
1599 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001600 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001601 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001602 "%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 -07001603 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001604 ret = hdd_setBand_helper(dev, ptr);
1605 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001606 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1607 {
1608 char *country_code;
1609
1610 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001611
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001612 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001613 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301614 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001615 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1616 (void *)(tSmeChangeCountryCallback)
1617 wlan_hdd_change_country_code_callback,
1618 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1619 if (eHAL_STATUS_SUCCESS == ret)
1620 {
1621 ret = wait_for_completion_interruptible_timeout(
1622 &pAdapter->change_country_code,
1623 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1624 if (0 >= ret)
1625 {
1626 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1627 __func__);
1628 }
1629 }
1630 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001631 {
1632 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001633 "%s: SME Change Country code fail ret=%d", __func__, ret);
1634 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001635 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001636
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001637 }
1638 /*
1639 command should be a string having format
1640 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1641 */
Amar Singhal0974e402013-02-12 14:27:46 -08001642 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001643 {
Amar Singhal0974e402013-02-12 14:27:46 -08001644 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001645
1646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001647 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001648
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001649 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001650 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001651 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1652 {
1653 int suspend = 0;
1654 tANI_U8 *ptr = (tANI_U8*)command + 15;
1655
1656 suspend = *ptr - '0';
1657 hdd_set_wlan_suspend_mode(suspend);
1658 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001659#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1660 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1661 {
1662 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001663 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001664 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1665 eHalStatus status = eHAL_STATUS_SUCCESS;
1666
1667 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1668 value = value + 15;
1669
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001670 /* Convert the value from ascii to integer */
1671 ret = kstrtos8(value, 10, &rssi);
1672 if (ret < 0)
1673 {
1674 /* If the input value is greater than max value of datatype, then also
1675 kstrtou8 fails */
1676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1677 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001678 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001679 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1680 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1681 ret = -EINVAL;
1682 goto exit;
1683 }
1684
Srinivas Girigowdade697412013-02-14 16:31:48 -08001685 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001686
Srinivas Girigowdade697412013-02-14 16:31:48 -08001687 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1688 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1689 {
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1691 "Neighbor lookup threshold value %d is out of range"
1692 " (Min: %d Max: %d)", lookUpThreshold,
1693 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1694 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1695 ret = -EINVAL;
1696 goto exit;
1697 }
1698
1699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1700 "%s: Received Command to Set Roam trigger"
1701 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1702
1703 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1704 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1705 if (eHAL_STATUS_SUCCESS != status)
1706 {
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: Failed to set roam trigger, try again", __func__);
1709 ret = -EPERM;
1710 goto exit;
1711 }
1712
1713 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1714 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1715 }
1716 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1717 {
1718 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1719 int rssi = (-1) * lookUpThreshold;
1720 char extra[32];
1721 tANI_U8 len = 0;
1722
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001723 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001724 if (copy_to_user(priv_data.buf, &extra, len + 1))
1725 {
1726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1727 "%s: failed to copy data to user buffer", __func__);
1728 ret = -EFAULT;
1729 goto exit;
1730 }
1731 }
1732 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1733 {
1734 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001736 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001737
Srinivas Girigowdade697412013-02-14 16:31:48 -08001738 /* input refresh period is in terms of seconds */
1739 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1740 value = value + 18;
1741 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001742 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001743 if (ret < 0)
1744 {
1745 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001746 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001748 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001749 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001750 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1751 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001756 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1757 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001758 {
1759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001760 "Roam scan period value %d is out of range"
1761 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001762 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1763 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001764 ret = -EINVAL;
1765 goto exit;
1766 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001767 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001768
1769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1770 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001771 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001772
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001773 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1774 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001775 }
1776 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1777 {
1778 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1779 char extra[32];
1780 tANI_U8 len = 0;
1781
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001782 len = scnprintf(extra, sizeof(extra), "%s %d",
1783 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001784 /* Returned value is in units of seconds */
1785 if (copy_to_user(priv_data.buf, &extra, len + 1))
1786 {
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s: failed to copy data to user buffer", __func__);
1789 ret = -EFAULT;
1790 goto exit;
1791 }
1792 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001793 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1794 {
1795 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001796 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001797 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001798
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001799 /* input refresh period is in terms of seconds */
1800 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1801 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001802
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001803 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001804 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001805 if (ret < 0)
1806 {
1807 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001808 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001810 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001811 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001812 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1813 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1814 ret = -EINVAL;
1815 goto exit;
1816 }
1817
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001818 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1819 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1820 {
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1822 "Neighbor scan results refresh period value %d is out of range"
1823 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1825 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1826 ret = -EINVAL;
1827 goto exit;
1828 }
1829 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1830
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1832 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001833 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001834
1835 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1836 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1837 }
1838 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1839 {
1840 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1841 char extra[32];
1842 tANI_U8 len = 0;
1843
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001844 len = scnprintf(extra, sizeof(extra), "%s %d",
1845 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001846 /* Returned value is in units of seconds */
1847 if (copy_to_user(priv_data.buf, &extra, len + 1))
1848 {
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: failed to copy data to user buffer", __func__);
1851 ret = -EFAULT;
1852 goto exit;
1853 }
1854 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001855#ifdef FEATURE_WLAN_LFR
1856 /* SETROAMMODE */
1857 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1858 {
1859 tANI_U8 *value = command;
1860 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1861
1862 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1863 value = value + SIZE_OF_SETROAMMODE + 1;
1864
1865 /* Convert the value from ascii to integer */
1866 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1867 if (ret < 0)
1868 {
1869 /* If the input value is greater than max value of datatype, then also
1870 kstrtou8 fails */
1871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1872 "%s: kstrtou8 failed range [%d - %d]", __func__,
1873 CFG_LFR_FEATURE_ENABLED_MIN,
1874 CFG_LFR_FEATURE_ENABLED_MAX);
1875 ret = -EINVAL;
1876 goto exit;
1877 }
1878 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1879 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1880 {
1881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1882 "Roam Mode value %d is out of range"
1883 " (Min: %d Max: %d)", roamMode,
1884 CFG_LFR_FEATURE_ENABLED_MIN,
1885 CFG_LFR_FEATURE_ENABLED_MAX);
1886 ret = -EINVAL;
1887 goto exit;
1888 }
1889
1890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1891 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1892 /*
1893 * Note that
1894 * SETROAMMODE 0 is to enable LFR while
1895 * SETROAMMODE 1 is to disable LFR, but
1896 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1897 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1898 */
1899 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1900 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1901 else
1902 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1903
1904 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1905 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1906 }
1907 /* GETROAMMODE */
1908 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1909 {
1910 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1911 char extra[32];
1912 tANI_U8 len = 0;
1913
1914 /*
1915 * roamMode value shall be inverted because the sementics is different.
1916 */
1917 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1918 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1919 else
1920 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1921
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001922 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001923 if (copy_to_user(priv_data.buf, &extra, len + 1))
1924 {
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1926 "%s: failed to copy data to user buffer", __func__);
1927 ret = -EFAULT;
1928 goto exit;
1929 }
1930 }
1931#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001932#endif
1933#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1934 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1935 {
1936 tANI_U8 *value = command;
1937 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1938
1939 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1940 value = value + 13;
1941 /* Convert the value from ascii to integer */
1942 ret = kstrtou8(value, 10, &roamRssiDiff);
1943 if (ret < 0)
1944 {
1945 /* If the input value is greater than max value of datatype, then also
1946 kstrtou8 fails */
1947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1948 "%s: kstrtou8 failed range [%d - %d]", __func__,
1949 CFG_ROAM_RSSI_DIFF_MIN,
1950 CFG_ROAM_RSSI_DIFF_MAX);
1951 ret = -EINVAL;
1952 goto exit;
1953 }
1954
1955 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1956 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1957 {
1958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1959 "Roam rssi diff value %d is out of range"
1960 " (Min: %d Max: %d)", roamRssiDiff,
1961 CFG_ROAM_RSSI_DIFF_MIN,
1962 CFG_ROAM_RSSI_DIFF_MAX);
1963 ret = -EINVAL;
1964 goto exit;
1965 }
1966
1967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1968 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1969
1970 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1971 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1972 }
1973 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1974 {
1975 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1976 char extra[32];
1977 tANI_U8 len = 0;
1978
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001979 len = scnprintf(extra, sizeof(extra), "%s %d",
1980 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001981 if (copy_to_user(priv_data.buf, &extra, len + 1))
1982 {
1983 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1984 "%s: failed to copy data to user buffer", __func__);
1985 ret = -EFAULT;
1986 goto exit;
1987 }
1988 }
1989#endif
1990#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1991 else if (strncmp(command, "GETBAND", 7) == 0)
1992 {
1993 int band = -1;
1994 char extra[32];
1995 tANI_U8 len = 0;
1996 hdd_getBand_helper(pHddCtx, &band);
1997
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001998 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001999 if (copy_to_user(priv_data.buf, &extra, len + 1))
2000 {
2001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2002 "%s: failed to copy data to user buffer", __func__);
2003 ret = -EFAULT;
2004 goto exit;
2005 }
2006 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002007 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2008 {
2009 tANI_U8 *value = command;
2010 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2011 tANI_U8 numChannels = 0;
2012 eHalStatus status = eHAL_STATUS_SUCCESS;
2013
2014 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2015 if (eHAL_STATUS_SUCCESS != status)
2016 {
2017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2018 "%s: Failed to parse channel list information", __func__);
2019 ret = -EINVAL;
2020 goto exit;
2021 }
2022
2023 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2024 {
2025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2026 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2027 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2028 ret = -EINVAL;
2029 goto exit;
2030 }
2031 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2032 numChannels);
2033 if (eHAL_STATUS_SUCCESS != status)
2034 {
2035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2036 "%s: Failed to update channel list information", __func__);
2037 ret = -EINVAL;
2038 goto exit;
2039 }
2040 }
2041 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2042 {
2043 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2044 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002045 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002046 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002047 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002048
2049 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2050 ChannelList, &numChannels ))
2051 {
2052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2053 "%s: failed to get roam scan channel list", __func__);
2054 ret = -EFAULT;
2055 goto exit;
2056 }
2057 /* output channel list is of the format
2058 [Number of roam scan channels][Channel1][Channel2]... */
2059 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002060 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002061 for (j = 0; (j < numChannels); j++)
2062 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002063 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2064 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002065 }
2066
2067 if (copy_to_user(priv_data.buf, &extra, len + 1))
2068 {
2069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2070 "%s: failed to copy data to user buffer", __func__);
2071 ret = -EFAULT;
2072 goto exit;
2073 }
2074 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002075 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2076 {
2077 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2078 char extra[32];
2079 tANI_U8 len = 0;
2080
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002081 /* Check if the features OKC/CCX/11R are supported simultaneously,
2082 then this operation is not permitted (return FAILURE) */
2083 if (ccxMode &&
2084 hdd_is_okc_mode_enabled(pHddCtx) &&
2085 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2088 "%s: OKC/CCX/11R are supported simultaneously"
2089 " hence this operation is not permitted!", __func__);
2090 ret = -EPERM;
2091 goto exit;
2092 }
2093
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002094 len = scnprintf(extra, sizeof(extra), "%s %d",
2095 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002096 if (copy_to_user(priv_data.buf, &extra, len + 1))
2097 {
2098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2099 "%s: failed to copy data to user buffer", __func__);
2100 ret = -EFAULT;
2101 goto exit;
2102 }
2103 }
2104 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2105 {
2106 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2107 char extra[32];
2108 tANI_U8 len = 0;
2109
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002110 /* Check if the features OKC/CCX/11R are supported simultaneously,
2111 then this operation is not permitted (return FAILURE) */
2112 if (okcMode &&
2113 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2114 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2117 "%s: OKC/CCX/11R are supported simultaneously"
2118 " hence this operation is not permitted!", __func__);
2119 ret = -EPERM;
2120 goto exit;
2121 }
2122
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002123 len = scnprintf(extra, sizeof(extra), "%s %d",
2124 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002125 if (copy_to_user(priv_data.buf, &extra, len + 1))
2126 {
2127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2128 "%s: failed to copy data to user buffer", __func__);
2129 ret = -EFAULT;
2130 goto exit;
2131 }
2132 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002133 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002134 {
2135 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2136 char extra[32];
2137 tANI_U8 len = 0;
2138
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002139 len = scnprintf(extra, sizeof(extra), "%s %d",
2140 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002141 if (copy_to_user(priv_data.buf, &extra, len + 1))
2142 {
2143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2144 "%s: failed to copy data to user buffer", __func__);
2145 ret = -EFAULT;
2146 goto exit;
2147 }
2148 }
2149 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2150 {
2151 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2152 char extra[32];
2153 tANI_U8 len = 0;
2154
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002155 len = scnprintf(extra, sizeof(extra), "%s %d",
2156 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002157 if (copy_to_user(priv_data.buf, &extra, len + 1))
2158 {
2159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2160 "%s: failed to copy data to user buffer", __func__);
2161 ret = -EFAULT;
2162 goto exit;
2163 }
2164 }
2165 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2166 {
2167 tANI_U8 *value = command;
2168 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2169
2170 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2171 value = value + 26;
2172 /* Convert the value from ascii to integer */
2173 ret = kstrtou8(value, 10, &minTime);
2174 if (ret < 0)
2175 {
2176 /* If the input value is greater than max value of datatype, then also
2177 kstrtou8 fails */
2178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2179 "%s: kstrtou8 failed range [%d - %d]", __func__,
2180 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2181 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2182 ret = -EINVAL;
2183 goto exit;
2184 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002185 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2186 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2187 {
2188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2189 "scan min channel time value %d is out of range"
2190 " (Min: %d Max: %d)", minTime,
2191 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2192 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2193 ret = -EINVAL;
2194 goto exit;
2195 }
2196
2197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2198 "%s: Received Command to change channel min time = %d", __func__, minTime);
2199
2200 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2201 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2202 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002203 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2204 {
2205 tANI_U8 *value = command;
2206 tANI_U8 channel = 0;
2207 tANI_U8 dwellTime = 0;
2208 tANI_U8 bufLen = 0;
2209 tANI_U8 *buf = NULL;
2210 tSirMacAddr targetApBssid;
2211 eHalStatus status = eHAL_STATUS_SUCCESS;
2212 struct ieee80211_channel chan;
2213 tANI_U8 finalLen = 0;
2214 tANI_U8 *finalBuf = NULL;
2215 tANI_U8 temp = 0;
2216 u64 cookie;
2217 hdd_station_ctx_t *pHddStaCtx = NULL;
2218 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2219
2220 /* if not associated, no need to send action frame */
2221 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2222 {
2223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2224 ret = -EINVAL;
2225 goto exit;
2226 }
2227
2228 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2229 &dwellTime, &buf, &bufLen);
2230 if (eHAL_STATUS_SUCCESS != status)
2231 {
2232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2233 "%s: Failed to parse send action frame data", __func__);
2234 ret = -EINVAL;
2235 goto exit;
2236 }
2237
2238 /* if the target bssid is different from currently associated AP,
2239 then no need to send action frame */
2240 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2241 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2242 {
2243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2244 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002245 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002246 goto exit;
2247 }
2248
2249 /* if the channel number is different from operating channel then
2250 no need to send action frame */
2251 if (channel != pHddStaCtx->conn_info.operationChannel)
2252 {
2253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2254 "%s: channel(%d) is different from operating channel(%d)",
2255 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2256 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002257 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002258 goto exit;
2259 }
2260 chan.center_freq = sme_ChnToFreq(channel);
2261
2262 finalLen = bufLen + 24;
2263 finalBuf = vos_mem_malloc(finalLen);
2264 if (NULL == finalBuf)
2265 {
2266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2267 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002268 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002269 goto exit;
2270 }
2271 vos_mem_zero(finalBuf, finalLen);
2272
2273 /* Fill subtype */
2274 temp = SIR_MAC_MGMT_ACTION << 4;
2275 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2276
2277 /* Fill type */
2278 temp = SIR_MAC_MGMT_FRAME;
2279 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2280
2281 /* Fill destination address (bssid of the AP) */
2282 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2283
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002284 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002285 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2286
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002287 /* Fill BSSID (AP mac address) */
2288 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002289
2290 /* Fill received buffer from 24th address */
2291 vos_mem_copy(finalBuf + 24, buf, bufLen);
2292
Jeff Johnson11c33152013-04-16 17:52:40 -07002293 /* done with the parsed buffer */
2294 vos_mem_free(buf);
2295
Yue Maf49ba872013-08-19 12:04:25 -07002296 wlan_hdd_action( NULL,
2297#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2298 &(pAdapter->wdev),
2299#else
2300 dev,
2301#endif
2302 &chan, 0,
2303#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2304 NL80211_CHAN_HT20, 1,
2305#endif
2306 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002307 1, &cookie );
2308 vos_mem_free(finalBuf);
2309 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002310 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2311 {
2312 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2313 char extra[32];
2314 tANI_U8 len = 0;
2315
2316 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002317 len = scnprintf(extra, sizeof(extra), "%s %d",
2318 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002319 if (copy_to_user(priv_data.buf, &extra, len + 1))
2320 {
2321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2322 "%s: failed to copy data to user buffer", __func__);
2323 ret = -EFAULT;
2324 goto exit;
2325 }
2326 }
2327 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2328 {
2329 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002330 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002331 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002332
2333 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2334 value = value + 19;
2335 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002336 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002337 if (ret < 0)
2338 {
2339 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002340 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002342 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002343 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2344 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2345 ret = -EINVAL;
2346 goto exit;
2347 }
2348
2349 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2350 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2351 {
2352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2353 "lfr mode value %d is out of range"
2354 " (Min: %d Max: %d)", maxTime,
2355 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2356 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2357 ret = -EINVAL;
2358 goto exit;
2359 }
2360
2361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2362 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2363
2364 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002365
2366 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2367 * where RFS is the RF Switching time. It is twice RFS to consider the
2368 * time to go off channel and return to the home channel. */
2369 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2370 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2371 {
2372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002373 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002374 " Hence enforcing home away time to disable (0)",
2375 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2376 homeAwayTime = 0;
2377 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2378 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2379 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002380 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2381 }
2382 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2383 {
2384 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2385 char extra[32];
2386 tANI_U8 len = 0;
2387
2388 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002389 len = scnprintf(extra, sizeof(extra), "%s %d",
2390 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002391 if (copy_to_user(priv_data.buf, &extra, len + 1))
2392 {
2393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2394 "%s: failed to copy data to user buffer", __func__);
2395 ret = -EFAULT;
2396 goto exit;
2397 }
2398 }
2399 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2400 {
2401 tANI_U8 *value = command;
2402 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2403
2404 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2405 value = value + 16;
2406 /* Convert the value from ascii to integer */
2407 ret = kstrtou16(value, 10, &val);
2408 if (ret < 0)
2409 {
2410 /* If the input value is greater than max value of datatype, then also
2411 kstrtou16 fails */
2412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2413 "%s: kstrtou16 failed range [%d - %d]", __func__,
2414 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2415 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2416 ret = -EINVAL;
2417 goto exit;
2418 }
2419
2420 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2421 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2422 {
2423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2424 "scan home time value %d is out of range"
2425 " (Min: %d Max: %d)", val,
2426 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2427 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2428 ret = -EINVAL;
2429 goto exit;
2430 }
2431
2432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2433 "%s: Received Command to change scan home time = %d", __func__, val);
2434
2435 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2436 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2437 }
2438 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2439 {
2440 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2441 char extra[32];
2442 tANI_U8 len = 0;
2443
2444 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002445 len = scnprintf(extra, sizeof(extra), "%s %d",
2446 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002447 if (copy_to_user(priv_data.buf, &extra, len + 1))
2448 {
2449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2450 "%s: failed to copy data to user buffer", __func__);
2451 ret = -EFAULT;
2452 goto exit;
2453 }
2454 }
2455 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2456 {
2457 tANI_U8 *value = command;
2458 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2459
2460 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2461 value = value + 17;
2462 /* Convert the value from ascii to integer */
2463 ret = kstrtou8(value, 10, &val);
2464 if (ret < 0)
2465 {
2466 /* If the input value is greater than max value of datatype, then also
2467 kstrtou8 fails */
2468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2469 "%s: kstrtou8 failed range [%d - %d]", __func__,
2470 CFG_ROAM_INTRA_BAND_MIN,
2471 CFG_ROAM_INTRA_BAND_MAX);
2472 ret = -EINVAL;
2473 goto exit;
2474 }
2475
2476 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2477 (val > CFG_ROAM_INTRA_BAND_MAX))
2478 {
2479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2480 "intra band mode value %d is out of range"
2481 " (Min: %d Max: %d)", val,
2482 CFG_ROAM_INTRA_BAND_MIN,
2483 CFG_ROAM_INTRA_BAND_MAX);
2484 ret = -EINVAL;
2485 goto exit;
2486 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2488 "%s: Received Command to change intra band = %d", __func__, val);
2489
2490 pHddCtx->cfg_ini->nRoamIntraBand = val;
2491 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2492 }
2493 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2494 {
2495 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2496 char extra[32];
2497 tANI_U8 len = 0;
2498
2499 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002500 len = scnprintf(extra, sizeof(extra), "%s %d",
2501 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002502 if (copy_to_user(priv_data.buf, &extra, len + 1))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2505 "%s: failed to copy data to user buffer", __func__);
2506 ret = -EFAULT;
2507 goto exit;
2508 }
2509 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002510 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2511 {
2512 tANI_U8 *value = command;
2513 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2514
2515 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2516 value = value + 15;
2517 /* Convert the value from ascii to integer */
2518 ret = kstrtou8(value, 10, &nProbes);
2519 if (ret < 0)
2520 {
2521 /* If the input value is greater than max value of datatype, then also
2522 kstrtou8 fails */
2523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2524 "%s: kstrtou8 failed range [%d - %d]", __func__,
2525 CFG_ROAM_SCAN_N_PROBES_MIN,
2526 CFG_ROAM_SCAN_N_PROBES_MAX);
2527 ret = -EINVAL;
2528 goto exit;
2529 }
2530
2531 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2532 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2533 {
2534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2535 "NProbes value %d is out of range"
2536 " (Min: %d Max: %d)", nProbes,
2537 CFG_ROAM_SCAN_N_PROBES_MIN,
2538 CFG_ROAM_SCAN_N_PROBES_MAX);
2539 ret = -EINVAL;
2540 goto exit;
2541 }
2542
2543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2544 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2545
2546 pHddCtx->cfg_ini->nProbes = nProbes;
2547 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2548 }
2549 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2550 {
2551 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2552 char extra[32];
2553 tANI_U8 len = 0;
2554
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002555 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002556 if (copy_to_user(priv_data.buf, &extra, len + 1))
2557 {
2558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2559 "%s: failed to copy data to user buffer", __func__);
2560 ret = -EFAULT;
2561 goto exit;
2562 }
2563 }
2564 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2565 {
2566 tANI_U8 *value = command;
2567 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002568 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002569
2570 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2571 /* input value is in units of msec */
2572 value = value + 20;
2573 /* Convert the value from ascii to integer */
2574 ret = kstrtou16(value, 10, &homeAwayTime);
2575 if (ret < 0)
2576 {
2577 /* If the input value is greater than max value of datatype, then also
2578 kstrtou8 fails */
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "%s: kstrtou8 failed range [%d - %d]", __func__,
2581 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2582 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2583 ret = -EINVAL;
2584 goto exit;
2585 }
2586
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002587 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2588 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2589 {
2590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2591 "homeAwayTime value %d is out of range"
2592 " (Min: %d Max: %d)", homeAwayTime,
2593 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2594 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2595 ret = -EINVAL;
2596 goto exit;
2597 }
2598
2599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2600 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2601
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002602 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2603 * where RFS is the RF Switching time. It is twice RFS to consider the
2604 * time to go off channel and return to the home channel. */
2605 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2606 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2607 {
2608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002609 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002610 " Hence enforcing home away time to disable (0)",
2611 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2612 homeAwayTime = 0;
2613 }
2614
2615 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2616 {
2617 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2618 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2619 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002620 }
2621 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2622 {
2623 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2624 char extra[32];
2625 tANI_U8 len = 0;
2626
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002627 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002628 if (copy_to_user(priv_data.buf, &extra, len + 1))
2629 {
2630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2631 "%s: failed to copy data to user buffer", __func__);
2632 ret = -EFAULT;
2633 goto exit;
2634 }
2635 }
2636 else if (strncmp(command, "REASSOC", 7) == 0)
2637 {
2638 tANI_U8 *value = command;
2639 tANI_U8 channel = 0;
2640 tSirMacAddr targetApBssid;
2641 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002642#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2643 tCsrHandoffRequest handoffInfo;
2644#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002645 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002646 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2647
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002648 /* if not associated, no need to proceed with reassoc */
2649 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2650 {
2651 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2652 ret = -EINVAL;
2653 goto exit;
2654 }
2655
2656 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2657 if (eHAL_STATUS_SUCCESS != status)
2658 {
2659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2660 "%s: Failed to parse reassoc command data", __func__);
2661 ret = -EINVAL;
2662 goto exit;
2663 }
2664
2665 /* if the target bssid is same as currently associated AP,
2666 then no need to proceed with reassoc */
2667 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2668 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2669 {
2670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2671 ret = -EINVAL;
2672 goto exit;
2673 }
2674
2675 /* Check channel number is a valid channel number */
2676 if(VOS_STATUS_SUCCESS !=
2677 wlan_hdd_validate_operation_channel(pAdapter, channel))
2678 {
2679 hddLog(VOS_TRACE_LEVEL_ERROR,
2680 "%s: Invalid Channel [%d] \n", __func__, channel);
2681 return -EINVAL;
2682 }
2683
2684 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002685#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2686 handoffInfo.channel = channel;
2687 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2688 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2689#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002690 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002691 else if (strncmp(command, "SETWESMODE", 10) == 0)
2692 {
2693 tANI_U8 *value = command;
2694 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2695
2696 /* Move pointer to ahead of SETWESMODE<delimiter> */
2697 value = value + 11;
2698 /* Convert the value from ascii to integer */
2699 ret = kstrtou8(value, 10, &wesMode);
2700 if (ret < 0)
2701 {
2702 /* If the input value is greater than max value of datatype, then also
2703 kstrtou8 fails */
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "%s: kstrtou8 failed range [%d - %d]", __func__,
2706 CFG_ENABLE_WES_MODE_NAME_MIN,
2707 CFG_ENABLE_WES_MODE_NAME_MAX);
2708 ret = -EINVAL;
2709 goto exit;
2710 }
2711
2712 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2713 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2714 {
2715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2716 "WES Mode value %d is out of range"
2717 " (Min: %d Max: %d)", wesMode,
2718 CFG_ENABLE_WES_MODE_NAME_MIN,
2719 CFG_ENABLE_WES_MODE_NAME_MAX);
2720 ret = -EINVAL;
2721 goto exit;
2722 }
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2724 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2725
2726 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2727 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2728 }
2729 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2730 {
2731 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2732 char extra[32];
2733 tANI_U8 len = 0;
2734
2735 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
2736 if (copy_to_user(priv_data.buf, &extra, len + 1))
2737 {
2738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2739 "%s: failed to copy data to user buffer", __func__);
2740 ret = -EFAULT;
2741 goto exit;
2742 }
2743 }
2744#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002745#ifdef FEATURE_WLAN_LFR
2746 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2747 {
2748 tANI_U8 *value = command;
2749 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2750
2751 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2752 value = value + 12;
2753 /* Convert the value from ascii to integer */
2754 ret = kstrtou8(value, 10, &lfrMode);
2755 if (ret < 0)
2756 {
2757 /* If the input value is greater than max value of datatype, then also
2758 kstrtou8 fails */
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2760 "%s: kstrtou8 failed range [%d - %d]", __func__,
2761 CFG_LFR_FEATURE_ENABLED_MIN,
2762 CFG_LFR_FEATURE_ENABLED_MAX);
2763 ret = -EINVAL;
2764 goto exit;
2765 }
2766
2767 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2768 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2769 {
2770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "lfr mode value %d is out of range"
2772 " (Min: %d Max: %d)", lfrMode,
2773 CFG_LFR_FEATURE_ENABLED_MIN,
2774 CFG_LFR_FEATURE_ENABLED_MAX);
2775 ret = -EINVAL;
2776 goto exit;
2777 }
2778
2779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2780 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2781
2782 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2783 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2784 }
2785#endif
2786#ifdef WLAN_FEATURE_VOWIFI_11R
2787 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2788 {
2789 tANI_U8 *value = command;
2790 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2791
2792 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2793 value = value + 18;
2794 /* Convert the value from ascii to integer */
2795 ret = kstrtou8(value, 10, &ft);
2796 if (ret < 0)
2797 {
2798 /* If the input value is greater than max value of datatype, then also
2799 kstrtou8 fails */
2800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2801 "%s: kstrtou8 failed range [%d - %d]", __func__,
2802 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2803 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2804 ret = -EINVAL;
2805 goto exit;
2806 }
2807
2808 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2809 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2810 {
2811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2812 "ft mode value %d is out of range"
2813 " (Min: %d Max: %d)", ft,
2814 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2815 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2816 ret = -EINVAL;
2817 goto exit;
2818 }
2819
2820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2821 "%s: Received Command to change ft mode = %d", __func__, ft);
2822
2823 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2824 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2825 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302826
2827 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2828 {
2829 tANI_U8 *value = command;
2830 tSirMacAddr targetApBssid;
2831 tANI_U8 trigger = 0;
2832 eHalStatus status = eHAL_STATUS_SUCCESS;
2833 hdd_station_ctx_t *pHddStaCtx = NULL;
2834 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2835
2836 /* if not associated, no need to proceed with reassoc */
2837 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2838 {
2839 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2840 ret = -EINVAL;
2841 goto exit;
2842 }
2843
2844 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2845 if (eHAL_STATUS_SUCCESS != status)
2846 {
2847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2848 "%s: Failed to parse reassoc command data", __func__);
2849 ret = -EINVAL;
2850 goto exit;
2851 }
2852
2853 /* if the target bssid is same as currently associated AP,
2854 then no need to proceed with reassoc */
2855 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2856 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2857 {
2858 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2859 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2860 __func__);
2861 ret = -EINVAL;
2862 goto exit;
2863 }
2864
2865 /* Proceed with scan/roam */
2866 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2867 &targetApBssid[0],
2868 (tSmeFastRoamTrigger)(trigger));
2869 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002870#endif
2871#ifdef FEATURE_WLAN_CCX
2872 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2873 {
2874 tANI_U8 *value = command;
2875 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2876
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002877 /* Check if the features OKC/CCX/11R are supported simultaneously,
2878 then this operation is not permitted (return FAILURE) */
2879 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2880 hdd_is_okc_mode_enabled(pHddCtx) &&
2881 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2882 {
2883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2884 "%s: OKC/CCX/11R are supported simultaneously"
2885 " hence this operation is not permitted!", __func__);
2886 ret = -EPERM;
2887 goto exit;
2888 }
2889
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002890 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2891 value = value + 11;
2892 /* Convert the value from ascii to integer */
2893 ret = kstrtou8(value, 10, &ccxMode);
2894 if (ret < 0)
2895 {
2896 /* If the input value is greater than max value of datatype, then also
2897 kstrtou8 fails */
2898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2899 "%s: kstrtou8 failed range [%d - %d]", __func__,
2900 CFG_CCX_FEATURE_ENABLED_MIN,
2901 CFG_CCX_FEATURE_ENABLED_MAX);
2902 ret = -EINVAL;
2903 goto exit;
2904 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002905 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2906 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2907 {
2908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2909 "Ccx mode value %d is out of range"
2910 " (Min: %d Max: %d)", ccxMode,
2911 CFG_CCX_FEATURE_ENABLED_MIN,
2912 CFG_CCX_FEATURE_ENABLED_MAX);
2913 ret = -EINVAL;
2914 goto exit;
2915 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2917 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2918
2919 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2920 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2921 }
2922#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002923 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2924 {
2925 tANI_U8 *value = command;
2926 tANI_BOOLEAN roamScanControl = 0;
2927
2928 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2929 value = value + 19;
2930 /* Convert the value from ascii to integer */
2931 ret = kstrtou8(value, 10, &roamScanControl);
2932 if (ret < 0)
2933 {
2934 /* If the input value is greater than max value of datatype, then also
2935 kstrtou8 fails */
2936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2937 "%s: kstrtou8 failed ", __func__);
2938 ret = -EINVAL;
2939 goto exit;
2940 }
2941
2942 if (0 != roamScanControl)
2943 {
2944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2945 "roam scan control invalid value = %d",
2946 roamScanControl);
2947 ret = -EINVAL;
2948 goto exit;
2949 }
2950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2951 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2952
2953 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2954 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002955#ifdef FEATURE_WLAN_OKC
2956 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2957 {
2958 tANI_U8 *value = command;
2959 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2960
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002961 /* Check if the features OKC/CCX/11R are supported simultaneously,
2962 then this operation is not permitted (return FAILURE) */
2963 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2964 hdd_is_okc_mode_enabled(pHddCtx) &&
2965 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2966 {
2967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2968 "%s: OKC/CCX/11R are supported simultaneously"
2969 " hence this operation is not permitted!", __func__);
2970 ret = -EPERM;
2971 goto exit;
2972 }
2973
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002974 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2975 value = value + 11;
2976 /* Convert the value from ascii to integer */
2977 ret = kstrtou8(value, 10, &okcMode);
2978 if (ret < 0)
2979 {
2980 /* If the input value is greater than max value of datatype, then also
2981 kstrtou8 fails */
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2983 "%s: kstrtou8 failed range [%d - %d]", __func__,
2984 CFG_OKC_FEATURE_ENABLED_MIN,
2985 CFG_OKC_FEATURE_ENABLED_MAX);
2986 ret = -EINVAL;
2987 goto exit;
2988 }
2989
2990 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2991 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2992 {
2993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2994 "Okc mode value %d is out of range"
2995 " (Min: %d Max: %d)", okcMode,
2996 CFG_OKC_FEATURE_ENABLED_MIN,
2997 CFG_OKC_FEATURE_ENABLED_MAX);
2998 ret = -EINVAL;
2999 goto exit;
3000 }
3001
3002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3003 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3004
3005 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3006 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003007#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003008 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3009 {
3010 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3011 char extra[32];
3012 tANI_U8 len = 0;
3013
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003014 len = scnprintf(extra, sizeof(extra), "%s %d",
3015 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003016 if (copy_to_user(priv_data.buf, &extra, len + 1))
3017 {
3018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3019 "%s: failed to copy data to user buffer", __func__);
3020 ret = -EFAULT;
3021 goto exit;
3022 }
3023 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303024#ifdef WLAN_FEATURE_PACKET_FILTERING
3025 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3026 {
3027 tANI_U8 filterType = 0;
3028 tANI_U8 *value = command;
3029
3030 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3031 value = value + 22;
3032
3033 /* Convert the value from ascii to integer */
3034 ret = kstrtou8(value, 10, &filterType);
3035 if (ret < 0)
3036 {
3037 /* If the input value is greater than max value of datatype,
3038 * then also kstrtou8 fails
3039 */
3040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3041 "%s: kstrtou8 failed range ", __func__);
3042 ret = -EINVAL;
3043 goto exit;
3044 }
3045
3046 if (filterType != 0 && filterType != 1)
3047 {
3048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3049 "%s: Accepted Values are 0 and 1 ", __func__);
3050 ret = -EINVAL;
3051 goto exit;
3052 }
3053 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3054 pAdapter->sessionId);
3055 }
3056#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303057 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3058 {
3059 char *dhcpPhase;
3060 dhcpPhase = command + 12;
3061 if ('1' == *dhcpPhase)
3062 {
3063 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3064 pAdapter->macAddressCurrent.bytes);
3065 }
3066 else if ('2' == *dhcpPhase)
3067 {
3068 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3069 pAdapter->macAddressCurrent.bytes);
3070 }
3071 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003072 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3073 {
3074 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3075 }
3076 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3077 {
3078 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3079 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303080 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3081 {
3082 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3083 char extra[32];
3084 tANI_U8 len = 0;
3085
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003086 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303087 (int)pCfg->nActiveMaxChnTime);
3088 if (copy_to_user(priv_data.buf, &extra, len + 1))
3089 {
3090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3091 "%s: failed to copy data to user buffer", __func__);
3092 ret = -EFAULT;
3093 goto exit;
3094 }
3095 ret = len;
3096 }
3097 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3098 {
3099 tANI_U8 *value = command;
3100 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3101 int val = 0, temp;
3102
3103 value = value + 13;
3104 temp = kstrtou32(value, 10, &val);
3105 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3106 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3107 {
3108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3109 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3110 ret = -EFAULT;
3111 goto exit;
3112 }
3113 pCfg->nActiveMaxChnTime = val;
3114 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003115 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3116 {
3117 tANI_U8 filterType = 0;
3118 tANI_U8 *value;
3119 value = command + 9;
3120
3121 /* Convert the value from ascii to integer */
3122 ret = kstrtou8(value, 10, &filterType);
3123 if (ret < 0)
3124 {
3125 /* If the input value is greater than max value of datatype,
3126 * then also kstrtou8 fails
3127 */
3128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3129 "%s: kstrtou8 failed range ", __func__);
3130 ret = -EINVAL;
3131 goto exit;
3132 }
3133 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3134 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3135 {
3136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3137 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3138 " 2-Sink ", __func__);
3139 ret = -EINVAL;
3140 goto exit;
3141 }
3142 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3143 pHddCtx->drvr_miracast = filterType;
3144 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3145 }
Leo Chang614d2072013-08-22 14:59:44 -07003146 else if (strncmp(command, "SETMCRATE", 9) == 0)
3147 {
3148 int rc;
3149 tANI_U8 *value = command;
3150 int targetRate;
3151
3152 /* Only valid for SAP mode */
3153 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3154 {
3155 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3156 "%s: SAP mode is not running", __func__);
3157 ret = -EFAULT;
3158 goto exit;
3159 }
3160
3161 /* Move pointer to ahead of SETMCRATE<delimiter> */
3162 /* input value is in units of hundred kbps */
3163 value = value + 10;
3164 /* Convert the value from ascii to integer, decimal base */
3165 ret = kstrtouint(value, 10, &targetRate);
3166
3167 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3168 if (rc)
3169 {
3170 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3171 "%s: Set MC Rate Fail %d", __func__, rc);
3172 ret = -EFAULT;
3173 goto exit;
3174 }
3175 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303176#ifdef FEATURE_WLAN_BATCH_SCAN
3177 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3178 {
3179 char extra[32];
3180 tANI_U8 len = 0;
3181 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3182
3183 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3184 {
3185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3186 "%s: Batch scan feature is not supported by FW", __func__);
3187 ret = -EINVAL;
3188 goto exit;
3189 }
3190
3191 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3192 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3193 {
3194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3195 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3196 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3197 " mode",
3198 pAdapter->device_mode);
3199 ret = -EINVAL;
3200 goto exit;
3201 }
3202
3203 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3204 version);
3205 if (copy_to_user(priv_data.buf, &extra, len + 1))
3206 {
3207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3208 "%s: failed to copy data to user buffer", __func__);
3209 ret = -EFAULT;
3210 goto exit;
3211 }
3212 ret = HDD_BATCH_SCAN_VERSION;
3213 }
3214 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3215 {
3216 int status;
3217 tANI_U8 *value = (command + 16);
3218 eHalStatus halStatus;
3219 unsigned long rc;
3220 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3221 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3222
3223 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3224 {
3225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3226 "%s: Batch scan feature is not supported by FW", __func__);
3227 ret = -EINVAL;
3228 goto exit;
3229 }
3230
Rajeev Kumar20140c12013-10-21 19:39:02 -07003231
Rajeev79dbe4c2013-10-05 11:03:42 +05303232 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3233 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3234 {
3235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003236 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303237 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3238 pAdapter->device_mode);
3239 ret = -EINVAL;
3240 goto exit;
3241 }
3242
Rajeev Kumar20140c12013-10-21 19:39:02 -07003243
Rajeev79dbe4c2013-10-05 11:03:42 +05303244 status = hdd_parse_set_batchscan_command(value, pReq);
3245 if (status)
3246 {
3247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003248 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303249 ret = -EINVAL;
3250 goto exit;
3251 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003252
3253
Rajeev79dbe4c2013-10-05 11:03:42 +05303254 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3255 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3256 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3257 pAdapter);
3258
3259 if ( eHAL_STATUS_SUCCESS == halStatus )
3260 {
3261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3262 "sme_SetBatchScanReq returned success halStatus %d",
3263 halStatus);
3264 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3265 {
3266 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3267 rc = wait_for_completion_timeout(
3268 &pAdapter->hdd_set_batch_scan_req_var,
3269 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3270 if (0 == rc)
3271 {
3272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3273 "%s: Timeout waiting for set batch scan to complete",
3274 __func__);
3275 ret = -EINVAL;
3276 goto exit;
3277 }
3278 }
3279 if ( !pRsp->nScansToBatch )
3280 {
3281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003283 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303284 ret = -EINVAL;
3285 goto exit;
3286 }
3287 /*As per the Batch Scan Framework API we should return the MIN of
3288 either MSCAN or the max # of scans firmware can cache*/
3289 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3290
Rajeev Kumar20140c12013-10-21 19:39:02 -07003291 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3292
Rajeev79dbe4c2013-10-05 11:03:42 +05303293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3294 "%s: request MSCAN %d response MSCAN %d ret %d",
3295 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3296 }
3297 else
3298 {
3299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3300 "sme_SetBatchScanReq returned failure halStatus %d",
3301 halStatus);
3302 ret = -EINVAL;
3303 goto exit;
3304 }
3305 }
3306 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3307 {
3308 eHalStatus halStatus;
3309 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3310 pInd->param = 0;
3311
3312 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3313 {
3314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3315 "%s: Batch scan feature is not supported by FW", __func__);
3316 ret = -EINVAL;
3317 goto exit;
3318 }
3319
Rajeev Kumar20140c12013-10-21 19:39:02 -07003320 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303321 {
3322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003323 "Batch scan is not yet enabled batch scan state %d",
3324 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303325 ret = -EINVAL;
3326 goto exit;
3327 }
3328
Rajeev Kumar20140c12013-10-21 19:39:02 -07003329 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3330
Rajeev79dbe4c2013-10-05 11:03:42 +05303331 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3332 pAdapter->sessionId);
3333 if ( eHAL_STATUS_SUCCESS == halStatus )
3334 {
3335 ret = 0;
3336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3337 "sme_StopBatchScanInd returned success halStatus %d",
3338 halStatus);
3339 }
3340 else
3341 {
3342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3343 "sme_StopBatchScanInd returned failure halStatus %d",
3344 halStatus);
3345 ret = -EINVAL;
3346 goto exit;
3347 }
3348 }
3349 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3350 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003351 tANI_U32 remain_len;
3352
Rajeev79dbe4c2013-10-05 11:03:42 +05303353 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3354 {
3355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3356 "%s: Batch scan feature is not supported by FW", __func__);
3357 ret = -EINVAL;
3358 goto exit;
3359 }
3360
Rajeev Kumar20140c12013-10-21 19:39:02 -07003361 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303362 {
3363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003364 "Batch scan is not yet enabled could not return results"
3365 "Batch Scan state %d",
3366 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303367 ret = -EINVAL;
3368 goto exit;
3369 }
3370
3371 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003372 remain_len = priv_data.total_len - priv_data.used_len;
3373 if (remain_len < priv_data.total_len)
3374 {
3375 /*Clear previous batch scan response data if any*/
3376 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3377 }
3378 else
3379 {
3380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3381 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003382 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003383 priv_data.total_len, priv_data.used_len, remain_len);
3384 ret = -EINVAL;
3385 goto exit;
3386 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303387 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3388 }
3389#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003390#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3391 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3392 {
3393 tANI_U8 *value = command;
3394 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3395 tANI_U8 numChannels = 0;
3396 eHalStatus status = eHAL_STATUS_SUCCESS;
3397
3398 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3399 if (eHAL_STATUS_SUCCESS != status)
3400 {
3401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3402 "%s: Failed to parse channel list information", __func__);
3403 ret = -EINVAL;
3404 goto exit;
3405 }
3406
3407 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3408 {
3409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3411 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3416 ChannelList,
3417 numChannels);
3418 if (eHAL_STATUS_SUCCESS != status)
3419 {
3420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3421 "%s: Failed to update channel list information", __func__);
3422 ret = -EINVAL;
3423 goto exit;
3424 }
3425 }
3426 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3427 {
3428 tANI_U8 *value = command;
3429 char extra[128] = {0};
3430 int len = 0;
3431 tANI_U8 tid = 0;
3432 hdd_station_ctx_t *pHddStaCtx = NULL;
3433 tAniTrafStrmMetrics tsmMetrics;
3434 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3435
3436 /* if not associated, return error */
3437 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3438 {
3439 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3440 ret = -EINVAL;
3441 goto exit;
3442 }
3443
3444 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3445 value = value + 12;
3446 /* Convert the value from ascii to integer */
3447 ret = kstrtou8(value, 10, &tid);
3448 if (ret < 0)
3449 {
3450 /* If the input value is greater than max value of datatype, then also
3451 kstrtou8 fails */
3452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3453 "%s: kstrtou8 failed range [%d - %d]", __func__,
3454 TID_MIN_VALUE,
3455 TID_MAX_VALUE);
3456 ret = -EINVAL;
3457 goto exit;
3458 }
3459
3460 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3461 {
3462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3463 "tid value %d is out of range"
3464 " (Min: %d Max: %d)", tid,
3465 TID_MIN_VALUE,
3466 TID_MAX_VALUE);
3467 ret = -EINVAL;
3468 goto exit;
3469 }
3470
3471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3472 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3473
3474 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3475 {
3476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3477 "%s: failed to get tsm stats", __func__);
3478 ret = -EFAULT;
3479 goto exit;
3480 }
3481
3482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3483 "UplinkPktQueueDly(%d)\n"
3484 "UplinkPktQueueDlyHist[0](%d)\n"
3485 "UplinkPktQueueDlyHist[1](%d)\n"
3486 "UplinkPktQueueDlyHist[2](%d)\n"
3487 "UplinkPktQueueDlyHist[3](%d)\n"
3488 "UplinkPktTxDly(%lu)\n"
3489 "UplinkPktLoss(%d)\n"
3490 "UplinkPktCount(%d)\n"
3491 "RoamingCount(%d)\n"
3492 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3493 tsmMetrics.UplinkPktQueueDlyHist[0],
3494 tsmMetrics.UplinkPktQueueDlyHist[1],
3495 tsmMetrics.UplinkPktQueueDlyHist[2],
3496 tsmMetrics.UplinkPktQueueDlyHist[3],
3497 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3498 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3499
3500 /* Output TSM stats is of the format
3501 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3502 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3503 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3504 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3505 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3506 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3507 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3508 tsmMetrics.RoamingDly);
3509
3510 if (copy_to_user(priv_data.buf, &extra, len + 1))
3511 {
3512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3513 "%s: failed to copy data to user buffer", __func__);
3514 ret = -EFAULT;
3515 goto exit;
3516 }
3517 }
3518 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3519 {
3520 tANI_U8 *value = command;
3521 tANI_U8 *cckmIe = NULL;
3522 tANI_U8 cckmIeLen = 0;
3523 eHalStatus status = eHAL_STATUS_SUCCESS;
3524
3525 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3526 if (eHAL_STATUS_SUCCESS != status)
3527 {
3528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3529 "%s: Failed to parse cckm ie data", __func__);
3530 ret = -EINVAL;
3531 goto exit;
3532 }
3533
3534 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3535 {
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3537 "%s: CCKM Ie input length is more than max[%d]", __func__,
3538 DOT11F_IE_RSN_MAX_LEN);
3539 if (NULL != cckmIe)
3540 {
3541 vos_mem_free(cckmIe);
3542 }
3543 ret = -EINVAL;
3544 goto exit;
3545 }
3546 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3547 if (NULL != cckmIe)
3548 {
3549 vos_mem_free(cckmIe);
3550 }
3551 }
3552#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003553 else {
3554 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3555 __func__, command);
3556 }
3557
Jeff Johnson295189b2012-06-20 16:38:30 -07003558 }
3559exit:
3560 if (command)
3561 {
3562 kfree(command);
3563 }
3564 return ret;
3565}
3566
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003567
3568
3569#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3570static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3571{
3572 struct statsContext *pStatsContext = NULL;
3573 hdd_adapter_t *pAdapter = NULL;
3574
3575 if (NULL == pContext)
3576 {
3577 hddLog(VOS_TRACE_LEVEL_ERROR,
3578 "%s: Bad param, pContext [%p]",
3579 __func__, pContext);
3580 return;
3581 }
3582
3583 /* there is a race condition that exists between this callback function
3584 and the caller since the caller could time out either before or
3585 while this code is executing. we'll assume the timeout hasn't
3586 occurred, but we'll verify that right before we save our work */
3587
3588 pStatsContext = pContext;
3589 pAdapter = pStatsContext->pAdapter;
3590 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3591 {
3592 /* the caller presumably timed out so there is nothing we can do */
3593 hddLog(VOS_TRACE_LEVEL_WARN,
3594 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3595 __func__, pAdapter, pStatsContext->magic);
3596 return;
3597 }
3598
3599 /* the race is on. caller could have timed out immediately after
3600 we verified the magic, but if so, caller will wait a short time
3601 for us to copy over the tsm stats */
3602 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3603 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3604 tsmMetrics.UplinkPktQueueDlyHist,
3605 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3606 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3607 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3608 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3609 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3610 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3611 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3612
3613 /* and notify the caller */
3614 complete(&pStatsContext->completion);
3615}
3616
3617
3618
3619static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3620 tAniTrafStrmMetrics* pTsmMetrics)
3621{
3622 hdd_station_ctx_t *pHddStaCtx = NULL;
3623 eHalStatus hstatus;
3624 long lrc;
3625 struct statsContext context;
3626 hdd_context_t *pHddCtx = NULL;
3627
3628 if (NULL == pAdapter)
3629 {
3630 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3631 return VOS_STATUS_E_FAULT;
3632 }
3633
3634 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3635 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3636
3637 /* we are connected prepare our callback context */
3638 init_completion(&context.completion);
3639 context.pAdapter = pAdapter;
3640 context.magic = STATS_CONTEXT_MAGIC;
3641
3642 /* query tsm stats */
3643 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3644 pHddStaCtx->conn_info.staId[ 0 ],
3645 pHddStaCtx->conn_info.bssId,
3646 &context, pHddCtx->pvosContext, tid);
3647
3648 if (eHAL_STATUS_SUCCESS != hstatus)
3649 {
3650 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3651 return hstatus;
3652 }
3653 else
3654 {
3655 /* request was sent -- wait for the response */
3656 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3657 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3658 /* either we have a response or we timed out
3659 either way, first invalidate our magic */
3660 context.magic = 0;
3661 if (lrc <= 0)
3662 {
3663 hddLog(VOS_TRACE_LEVEL_ERROR,
3664 "%s: SME %s while retrieving statistics",
3665 __func__, (0 == lrc) ? "timeout" : "interrupt");
3666 /* there is a race condition such that the callback
3667 function could be executing at the same time we are. of
3668 primary concern is if the callback function had already
3669 verified the "magic" but hasn't yet set the completion
3670 variable. Since the completion variable is on our
3671 stack, we'll delay just a bit to make sure the data is
3672 still valid if that is the case */
3673 msleep(50);
3674 return (VOS_STATUS_E_TIMEOUT);
3675 }
3676 }
3677 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3678 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3679 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3680 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3681 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3682 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3683 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3684 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3685 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3686 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3687
3688 return VOS_STATUS_SUCCESS;
3689}
3690#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3691
Srinivas Girigowdade697412013-02-14 16:31:48 -08003692#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3693void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3694{
3695 eCsrBand band = -1;
3696 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3697 switch (band)
3698 {
3699 case eCSR_BAND_ALL:
3700 *pBand = WLAN_HDD_UI_BAND_AUTO;
3701 break;
3702
3703 case eCSR_BAND_24:
3704 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3705 break;
3706
3707 case eCSR_BAND_5G:
3708 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3709 break;
3710
3711 default:
3712 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3713 *pBand = -1;
3714 break;
3715 }
3716}
3717
3718/**---------------------------------------------------------------------------
3719
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003720 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3721
3722 This function parses the send action frame data passed in the format
3723 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3724
Srinivas Girigowda56076852013-08-20 14:00:50 -07003725 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003726 \param - pTargetApBssid Pointer to target Ap bssid
3727 \param - pChannel Pointer to the Target AP channel
3728 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3729 \param - pBuf Pointer to data
3730 \param - pBufLen Pointer to data length
3731
3732 \return - 0 for success non-zero for failure
3733
3734 --------------------------------------------------------------------------*/
3735VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3736 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3737{
3738 tANI_U8 *inPtr = pValue;
3739 tANI_U8 *dataEnd;
3740 int tempInt;
3741 int j = 0;
3742 int i = 0;
3743 int v = 0;
3744 tANI_U8 tempBuf[32];
3745 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003746 /* 12 hexa decimal digits and 5 ':' */
3747 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003748
3749 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3750 /*no argument after the command*/
3751 if (NULL == inPtr)
3752 {
3753 return -EINVAL;
3754 }
3755
3756 /*no space after the command*/
3757 else if (SPACE_ASCII_VALUE != *inPtr)
3758 {
3759 return -EINVAL;
3760 }
3761
3762 /*removing empty spaces*/
3763 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3764
3765 /*no argument followed by spaces*/
3766 if ('\0' == *inPtr)
3767 {
3768 return -EINVAL;
3769 }
3770
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003771 v = sscanf(inPtr, "%17s", macAddress);
3772 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003773 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3775 "Invalid MAC address or All hex inputs are not read (%d)", v);
3776 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003777 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003778
3779 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3780 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3781 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3782 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3783 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3784 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003785
3786 /* point to the next argument */
3787 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3788 /*no argument after the command*/
3789 if (NULL == inPtr) return -EINVAL;
3790
3791 /*removing empty spaces*/
3792 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3793
3794 /*no argument followed by spaces*/
3795 if ('\0' == *inPtr)
3796 {
3797 return -EINVAL;
3798 }
3799
3800 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003801 v = sscanf(inPtr, "%32s ", tempBuf);
3802 if (1 != v) return -EINVAL;
3803
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003804 v = kstrtos32(tempBuf, 10, &tempInt);
3805 if ( v < 0) return -EINVAL;
3806
3807 *pChannel = tempInt;
3808
3809 /* point to the next argument */
3810 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3811 /*no argument after the command*/
3812 if (NULL == inPtr) return -EINVAL;
3813 /*removing empty spaces*/
3814 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3815
3816 /*no argument followed by spaces*/
3817 if ('\0' == *inPtr)
3818 {
3819 return -EINVAL;
3820 }
3821
3822 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003823 v = sscanf(inPtr, "%32s ", tempBuf);
3824 if (1 != v) return -EINVAL;
3825
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003826 v = kstrtos32(tempBuf, 10, &tempInt);
3827 if ( v < 0) return -EINVAL;
3828
3829 *pDwellTime = tempInt;
3830
3831 /* point to the next argument */
3832 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3833 /*no argument after the command*/
3834 if (NULL == inPtr) return -EINVAL;
3835 /*removing empty spaces*/
3836 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3837
3838 /*no argument followed by spaces*/
3839 if ('\0' == *inPtr)
3840 {
3841 return -EINVAL;
3842 }
3843
3844 /* find the length of data */
3845 dataEnd = inPtr;
3846 while(('\0' != *dataEnd) )
3847 {
3848 dataEnd++;
3849 ++(*pBufLen);
3850 }
3851 if ( *pBufLen <= 0) return -EINVAL;
3852
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003853 /* Allocate the number of bytes based on the number of input characters
3854 whether it is even or odd.
3855 if the number of input characters are even, then we need N/2 byte.
3856 if the number of input characters are odd, then we need do (N+1)/2 to
3857 compensate rounding off.
3858 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3859 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3860 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003861 if (NULL == *pBuf)
3862 {
3863 hddLog(VOS_TRACE_LEVEL_FATAL,
3864 "%s: vos_mem_alloc failed ", __func__);
3865 return -EINVAL;
3866 }
3867
3868 /* the buffer received from the upper layer is character buffer,
3869 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3870 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3871 and f0 in 3rd location */
3872 for (i = 0, j = 0; j < *pBufLen; j += 2)
3873 {
3874 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3875 (*pBuf)[i++] = tempByte;
3876 }
3877 *pBufLen = i;
3878 return VOS_STATUS_SUCCESS;
3879}
3880
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003881/**---------------------------------------------------------------------------
3882
Srinivas Girigowdade697412013-02-14 16:31:48 -08003883 \brief hdd_parse_channellist() - HDD Parse channel list
3884
3885 This function parses the channel list passed in the format
3886 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003887 if the Number of channels (N) does not match with the actual number of channels passed
3888 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3889 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3890 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3891 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003892
3893 \param - pValue Pointer to input channel list
3894 \param - ChannelList Pointer to local output array to record channel list
3895 \param - pNumChannels Pointer to number of roam scan channels
3896
3897 \return - 0 for success non-zero for failure
3898
3899 --------------------------------------------------------------------------*/
3900VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3901{
3902 tANI_U8 *inPtr = pValue;
3903 int tempInt;
3904 int j = 0;
3905 int v = 0;
3906 char buf[32];
3907
3908 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3909 /*no argument after the command*/
3910 if (NULL == inPtr)
3911 {
3912 return -EINVAL;
3913 }
3914
3915 /*no space after the command*/
3916 else if (SPACE_ASCII_VALUE != *inPtr)
3917 {
3918 return -EINVAL;
3919 }
3920
3921 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003922 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003923
3924 /*no argument followed by spaces*/
3925 if ('\0' == *inPtr)
3926 {
3927 return -EINVAL;
3928 }
3929
3930 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003931 v = sscanf(inPtr, "%32s ", buf);
3932 if (1 != v) return -EINVAL;
3933
Srinivas Girigowdade697412013-02-14 16:31:48 -08003934 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003935 if ((v < 0) ||
3936 (tempInt <= 0) ||
3937 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3938 {
3939 return -EINVAL;
3940 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003941
3942 *pNumChannels = tempInt;
3943
3944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3945 "Number of channels are: %d", *pNumChannels);
3946
3947 for (j = 0; j < (*pNumChannels); j++)
3948 {
3949 /*inPtr pointing to the beginning of first space after number of channels*/
3950 inPtr = strpbrk( inPtr, " " );
3951 /*no channel list after the number of channels argument*/
3952 if (NULL == inPtr)
3953 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003954 if (0 != j)
3955 {
3956 *pNumChannels = j;
3957 return VOS_STATUS_SUCCESS;
3958 }
3959 else
3960 {
3961 return -EINVAL;
3962 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003963 }
3964
3965 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003966 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003967
3968 /*no channel list after the number of channels argument and spaces*/
3969 if ( '\0' == *inPtr )
3970 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003971 if (0 != j)
3972 {
3973 *pNumChannels = j;
3974 return VOS_STATUS_SUCCESS;
3975 }
3976 else
3977 {
3978 return -EINVAL;
3979 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003980 }
3981
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003982 v = sscanf(inPtr, "%32s ", buf);
3983 if (1 != v) return -EINVAL;
3984
Srinivas Girigowdade697412013-02-14 16:31:48 -08003985 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003986 if ((v < 0) ||
3987 (tempInt <= 0) ||
3988 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3989 {
3990 return -EINVAL;
3991 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003992 pChannelList[j] = tempInt;
3993
3994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3995 "Channel %d added to preferred channel list",
3996 pChannelList[j] );
3997 }
3998
Srinivas Girigowdade697412013-02-14 16:31:48 -08003999 return VOS_STATUS_SUCCESS;
4000}
4001
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004002
4003/**---------------------------------------------------------------------------
4004
4005 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4006
4007 This function parses the reasoc command data passed in the format
4008 REASSOC<space><bssid><space><channel>
4009
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004010 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004011 \param - pTargetApBssid Pointer to target Ap bssid
4012 \param - pChannel Pointer to the Target AP channel
4013
4014 \return - 0 for success non-zero for failure
4015
4016 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004017VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4018 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004019{
4020 tANI_U8 *inPtr = pValue;
4021 int tempInt;
4022 int v = 0;
4023 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004024 /* 12 hexa decimal digits and 5 ':' */
4025 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004026
4027 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4028 /*no argument after the command*/
4029 if (NULL == inPtr)
4030 {
4031 return -EINVAL;
4032 }
4033
4034 /*no space after the command*/
4035 else if (SPACE_ASCII_VALUE != *inPtr)
4036 {
4037 return -EINVAL;
4038 }
4039
4040 /*removing empty spaces*/
4041 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4042
4043 /*no argument followed by spaces*/
4044 if ('\0' == *inPtr)
4045 {
4046 return -EINVAL;
4047 }
4048
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004049 v = sscanf(inPtr, "%17s", macAddress);
4050 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004051 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4053 "Invalid MAC address or All hex inputs are not read (%d)", v);
4054 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004055 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004056
4057 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4058 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4059 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4060 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4061 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4062 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004063
4064 /* point to the next argument */
4065 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4066 /*no argument after the command*/
4067 if (NULL == inPtr) return -EINVAL;
4068
4069 /*removing empty spaces*/
4070 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4071
4072 /*no argument followed by spaces*/
4073 if ('\0' == *inPtr)
4074 {
4075 return -EINVAL;
4076 }
4077
4078 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004079 v = sscanf(inPtr, "%32s ", tempBuf);
4080 if (1 != v) return -EINVAL;
4081
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004082 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004083 if ((v < 0) ||
4084 (tempInt <= 0) ||
4085 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4086 {
4087 return -EINVAL;
4088 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004089
4090 *pChannel = tempInt;
4091 return VOS_STATUS_SUCCESS;
4092}
4093
4094#endif
4095
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004096#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4097/**---------------------------------------------------------------------------
4098
4099 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4100
4101 This function parses the SETCCKM IE command
4102 SETCCKMIE<space><ie data>
4103
4104 \param - pValue Pointer to input data
4105 \param - pCckmIe Pointer to output cckm Ie
4106 \param - pCckmIeLen Pointer to output cckm ie length
4107
4108 \return - 0 for success non-zero for failure
4109
4110 --------------------------------------------------------------------------*/
4111VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4112 tANI_U8 *pCckmIeLen)
4113{
4114 tANI_U8 *inPtr = pValue;
4115 tANI_U8 *dataEnd;
4116 int j = 0;
4117 int i = 0;
4118 tANI_U8 tempByte = 0;
4119
4120 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4121 /*no argument after the command*/
4122 if (NULL == inPtr)
4123 {
4124 return -EINVAL;
4125 }
4126
4127 /*no space after the command*/
4128 else if (SPACE_ASCII_VALUE != *inPtr)
4129 {
4130 return -EINVAL;
4131 }
4132
4133 /*removing empty spaces*/
4134 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4135
4136 /*no argument followed by spaces*/
4137 if ('\0' == *inPtr)
4138 {
4139 return -EINVAL;
4140 }
4141
4142 /* find the length of data */
4143 dataEnd = inPtr;
4144 while(('\0' != *dataEnd) )
4145 {
4146 dataEnd++;
4147 ++(*pCckmIeLen);
4148 }
4149 if ( *pCckmIeLen <= 0) return -EINVAL;
4150
4151 /* Allocate the number of bytes based on the number of input characters
4152 whether it is even or odd.
4153 if the number of input characters are even, then we need N/2 byte.
4154 if the number of input characters are odd, then we need do (N+1)/2 to
4155 compensate rounding off.
4156 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4157 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4158 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4159 if (NULL == *pCckmIe)
4160 {
4161 hddLog(VOS_TRACE_LEVEL_FATAL,
4162 "%s: vos_mem_alloc failed ", __func__);
4163 return -EINVAL;
4164 }
4165 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4166 /* the buffer received from the upper layer is character buffer,
4167 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4168 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4169 and f0 in 3rd location */
4170 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4171 {
4172 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4173 (*pCckmIe)[i++] = tempByte;
4174 }
4175 *pCckmIeLen = i;
4176
4177 return VOS_STATUS_SUCCESS;
4178}
4179#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4180
Jeff Johnson295189b2012-06-20 16:38:30 -07004181/**---------------------------------------------------------------------------
4182
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004183 \brief hdd_is_valid_mac_address() - Validate MAC address
4184
4185 This function validates whether the given MAC address is valid or not
4186 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4187 where X is the hexa decimal digit character and separated by ':'
4188 This algorithm works even if MAC address is not separated by ':'
4189
4190 This code checks given input string mac contains exactly 12 hexadecimal digits.
4191 and a separator colon : appears in the input string only after
4192 an even number of hex digits.
4193
4194 \param - pMacAddr pointer to the input MAC address
4195 \return - 1 for valid and 0 for invalid
4196
4197 --------------------------------------------------------------------------*/
4198
4199v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4200{
4201 int xdigit = 0;
4202 int separator = 0;
4203 while (*pMacAddr)
4204 {
4205 if (isxdigit(*pMacAddr))
4206 {
4207 xdigit++;
4208 }
4209 else if (':' == *pMacAddr)
4210 {
4211 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4212 break;
4213
4214 ++separator;
4215 }
4216 else
4217 {
4218 separator = -1;
4219 /* Invalid MAC found */
4220 return 0;
4221 }
4222 ++pMacAddr;
4223 }
4224 return (xdigit == 12 && (separator == 5 || separator == 0));
4225}
4226
4227/**---------------------------------------------------------------------------
4228
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 \brief hdd_open() - HDD Open function
4230
4231 This is called in response to ifconfig up
4232
4233 \param - dev Pointer to net_device structure
4234
4235 \return - 0 for success non-zero for failure
4236
4237 --------------------------------------------------------------------------*/
4238int hdd_open (struct net_device *dev)
4239{
4240 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4241 hdd_context_t *pHddCtx;
4242 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4243 VOS_STATUS status;
4244 v_BOOL_t in_standby = TRUE;
4245
4246 if (NULL == pAdapter)
4247 {
4248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004249 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 return -ENODEV;
4251 }
4252
4253 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4254 if (NULL == pHddCtx)
4255 {
4256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004257 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 return -ENODEV;
4259 }
4260
4261 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4262 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4263 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004264 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4265 {
4266 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304267 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004268 in_standby = FALSE;
4269 break;
4270 }
4271 else
4272 {
4273 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4274 pAdapterNode = pNext;
4275 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 }
4277
4278 if (TRUE == in_standby)
4279 {
4280 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4281 {
4282 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4283 "wlan out of power save", __func__);
4284 return -EINVAL;
4285 }
4286 }
4287
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004288 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4290 {
4291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004292 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004293 /* Enable TX queues only when we are connected */
4294 netif_tx_start_all_queues(dev);
4295 }
4296
4297 return 0;
4298}
4299
4300int hdd_mon_open (struct net_device *dev)
4301{
4302 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4303
4304 if(pAdapter == NULL) {
4305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004306 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004307 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004308 }
4309
4310 netif_start_queue(dev);
4311
4312 return 0;
4313}
4314/**---------------------------------------------------------------------------
4315
4316 \brief hdd_stop() - HDD stop function
4317
4318 This is called in response to ifconfig down
4319
4320 \param - dev Pointer to net_device structure
4321
4322 \return - 0 for success non-zero for failure
4323
4324 --------------------------------------------------------------------------*/
4325
4326int hdd_stop (struct net_device *dev)
4327{
4328 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4329 hdd_context_t *pHddCtx;
4330 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4331 VOS_STATUS status;
4332 v_BOOL_t enter_standby = TRUE;
4333
4334 ENTER();
4335
4336 if (NULL == pAdapter)
4337 {
4338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004339 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 return -ENODEV;
4341 }
4342
4343 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4344 if (NULL == pHddCtx)
4345 {
4346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004347 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004348 return -ENODEV;
4349 }
4350
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004351 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4353 netif_tx_disable(pAdapter->dev);
4354 netif_carrier_off(pAdapter->dev);
4355
4356
4357 /* SoftAP ifaces should never go in power save mode
4358 making sure same here. */
4359 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4360 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004362 )
4363 {
4364 /* SoftAP mode, so return from here */
4365 EXIT();
4366 return 0;
4367 }
4368
4369 /* Find if any iface is up then
4370 if any iface is up then can't put device to sleep/ power save mode. */
4371 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4372 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4373 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004374 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4375 {
4376 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304377 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004378 enter_standby = FALSE;
4379 break;
4380 }
4381 else
4382 {
4383 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4384 pAdapterNode = pNext;
4385 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004386 }
4387
4388 if (TRUE == enter_standby)
4389 {
4390 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4391 "entering standby", __func__);
4392 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4393 {
4394 /*log and return success*/
4395 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4396 "wlan in power save", __func__);
4397 }
4398 }
4399
4400 EXIT();
4401 return 0;
4402}
4403
4404/**---------------------------------------------------------------------------
4405
4406 \brief hdd_uninit() - HDD uninit function
4407
4408 This is called during the netdev unregister to uninitialize all data
4409associated with the device
4410
4411 \param - dev Pointer to net_device structure
4412
4413 \return - void
4414
4415 --------------------------------------------------------------------------*/
4416static void hdd_uninit (struct net_device *dev)
4417{
4418 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4419
4420 ENTER();
4421
4422 do
4423 {
4424 if (NULL == pAdapter)
4425 {
4426 hddLog(VOS_TRACE_LEVEL_FATAL,
4427 "%s: NULL pAdapter", __func__);
4428 break;
4429 }
4430
4431 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4432 {
4433 hddLog(VOS_TRACE_LEVEL_FATAL,
4434 "%s: Invalid magic", __func__);
4435 break;
4436 }
4437
4438 if (NULL == pAdapter->pHddCtx)
4439 {
4440 hddLog(VOS_TRACE_LEVEL_FATAL,
4441 "%s: NULL pHddCtx", __func__);
4442 break;
4443 }
4444
4445 if (dev != pAdapter->dev)
4446 {
4447 hddLog(VOS_TRACE_LEVEL_FATAL,
4448 "%s: Invalid device reference", __func__);
4449 /* we haven't validated all cases so let this go for now */
4450 }
4451
4452 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4453
4454 /* after uninit our adapter structure will no longer be valid */
4455 pAdapter->dev = NULL;
4456 pAdapter->magic = 0;
4457 } while (0);
4458
4459 EXIT();
4460}
4461
4462/**---------------------------------------------------------------------------
4463
4464 \brief hdd_release_firmware() -
4465
4466 This function calls the release firmware API to free the firmware buffer.
4467
4468 \param - pFileName Pointer to the File Name.
4469 pCtx - Pointer to the adapter .
4470
4471
4472 \return - 0 for success, non zero for failure
4473
4474 --------------------------------------------------------------------------*/
4475
4476VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4477{
4478 VOS_STATUS status = VOS_STATUS_SUCCESS;
4479 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4480 ENTER();
4481
4482
4483 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4484
4485 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4486
4487 if(pHddCtx->fw) {
4488 release_firmware(pHddCtx->fw);
4489 pHddCtx->fw = NULL;
4490 }
4491 else
4492 status = VOS_STATUS_E_FAILURE;
4493 }
4494 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4495 if(pHddCtx->nv) {
4496 release_firmware(pHddCtx->nv);
4497 pHddCtx->nv = NULL;
4498 }
4499 else
4500 status = VOS_STATUS_E_FAILURE;
4501
4502 }
4503
4504 EXIT();
4505 return status;
4506}
4507
4508/**---------------------------------------------------------------------------
4509
4510 \brief hdd_request_firmware() -
4511
4512 This function reads the firmware file using the request firmware
4513 API and returns the the firmware data and the firmware file size.
4514
4515 \param - pfileName - Pointer to the file name.
4516 - pCtx - Pointer to the adapter .
4517 - ppfw_data - Pointer to the pointer of the firmware data.
4518 - pSize - Pointer to the file size.
4519
4520 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4521
4522 --------------------------------------------------------------------------*/
4523
4524
4525VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4526{
4527 int status;
4528 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4529 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4530 ENTER();
4531
4532 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4533
4534 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4535
4536 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4537 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4538 __func__, pfileName);
4539 retval = VOS_STATUS_E_FAILURE;
4540 }
4541
4542 else {
4543 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4544 *pSize = pHddCtx->fw->size;
4545 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4546 __func__, *pSize);
4547 }
4548 }
4549 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4550
4551 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4552
4553 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4554 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4555 __func__, pfileName);
4556 retval = VOS_STATUS_E_FAILURE;
4557 }
4558
4559 else {
4560 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4561 *pSize = pHddCtx->nv->size;
4562 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4563 __func__, *pSize);
4564 }
4565 }
4566
4567 EXIT();
4568 return retval;
4569}
4570/**---------------------------------------------------------------------------
4571 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4572
4573 This is the function invoked by SME to inform the result of a full power
4574 request issued by HDD
4575
4576 \param - callbackcontext - Pointer to cookie
4577 status - result of request
4578
4579 \return - None
4580
4581--------------------------------------------------------------------------*/
4582void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4583{
4584 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4585
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004586 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004587 if(&pHddCtx->full_pwr_comp_var)
4588 {
4589 complete(&pHddCtx->full_pwr_comp_var);
4590 }
4591}
4592
4593/**---------------------------------------------------------------------------
4594
4595 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4596
4597 This is the function invoked by SME to inform the result of BMPS
4598 request issued by HDD
4599
4600 \param - callbackcontext - Pointer to cookie
4601 status - result of request
4602
4603 \return - None
4604
4605--------------------------------------------------------------------------*/
4606void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4607{
4608
4609 struct completion *completion_var = (struct completion*) callbackContext;
4610
4611 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4612 if(completion_var != NULL)
4613 {
4614 complete(completion_var);
4615 }
4616}
4617
4618/**---------------------------------------------------------------------------
4619
4620 \brief hdd_get_cfg_file_size() -
4621
4622 This function reads the configuration file using the request firmware
4623 API and returns the configuration file size.
4624
4625 \param - pCtx - Pointer to the adapter .
4626 - pFileName - Pointer to the file name.
4627 - pBufSize - Pointer to the buffer size.
4628
4629 \return - 0 for success, non zero for failure
4630
4631 --------------------------------------------------------------------------*/
4632
4633VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4634{
4635 int status;
4636 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4637
4638 ENTER();
4639
4640 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4641
4642 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4643 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4644 status = VOS_STATUS_E_FAILURE;
4645 }
4646 else {
4647 *pBufSize = pHddCtx->fw->size;
4648 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4649 release_firmware(pHddCtx->fw);
4650 pHddCtx->fw = NULL;
4651 }
4652
4653 EXIT();
4654 return VOS_STATUS_SUCCESS;
4655}
4656
4657/**---------------------------------------------------------------------------
4658
4659 \brief hdd_read_cfg_file() -
4660
4661 This function reads the configuration file using the request firmware
4662 API and returns the cfg data and the buffer size of the configuration file.
4663
4664 \param - pCtx - Pointer to the adapter .
4665 - pFileName - Pointer to the file name.
4666 - pBuffer - Pointer to the data buffer.
4667 - pBufSize - Pointer to the buffer size.
4668
4669 \return - 0 for success, non zero for failure
4670
4671 --------------------------------------------------------------------------*/
4672
4673VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4674 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4675{
4676 int status;
4677 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4678
4679 ENTER();
4680
4681 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4682
4683 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4684 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4685 return VOS_STATUS_E_FAILURE;
4686 }
4687 else {
4688 if(*pBufSize != pHddCtx->fw->size) {
4689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4690 "file size", __func__);
4691 release_firmware(pHddCtx->fw);
4692 pHddCtx->fw = NULL;
4693 return VOS_STATUS_E_FAILURE;
4694 }
4695 else {
4696 if(pBuffer) {
4697 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4698 }
4699 release_firmware(pHddCtx->fw);
4700 pHddCtx->fw = NULL;
4701 }
4702 }
4703
4704 EXIT();
4705
4706 return VOS_STATUS_SUCCESS;
4707}
4708
4709/**---------------------------------------------------------------------------
4710
Jeff Johnson295189b2012-06-20 16:38:30 -07004711 \brief hdd_set_mac_address() -
4712
4713 This function sets the user specified mac address using
4714 the command ifconfig wlanX hw ether <mac adress>.
4715
4716 \param - dev - Pointer to the net device.
4717 - addr - Pointer to the sockaddr.
4718 \return - 0 for success, non zero for failure
4719
4720 --------------------------------------------------------------------------*/
4721
4722static int hdd_set_mac_address(struct net_device *dev, void *addr)
4723{
4724 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4725 struct sockaddr *psta_mac_addr = addr;
4726 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4727
4728 ENTER();
4729
4730 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4731
4732#ifdef HDD_SESSIONIZE
4733 // set the MAC address though the STA ID CFG.
4734 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4735 (v_U8_t *)&pAdapter->macAddressCurrent,
4736 sizeof( pAdapter->macAddressCurrent ),
4737 hdd_set_mac_addr_cb, VOS_FALSE );
4738#endif
4739
4740 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4741
4742 EXIT();
4743 return halStatus;
4744}
4745
4746tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4747{
4748 int i;
4749 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4750 {
4751 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4752 break;
4753 }
4754
4755 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4756 return NULL;
4757
4758 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4759 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4760}
4761
4762void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4763{
4764 int i;
4765 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4766 {
4767 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4768 {
4769 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4770 break;
4771 }
4772 }
4773 return;
4774}
4775
4776#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4777 static struct net_device_ops wlan_drv_ops = {
4778 .ndo_open = hdd_open,
4779 .ndo_stop = hdd_stop,
4780 .ndo_uninit = hdd_uninit,
4781 .ndo_start_xmit = hdd_hard_start_xmit,
4782 .ndo_tx_timeout = hdd_tx_timeout,
4783 .ndo_get_stats = hdd_stats,
4784 .ndo_do_ioctl = hdd_ioctl,
4785 .ndo_set_mac_address = hdd_set_mac_address,
4786 .ndo_select_queue = hdd_select_queue,
4787#ifdef WLAN_FEATURE_PACKET_FILTERING
4788#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4789 .ndo_set_rx_mode = hdd_set_multicast_list,
4790#else
4791 .ndo_set_multicast_list = hdd_set_multicast_list,
4792#endif //LINUX_VERSION_CODE
4793#endif
4794 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004795 static struct net_device_ops wlan_mon_drv_ops = {
4796 .ndo_open = hdd_mon_open,
4797 .ndo_stop = hdd_stop,
4798 .ndo_uninit = hdd_uninit,
4799 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4800 .ndo_tx_timeout = hdd_tx_timeout,
4801 .ndo_get_stats = hdd_stats,
4802 .ndo_do_ioctl = hdd_ioctl,
4803 .ndo_set_mac_address = hdd_set_mac_address,
4804 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004805
4806#endif
4807
4808void hdd_set_station_ops( struct net_device *pWlanDev )
4809{
4810#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4811 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4812 pWlanDev->netdev_ops = &wlan_drv_ops;
4813#else
4814 pWlanDev->open = hdd_open;
4815 pWlanDev->stop = hdd_stop;
4816 pWlanDev->uninit = hdd_uninit;
4817 pWlanDev->hard_start_xmit = NULL;
4818 pWlanDev->tx_timeout = hdd_tx_timeout;
4819 pWlanDev->get_stats = hdd_stats;
4820 pWlanDev->do_ioctl = hdd_ioctl;
4821 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4822 pWlanDev->set_mac_address = hdd_set_mac_address;
4823#endif
4824}
4825
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004826static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004827{
4828 struct net_device *pWlanDev = NULL;
4829 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 /*
4831 * cfg80211 initialization and registration....
4832 */
4833 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4834
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 if(pWlanDev != NULL)
4836 {
4837
4838 //Save the pointer to the net_device in the HDD adapter
4839 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4840
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4842
4843 pAdapter->dev = pWlanDev;
4844 pAdapter->pHddCtx = pHddCtx;
4845 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4846
4847 init_completion(&pAdapter->session_open_comp_var);
4848 init_completion(&pAdapter->session_close_comp_var);
4849 init_completion(&pAdapter->disconnect_comp_var);
4850 init_completion(&pAdapter->linkup_event_var);
4851 init_completion(&pAdapter->cancel_rem_on_chan_var);
4852 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4854 init_completion(&pAdapter->offchannel_tx_event);
4855#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004857#ifdef FEATURE_WLAN_TDLS
4858 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004859 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004860 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304861 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004862#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004863 init_completion(&pHddCtx->mc_sus_event_var);
4864 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304865 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004866 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004867 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004868
Rajeev79dbe4c2013-10-05 11:03:42 +05304869#ifdef FEATURE_WLAN_BATCH_SCAN
4870 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4871 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4872 pAdapter->pBatchScanRsp = NULL;
4873 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004874 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304875 mutex_init(&pAdapter->hdd_batch_scan_lock);
4876#endif
4877
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 pAdapter->isLinkUpSvcNeeded = FALSE;
4879 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4880 //Init the net_device structure
4881 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4882
4883 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4884 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4885 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4886 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4887
4888 hdd_set_station_ops( pAdapter->dev );
4889
4890 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004891 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4892 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4893 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004894 /* set pWlanDev's parent to underlying device */
4895 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4896 }
4897
4898 return pAdapter;
4899}
4900
4901VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4902{
4903 struct net_device *pWlanDev = pAdapter->dev;
4904 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4905 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4906 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4907
4908 if( rtnl_lock_held )
4909 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004910 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4912 {
4913 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4914 return VOS_STATUS_E_FAILURE;
4915 }
4916 }
4917 if (register_netdevice(pWlanDev))
4918 {
4919 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4920 return VOS_STATUS_E_FAILURE;
4921 }
4922 }
4923 else
4924 {
4925 if(register_netdev(pWlanDev))
4926 {
4927 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4928 return VOS_STATUS_E_FAILURE;
4929 }
4930 }
4931 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4932
4933 return VOS_STATUS_SUCCESS;
4934}
4935
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004936static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004937{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004938 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004939
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004940 if (NULL == pAdapter)
4941 {
4942 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4943 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004945
4946 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4947 {
4948 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4949 return eHAL_STATUS_NOT_INITIALIZED;
4950 }
4951
4952 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4953
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004954#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004955 /* need to make sure all of our scheduled work has completed.
4956 * This callback is called from MC thread context, so it is safe to
4957 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004958 *
4959 * Even though this is called from MC thread context, if there is a faulty
4960 * work item in the system, that can hang this call forever. So flushing
4961 * this global work queue is not safe; and now we make sure that
4962 * individual work queues are stopped correctly. But the cancel work queue
4963 * is a GPL only API, so the proprietary version of the driver would still
4964 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004965 */
4966 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004967#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004968
4969 /* We can be blocked while waiting for scheduled work to be
4970 * flushed, and the adapter structure can potentially be freed, in
4971 * which case the magic will have been reset. So make sure the
4972 * magic is still good, and hence the adapter structure is still
4973 * valid, before signaling completion */
4974 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4975 {
4976 complete(&pAdapter->session_close_comp_var);
4977 }
4978
Jeff Johnson295189b2012-06-20 16:38:30 -07004979 return eHAL_STATUS_SUCCESS;
4980}
4981
4982VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4983{
4984 struct net_device *pWlanDev = pAdapter->dev;
4985 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4986 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4987 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4988 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4989 int rc = 0;
4990
4991 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004992 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 //Open a SME session for future operation
4994 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004995 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004996 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4997 {
4998 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07004999 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005000 halStatus, halStatus );
5001 status = VOS_STATUS_E_FAILURE;
5002 goto error_sme_open;
5003 }
5004
5005 //Block on a completion variable. Can't wait forever though.
5006 rc = wait_for_completion_interruptible_timeout(
5007 &pAdapter->session_open_comp_var,
5008 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5009 if (!rc)
5010 {
5011 hddLog(VOS_TRACE_LEVEL_FATAL,
5012 "Session is not opened within timeout period code %08d", rc );
5013 status = VOS_STATUS_E_FAILURE;
5014 goto error_sme_open;
5015 }
5016
5017 // Register wireless extensions
5018 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5019 {
5020 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005021 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005022 halStatus, halStatus );
5023 status = VOS_STATUS_E_FAILURE;
5024 goto error_register_wext;
5025 }
5026 //Safe to register the hard_start_xmit function again
5027#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5028 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5029#else
5030 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5031#endif
5032
5033 //Set the Connection State to Not Connected
5034 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5035
5036 //Set the default operation channel
5037 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5038
5039 /* Make the default Auth Type as OPEN*/
5040 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5041
5042 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5043 {
5044 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005045 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005046 status, status );
5047 goto error_init_txrx;
5048 }
5049
5050 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5051
5052 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5053 {
5054 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005055 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005056 status, status );
5057 goto error_wmm_init;
5058 }
5059
5060 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5061
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005062#ifdef FEATURE_WLAN_TDLS
5063 if(0 != wlan_hdd_tdls_init(pAdapter))
5064 {
5065 status = VOS_STATUS_E_FAILURE;
5066 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5067 goto error_tdls_init;
5068 }
5069 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5070#endif
5071
Jeff Johnson295189b2012-06-20 16:38:30 -07005072 return VOS_STATUS_SUCCESS;
5073
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005074#ifdef FEATURE_WLAN_TDLS
5075error_tdls_init:
5076 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5077 hdd_wmm_adapter_close(pAdapter);
5078#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005079error_wmm_init:
5080 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5081 hdd_deinit_tx_rx(pAdapter);
5082error_init_txrx:
5083 hdd_UnregisterWext(pWlanDev);
5084error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005085 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 {
5087 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005088 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005089 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005090 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005091 {
5092 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005093 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005095 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005096 }
5097}
5098error_sme_open:
5099 return status;
5100}
5101
Jeff Johnson295189b2012-06-20 16:38:30 -07005102void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5103{
5104 hdd_cfg80211_state_t *cfgState;
5105
5106 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5107
5108 if( NULL != cfgState->buf )
5109 {
5110 int rc;
5111 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5112 rc = wait_for_completion_interruptible_timeout(
5113 &pAdapter->tx_action_cnf_event,
5114 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5115 if(!rc)
5116 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5119 }
5120 }
5121 return;
5122}
Jeff Johnson295189b2012-06-20 16:38:30 -07005123
5124void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5125{
5126 ENTER();
5127 switch ( pAdapter->device_mode )
5128 {
5129 case WLAN_HDD_INFRA_STATION:
5130 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005131 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005132 {
5133 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5134 {
5135 hdd_deinit_tx_rx( pAdapter );
5136 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5137 }
5138
5139 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5140 {
5141 hdd_wmm_adapter_close( pAdapter );
5142 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5143 }
5144
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005146#ifdef FEATURE_WLAN_TDLS
5147 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5148 {
5149 wlan_hdd_tdls_exit(pAdapter);
5150 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5151 }
5152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005153
5154 break;
5155 }
5156
5157 case WLAN_HDD_SOFTAP:
5158 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305160
5161 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5162 {
5163 hdd_wmm_adapter_close( pAdapter );
5164 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5165 }
5166
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005168
5169 hdd_unregister_hostapd(pAdapter);
5170 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005172 break;
5173 }
5174
5175 case WLAN_HDD_MONITOR:
5176 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005178 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5179 {
5180 hdd_deinit_tx_rx( pAdapter );
5181 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5182 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 if(NULL != pAdapterforTx)
5184 {
5185 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 break;
5188 }
5189
5190
5191 default:
5192 break;
5193 }
5194
5195 EXIT();
5196}
5197
5198void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5199{
5200 struct net_device *pWlanDev = pAdapter->dev;
5201
Rajeev79dbe4c2013-10-05 11:03:42 +05305202#ifdef FEATURE_WLAN_BATCH_SCAN
5203 tHddBatchScanRsp *pNode;
5204 tHddBatchScanRsp *pPrev;
5205 if (pAdapter)
5206 {
5207 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5208 pNode = pAdapter->pBatchScanRsp;
5209 while (pNode)
5210 {
5211 pPrev = pNode;
5212 pNode = pNode->pNext;
5213 vos_mem_free((v_VOID_t * )pPrev);
5214 }
5215 pAdapter->pBatchScanRsp = NULL;
5216 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5217 }
5218#endif
5219
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5221 if( rtnl_held )
5222 {
5223 unregister_netdevice(pWlanDev);
5224 }
5225 else
5226 {
5227 unregister_netdev(pWlanDev);
5228 }
5229 // note that the pAdapter is no longer valid at this point
5230 // since the memory has been reclaimed
5231 }
5232
5233}
5234
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005235void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5236{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305237 VOS_STATUS status;
5238 hdd_adapter_t *pAdapter = NULL;
5239 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005240
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305241 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005242
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305243 /*loop through all adapters.*/
5244 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005245 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305246 pAdapter = pAdapterNode->pAdapter;
5247 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5248 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005249
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305250 { // we skip this registration for modes other than STA and P2P client modes.
5251 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5252 pAdapterNode = pNext;
5253 continue;
5254 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005255
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305256 //Apply Dynamic DTIM For P2P
5257 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5258 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5259 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5260 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5261 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5262 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5263 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5264 (eConnectionState_Associated ==
5265 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5266 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5267 {
5268 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005269
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305270 powerRequest.uIgnoreDTIM = 1;
5271 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5272
5273 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5274 {
5275 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5276 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5277 }
5278 else
5279 {
5280 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5281 }
5282
5283 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5284 * specified during Enter/Exit BMPS when LCD off*/
5285 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5286 NULL, eANI_BOOLEAN_FALSE);
5287 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5288 NULL, eANI_BOOLEAN_FALSE);
5289
5290 /* switch to the DTIM specified in cfg.ini */
5291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5292 "Switch to DTIM %d", powerRequest.uListenInterval);
5293 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5294 break;
5295
5296 }
5297
5298 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5299 pAdapterNode = pNext;
5300 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005301}
5302
5303void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5304{
5305 /*Switch back to DTIM 1*/
5306 tSirSetPowerParamsReq powerRequest = { 0 };
5307
5308 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5309 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005310 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005311
5312 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5313 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5314 NULL, eANI_BOOLEAN_FALSE);
5315 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5316 NULL, eANI_BOOLEAN_FALSE);
5317
5318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5319 "Switch to DTIM%d",powerRequest.uListenInterval);
5320 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5321
5322}
5323
Jeff Johnson295189b2012-06-20 16:38:30 -07005324VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5325{
5326 VOS_STATUS status = VOS_STATUS_SUCCESS;
5327
5328 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5329 {
5330 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5331 }
5332
5333 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5334 {
5335 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5336 }
5337
5338 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5339 {
5340 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5341 }
5342
5343 return status;
5344}
5345
5346VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5347{
5348 hdd_adapter_t *pAdapter = NULL;
5349 eHalStatus halStatus;
5350 VOS_STATUS status = VOS_STATUS_E_INVAL;
5351 v_BOOL_t disableBmps = FALSE;
5352 v_BOOL_t disableImps = FALSE;
5353
5354 switch(session_type)
5355 {
5356 case WLAN_HDD_INFRA_STATION:
5357 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005358 case WLAN_HDD_P2P_CLIENT:
5359 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005360 //Exit BMPS -> Is Sta/P2P Client is already connected
5361 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5362 if((NULL != pAdapter)&&
5363 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5364 {
5365 disableBmps = TRUE;
5366 }
5367
5368 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5369 if((NULL != pAdapter)&&
5370 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5371 {
5372 disableBmps = TRUE;
5373 }
5374
5375 //Exit both Bmps and Imps incase of Go/SAP Mode
5376 if((WLAN_HDD_SOFTAP == session_type) ||
5377 (WLAN_HDD_P2P_GO == session_type))
5378 {
5379 disableBmps = TRUE;
5380 disableImps = TRUE;
5381 }
5382
5383 if(TRUE == disableImps)
5384 {
5385 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5386 {
5387 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5388 }
5389 }
5390
5391 if(TRUE == disableBmps)
5392 {
5393 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5394 {
5395 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5396
5397 if(eHAL_STATUS_SUCCESS != halStatus)
5398 {
5399 status = VOS_STATUS_E_FAILURE;
5400 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5401 VOS_ASSERT(0);
5402 return status;
5403 }
5404 }
5405
5406 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5407 {
5408 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5409
5410 if(eHAL_STATUS_SUCCESS != halStatus)
5411 {
5412 status = VOS_STATUS_E_FAILURE;
5413 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5414 VOS_ASSERT(0);
5415 return status;
5416 }
5417 }
5418 }
5419
5420 if((TRUE == disableBmps) ||
5421 (TRUE == disableImps))
5422 {
5423 /* Now, get the chip into Full Power now */
5424 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5425 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5426 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5427
5428 if(halStatus != eHAL_STATUS_SUCCESS)
5429 {
5430 if(halStatus == eHAL_STATUS_PMC_PENDING)
5431 {
5432 //Block on a completion variable. Can't wait forever though
5433 wait_for_completion_interruptible_timeout(
5434 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5435 }
5436 else
5437 {
5438 status = VOS_STATUS_E_FAILURE;
5439 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5440 VOS_ASSERT(0);
5441 return status;
5442 }
5443 }
5444
5445 status = VOS_STATUS_SUCCESS;
5446 }
5447
5448 break;
5449 }
5450 return status;
5451}
5452
5453hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005454 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005455 tANI_U8 rtnl_held )
5456{
5457 hdd_adapter_t *pAdapter = NULL;
5458 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5459 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5460 VOS_STATUS exitbmpsStatus;
5461
5462 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5463
5464 //Disable BMPS incase of Concurrency
5465 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5466
5467 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5468 {
5469 //Fail to Exit BMPS
5470 VOS_ASSERT(0);
5471 return NULL;
5472 }
5473
5474 switch(session_type)
5475 {
5476 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005478 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005479 {
5480 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5481
5482 if( NULL == pAdapter )
5483 return NULL;
5484
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305485#ifdef FEATURE_WLAN_TDLS
5486 /* A Mutex Lock is introduced while changing/initializing the mode to
5487 * protect the concurrent access for the Adapters by TDLS module.
5488 */
5489 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5490 {
5491 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5492 "%s: unable to lock list", __func__);
5493 return NULL;
5494 }
5495#endif
5496
Jeff Johnsone7245742012-09-05 17:12:55 -07005497 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5498 NL80211_IFTYPE_P2P_CLIENT:
5499 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005500
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 pAdapter->device_mode = session_type;
5502
5503 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305504#ifdef FEATURE_WLAN_TDLS
5505 mutex_unlock(&pHddCtx->tdls_lock);
5506#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 if( VOS_STATUS_SUCCESS != status )
5508 goto err_free_netdev;
5509
5510 status = hdd_register_interface( pAdapter, rtnl_held );
5511 if( VOS_STATUS_SUCCESS != status )
5512 {
5513 hdd_deinit_adapter(pHddCtx, pAdapter);
5514 goto err_free_netdev;
5515 }
5516 //Stop the Interface TX queue.
5517 netif_tx_disable(pAdapter->dev);
5518 //netif_tx_disable(pWlanDev);
5519 netif_carrier_off(pAdapter->dev);
5520
5521 break;
5522 }
5523
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 case WLAN_HDD_SOFTAP:
5526 {
5527 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5528 if( NULL == pAdapter )
5529 return NULL;
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5532 NL80211_IFTYPE_AP:
5533 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 pAdapter->device_mode = session_type;
5535
5536 status = hdd_init_ap_mode(pAdapter);
5537 if( VOS_STATUS_SUCCESS != status )
5538 goto err_free_netdev;
5539
5540 status = hdd_register_hostapd( pAdapter, rtnl_held );
5541 if( VOS_STATUS_SUCCESS != status )
5542 {
5543 hdd_deinit_adapter(pHddCtx, pAdapter);
5544 goto err_free_netdev;
5545 }
5546
5547 netif_tx_disable(pAdapter->dev);
5548 netif_carrier_off(pAdapter->dev);
5549
5550 hdd_set_conparam( 1 );
5551 break;
5552 }
5553 case WLAN_HDD_MONITOR:
5554 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5556 if( NULL == pAdapter )
5557 return NULL;
5558
5559 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5560 pAdapter->device_mode = session_type;
5561 status = hdd_register_interface( pAdapter, rtnl_held );
5562#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5563 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5564#else
5565 pAdapter->dev->open = hdd_mon_open;
5566 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5567#endif
5568 hdd_init_tx_rx( pAdapter );
5569 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5570 //Set adapter to be used for data tx. It will use either GO or softap.
5571 pAdapter->sessionCtx.monitor.pAdapterForTx =
5572 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5574 {
5575 pAdapter->sessionCtx.monitor.pAdapterForTx =
5576 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 /* This workqueue will be used to transmit management packet over
5579 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005580 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5581 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5582 return NULL;
5583 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005584
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5586 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 }
5588 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 case WLAN_HDD_FTM:
5590 {
5591 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5592
5593 if( NULL == pAdapter )
5594 return NULL;
5595 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5596 * message while loading driver in FTM mode. */
5597 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5598 pAdapter->device_mode = session_type;
5599 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305600
5601 hdd_init_tx_rx( pAdapter );
5602
5603 //Stop the Interface TX queue.
5604 netif_tx_disable(pAdapter->dev);
5605 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 }
5607 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 default:
5609 {
5610 VOS_ASSERT(0);
5611 return NULL;
5612 }
5613 }
5614
5615
5616 if( VOS_STATUS_SUCCESS == status )
5617 {
5618 //Add it to the hdd's session list.
5619 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5620 if( NULL == pHddAdapterNode )
5621 {
5622 status = VOS_STATUS_E_NOMEM;
5623 }
5624 else
5625 {
5626 pHddAdapterNode->pAdapter = pAdapter;
5627 status = hdd_add_adapter_back ( pHddCtx,
5628 pHddAdapterNode );
5629 }
5630 }
5631
5632 if( VOS_STATUS_SUCCESS != status )
5633 {
5634 if( NULL != pAdapter )
5635 {
5636 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5637 pAdapter = NULL;
5638 }
5639 if( NULL != pHddAdapterNode )
5640 {
5641 vos_mem_free( pHddAdapterNode );
5642 }
5643
5644 goto resume_bmps;
5645 }
5646
5647 if(VOS_STATUS_SUCCESS == status)
5648 {
5649 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5650
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005651 //Initialize the WoWL service
5652 if(!hdd_init_wowl(pAdapter))
5653 {
5654 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5655 goto err_free_netdev;
5656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005657 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 return pAdapter;
5659
5660err_free_netdev:
5661 free_netdev(pAdapter->dev);
5662 wlan_hdd_release_intf_addr( pHddCtx,
5663 pAdapter->macAddressCurrent.bytes );
5664
5665resume_bmps:
5666 //If bmps disabled enable it
5667 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5668 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305669 if (pHddCtx->hdd_wlan_suspended)
5670 {
5671 hdd_set_pwrparams(pHddCtx);
5672 }
5673 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005674 }
5675 return NULL;
5676}
5677
5678VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5679 tANI_U8 rtnl_held )
5680{
5681 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5682 VOS_STATUS status;
5683
5684 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5685 if( VOS_STATUS_SUCCESS != status )
5686 return status;
5687
5688 while ( pCurrent->pAdapter != pAdapter )
5689 {
5690 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5691 if( VOS_STATUS_SUCCESS != status )
5692 break;
5693
5694 pCurrent = pNext;
5695 }
5696 pAdapterNode = pCurrent;
5697 if( VOS_STATUS_SUCCESS == status )
5698 {
5699 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5700 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305701
5702#ifdef FEATURE_WLAN_TDLS
5703
5704 /* A Mutex Lock is introduced while changing/initializing the mode to
5705 * protect the concurrent access for the Adapters by TDLS module.
5706 */
5707 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5708 {
5709 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5710 "%s: unable to lock list", __func__);
5711 return VOS_STATUS_E_FAILURE;
5712 }
5713#endif
5714
Jeff Johnson295189b2012-06-20 16:38:30 -07005715 hdd_remove_adapter( pHddCtx, pAdapterNode );
5716 vos_mem_free( pAdapterNode );
5717
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305718#ifdef FEATURE_WLAN_TDLS
5719 mutex_unlock(&pHddCtx->tdls_lock);
5720#endif
5721
Jeff Johnson295189b2012-06-20 16:38:30 -07005722
5723 /* If there is a single session of STA/P2P client, re-enable BMPS */
5724 if ((!vos_concurrent_sessions_running()) &&
5725 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5726 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5727 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305728 if (pHddCtx->hdd_wlan_suspended)
5729 {
5730 hdd_set_pwrparams(pHddCtx);
5731 }
5732 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 }
5734
5735 return VOS_STATUS_SUCCESS;
5736 }
5737
5738 return VOS_STATUS_E_FAILURE;
5739}
5740
5741VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5742{
5743 hdd_adapter_list_node_t *pHddAdapterNode;
5744 VOS_STATUS status;
5745
5746 ENTER();
5747
5748 do
5749 {
5750 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5751 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5752 {
5753 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5754 vos_mem_free( pHddAdapterNode );
5755 }
5756 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5757
5758 EXIT();
5759
5760 return VOS_STATUS_SUCCESS;
5761}
5762
5763void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5764{
5765 v_U8_t addIE[1] = {0};
5766
5767 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5768 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5769 eANI_BOOLEAN_FALSE) )
5770 {
5771 hddLog(LOGE,
5772 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5773 }
5774
5775 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5776 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5777 eANI_BOOLEAN_FALSE) )
5778 {
5779 hddLog(LOGE,
5780 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5781 }
5782
5783 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5784 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5785 eANI_BOOLEAN_FALSE) )
5786 {
5787 hddLog(LOGE,
5788 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5789 }
5790}
5791
5792VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5793{
5794 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5795 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5796 union iwreq_data wrqu;
5797
5798 ENTER();
5799
5800 switch(pAdapter->device_mode)
5801 {
5802 case WLAN_HDD_INFRA_STATION:
5803 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005804 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5806 {
5807 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5808 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5809 pAdapter->sessionId,
5810 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5811 else
5812 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5813 pAdapter->sessionId,
5814 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5815 //success implies disconnect command got queued up successfully
5816 if(halStatus == eHAL_STATUS_SUCCESS)
5817 {
5818 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5819 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5820 }
5821 memset(&wrqu, '\0', sizeof(wrqu));
5822 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5823 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5824 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5825 }
5826 else
5827 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305828 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 }
5830
5831 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5832 {
5833 INIT_COMPLETION(pAdapter->session_close_comp_var);
5834 if (eHAL_STATUS_SUCCESS ==
5835 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5836 hdd_smeCloseSessionCallback, pAdapter))
5837 {
5838 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005839 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 &pAdapter->session_close_comp_var,
5841 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5842 }
5843 }
5844
5845 break;
5846
5847 case WLAN_HDD_SOFTAP:
5848 case WLAN_HDD_P2P_GO:
5849 //Any softap specific cleanup here...
5850 mutex_lock(&pHddCtx->sap_lock);
5851 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5852 {
5853 VOS_STATUS status;
5854 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5855
5856 //Stop Bss.
5857 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5858 if (VOS_IS_STATUS_SUCCESS(status))
5859 {
5860 hdd_hostapd_state_t *pHostapdState =
5861 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5862
5863 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5864
5865 if (!VOS_IS_STATUS_SUCCESS(status))
5866 {
5867 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005868 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 }
5870 }
5871 else
5872 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005873 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005874 }
5875 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5876
5877 if (eHAL_STATUS_FAILURE ==
5878 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5879 0, NULL, eANI_BOOLEAN_FALSE))
5880 {
5881 hddLog(LOGE,
5882 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005883 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 }
5885
5886 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5887 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5888 eANI_BOOLEAN_FALSE) )
5889 {
5890 hddLog(LOGE,
5891 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5892 }
5893
5894 // Reset WNI_CFG_PROBE_RSP Flags
5895 wlan_hdd_reset_prob_rspies(pAdapter);
5896 kfree(pAdapter->sessionCtx.ap.beacon);
5897 pAdapter->sessionCtx.ap.beacon = NULL;
5898 }
5899 mutex_unlock(&pHddCtx->sap_lock);
5900 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005901
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005903#ifdef WLAN_OPEN_SOURCE
5904 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
5905#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005907
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 default:
5909 break;
5910 }
5911
5912 EXIT();
5913 return VOS_STATUS_SUCCESS;
5914}
5915
5916VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5917{
5918 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5919 VOS_STATUS status;
5920 hdd_adapter_t *pAdapter;
5921
5922 ENTER();
5923
5924 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5925
5926 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5927 {
5928 pAdapter = pAdapterNode->pAdapter;
5929 netif_tx_disable(pAdapter->dev);
5930 netif_carrier_off(pAdapter->dev);
5931
5932 hdd_stop_adapter( pHddCtx, pAdapter );
5933
5934 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5935 pAdapterNode = pNext;
5936 }
5937
5938 EXIT();
5939
5940 return VOS_STATUS_SUCCESS;
5941}
5942
5943VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5944{
5945 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5946 VOS_STATUS status;
5947 hdd_adapter_t *pAdapter;
5948
5949 ENTER();
5950
5951 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5952
5953 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5954 {
5955 pAdapter = pAdapterNode->pAdapter;
5956 netif_tx_disable(pAdapter->dev);
5957 netif_carrier_off(pAdapter->dev);
5958
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005959 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5960
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305962 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5963 {
5964 hdd_wmm_adapter_close( pAdapter );
5965 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5966 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005967
5968 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5969 pAdapterNode = pNext;
5970 }
5971
5972 EXIT();
5973
5974 return VOS_STATUS_SUCCESS;
5975}
5976
5977VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5978{
5979 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5980 VOS_STATUS status;
5981 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305982 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005983
5984 ENTER();
5985
5986 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5987
5988 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5989 {
5990 pAdapter = pAdapterNode->pAdapter;
5991
5992 switch(pAdapter->device_mode)
5993 {
5994 case WLAN_HDD_INFRA_STATION:
5995 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005996 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305997
5998 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5999
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 hdd_init_station_mode(pAdapter);
6001 /* Open the gates for HDD to receive Wext commands */
6002 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006003 pHddCtx->scan_info.mScanPending = FALSE;
6004 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006005
6006 //Trigger the initial scan
6007 hdd_wlan_initial_scan(pAdapter);
6008
6009 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306010 if (eConnectionState_Associated == connState ||
6011 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006012 {
6013 union iwreq_data wrqu;
6014 memset(&wrqu, '\0', sizeof(wrqu));
6015 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6016 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6017 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006018 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006019
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 /* indicate disconnected event to nl80211 */
6021 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6022 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006023 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306024 else if (eConnectionState_Connecting == connState)
6025 {
6026 /*
6027 * Indicate connect failure to supplicant if we were in the
6028 * process of connecting
6029 */
6030 cfg80211_connect_result(pAdapter->dev, NULL,
6031 NULL, 0, NULL, 0,
6032 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6033 GFP_KERNEL);
6034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006035 break;
6036
6037 case WLAN_HDD_SOFTAP:
6038 /* softAP can handle SSR */
6039 break;
6040
6041 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006042 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006044 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 break;
6046
6047 case WLAN_HDD_MONITOR:
6048 /* monitor interface start */
6049 break;
6050 default:
6051 break;
6052 }
6053
6054 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6055 pAdapterNode = pNext;
6056 }
6057
6058 EXIT();
6059
6060 return VOS_STATUS_SUCCESS;
6061}
6062
6063VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6064{
6065 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6066 hdd_adapter_t *pAdapter;
6067 VOS_STATUS status;
6068 v_U32_t roamId;
6069
6070 ENTER();
6071
6072 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6073
6074 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6075 {
6076 pAdapter = pAdapterNode->pAdapter;
6077
6078 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6079 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6080 {
6081 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6082 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6083
6084 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6085 init_completion(&pAdapter->disconnect_comp_var);
6086 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6087 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6088
6089 wait_for_completion_interruptible_timeout(
6090 &pAdapter->disconnect_comp_var,
6091 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6092
6093 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6094 pHddCtx->isAmpAllowed = VOS_FALSE;
6095 sme_RoamConnect(pHddCtx->hHal,
6096 pAdapter->sessionId, &(pWextState->roamProfile),
6097 &roamId);
6098 }
6099
6100 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6101 pAdapterNode = pNext;
6102 }
6103
6104 EXIT();
6105
6106 return VOS_STATUS_SUCCESS;
6107}
6108
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006109void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6110{
6111 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6112 VOS_STATUS status;
6113 hdd_adapter_t *pAdapter;
6114 hdd_station_ctx_t *pHddStaCtx;
6115 hdd_ap_ctx_t *pHddApCtx;
6116 hdd_hostapd_state_t * pHostapdState;
6117 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6118 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6119 const char *p2pMode = "DEV";
6120 const char *ccMode = "Standalone";
6121 int n;
6122
6123 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6124 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6125 {
6126 pAdapter = pAdapterNode->pAdapter;
6127 switch (pAdapter->device_mode) {
6128 case WLAN_HDD_INFRA_STATION:
6129 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6130 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6131 staChannel = pHddStaCtx->conn_info.operationChannel;
6132 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6133 }
6134 break;
6135 case WLAN_HDD_P2P_CLIENT:
6136 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6137 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6138 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6139 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6140 p2pMode = "CLI";
6141 }
6142 break;
6143 case WLAN_HDD_P2P_GO:
6144 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6145 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6146 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6147 p2pChannel = pHddApCtx->operatingChannel;
6148 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6149 }
6150 p2pMode = "GO";
6151 break;
6152 case WLAN_HDD_SOFTAP:
6153 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6154 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6155 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6156 apChannel = pHddApCtx->operatingChannel;
6157 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6158 }
6159 break;
6160 default:
6161 break;
6162 }
6163 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6164 pAdapterNode = pNext;
6165 }
6166 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6167 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6168 }
6169 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6170 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6171 if (p2pChannel > 0) {
6172 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6173 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6174 }
6175 if (apChannel > 0) {
6176 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6177 apChannel, MAC_ADDR_ARRAY(apBssid));
6178 }
6179
6180 if (p2pChannel > 0 && apChannel > 0) {
6181 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6182 }
6183}
6184
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006185bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006186{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006187 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006188}
6189
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006190/* Once SSR is disabled then it cannot be set. */
6191void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006192{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006193 if (HDD_SSR_DISABLED == isSsrRequired)
6194 return;
6195
Jeff Johnson295189b2012-06-20 16:38:30 -07006196 isSsrRequired = value;
6197}
6198
6199VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6200 hdd_adapter_list_node_t** ppAdapterNode)
6201{
6202 VOS_STATUS status;
6203 spin_lock(&pHddCtx->hddAdapters.lock);
6204 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6205 (hdd_list_node_t**) ppAdapterNode );
6206 spin_unlock(&pHddCtx->hddAdapters.lock);
6207 return status;
6208}
6209
6210VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6211 hdd_adapter_list_node_t* pAdapterNode,
6212 hdd_adapter_list_node_t** pNextAdapterNode)
6213{
6214 VOS_STATUS status;
6215 spin_lock(&pHddCtx->hddAdapters.lock);
6216 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6217 (hdd_list_node_t*) pAdapterNode,
6218 (hdd_list_node_t**)pNextAdapterNode );
6219
6220 spin_unlock(&pHddCtx->hddAdapters.lock);
6221 return status;
6222}
6223
6224VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6225 hdd_adapter_list_node_t* pAdapterNode)
6226{
6227 VOS_STATUS status;
6228 spin_lock(&pHddCtx->hddAdapters.lock);
6229 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6230 &pAdapterNode->node );
6231 spin_unlock(&pHddCtx->hddAdapters.lock);
6232 return status;
6233}
6234
6235VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6236 hdd_adapter_list_node_t** ppAdapterNode)
6237{
6238 VOS_STATUS status;
6239 spin_lock(&pHddCtx->hddAdapters.lock);
6240 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6241 (hdd_list_node_t**) ppAdapterNode );
6242 spin_unlock(&pHddCtx->hddAdapters.lock);
6243 return status;
6244}
6245
6246VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6247 hdd_adapter_list_node_t* pAdapterNode)
6248{
6249 VOS_STATUS status;
6250 spin_lock(&pHddCtx->hddAdapters.lock);
6251 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6252 (hdd_list_node_t*) pAdapterNode );
6253 spin_unlock(&pHddCtx->hddAdapters.lock);
6254 return status;
6255}
6256
6257VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6258 hdd_adapter_list_node_t* pAdapterNode)
6259{
6260 VOS_STATUS status;
6261 spin_lock(&pHddCtx->hddAdapters.lock);
6262 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6263 (hdd_list_node_t*) pAdapterNode );
6264 spin_unlock(&pHddCtx->hddAdapters.lock);
6265 return status;
6266}
6267
6268hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6269 tSirMacAddr macAddr )
6270{
6271 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6272 hdd_adapter_t *pAdapter;
6273 VOS_STATUS status;
6274
6275 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6276
6277 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6278 {
6279 pAdapter = pAdapterNode->pAdapter;
6280
6281 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6282 macAddr, sizeof(tSirMacAddr) ) )
6283 {
6284 return pAdapter;
6285 }
6286 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6287 pAdapterNode = pNext;
6288 }
6289
6290 return NULL;
6291
6292}
6293
6294hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6295{
6296 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6297 hdd_adapter_t *pAdapter;
6298 VOS_STATUS status;
6299
6300 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6301
6302 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6303 {
6304 pAdapter = pAdapterNode->pAdapter;
6305
6306 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6307 IFNAMSIZ ) )
6308 {
6309 return pAdapter;
6310 }
6311 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6312 pAdapterNode = pNext;
6313 }
6314
6315 return NULL;
6316
6317}
6318
6319hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6320{
6321 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6322 hdd_adapter_t *pAdapter;
6323 VOS_STATUS status;
6324
6325 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6326
6327 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6328 {
6329 pAdapter = pAdapterNode->pAdapter;
6330
6331 if( pAdapter && (mode == pAdapter->device_mode) )
6332 {
6333 return pAdapter;
6334 }
6335 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6336 pAdapterNode = pNext;
6337 }
6338
6339 return NULL;
6340
6341}
6342
6343//Remove this function later
6344hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6345{
6346 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6347 hdd_adapter_t *pAdapter;
6348 VOS_STATUS status;
6349
6350 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6351
6352 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6353 {
6354 pAdapter = pAdapterNode->pAdapter;
6355
6356 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6357 {
6358 return pAdapter;
6359 }
6360
6361 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6362 pAdapterNode = pNext;
6363 }
6364
6365 return NULL;
6366
6367}
6368
Jeff Johnson295189b2012-06-20 16:38:30 -07006369/**---------------------------------------------------------------------------
6370
6371 \brief hdd_set_monitor_tx_adapter() -
6372
6373 This API initializes the adapter to be used while transmitting on monitor
6374 adapter.
6375
6376 \param - pHddCtx - Pointer to the HDD context.
6377 pAdapter - Adapter that will used for TX. This can be NULL.
6378 \return - None.
6379 --------------------------------------------------------------------------*/
6380void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6381{
6382 hdd_adapter_t *pMonAdapter;
6383
6384 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6385
6386 if( NULL != pMonAdapter )
6387 {
6388 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6389 }
6390}
Jeff Johnson295189b2012-06-20 16:38:30 -07006391/**---------------------------------------------------------------------------
6392
6393 \brief hdd_select_queue() -
6394
6395 This API returns the operating channel of the requested device mode
6396
6397 \param - pHddCtx - Pointer to the HDD context.
6398 - mode - Device mode for which operating channel is required
6399 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6400 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6401 \return - channel number. "0" id the requested device is not found OR it is not connected.
6402 --------------------------------------------------------------------------*/
6403v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6404{
6405 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6406 VOS_STATUS status;
6407 hdd_adapter_t *pAdapter;
6408 v_U8_t operatingChannel = 0;
6409
6410 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6411
6412 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6413 {
6414 pAdapter = pAdapterNode->pAdapter;
6415
6416 if( mode == pAdapter->device_mode )
6417 {
6418 switch(pAdapter->device_mode)
6419 {
6420 case WLAN_HDD_INFRA_STATION:
6421 case WLAN_HDD_P2P_CLIENT:
6422 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6423 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6424 break;
6425 case WLAN_HDD_SOFTAP:
6426 case WLAN_HDD_P2P_GO:
6427 /*softap connection info */
6428 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6429 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6430 break;
6431 default:
6432 break;
6433 }
6434
6435 break; //Found the device of interest. break the loop
6436 }
6437
6438 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6439 pAdapterNode = pNext;
6440 }
6441 return operatingChannel;
6442}
6443
6444#ifdef WLAN_FEATURE_PACKET_FILTERING
6445/**---------------------------------------------------------------------------
6446
6447 \brief hdd_set_multicast_list() -
6448
6449 This used to set the multicast address list.
6450
6451 \param - dev - Pointer to the WLAN device.
6452 - skb - Pointer to OS packet (sk_buff).
6453 \return - success/fail
6454
6455 --------------------------------------------------------------------------*/
6456static void hdd_set_multicast_list(struct net_device *dev)
6457{
6458 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 int mc_count;
6460 int i = 0;
6461 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306462
6463 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006464 {
6465 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306466 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 return;
6468 }
6469
6470 if (dev->flags & IFF_ALLMULTI)
6471 {
6472 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006473 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306474 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 }
6476 else
6477 {
6478 mc_count = netdev_mc_count(dev);
6479 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006480 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6482 {
6483 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006484 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306485 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 return;
6487 }
6488
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306489 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006490
6491 netdev_for_each_mc_addr(ha, dev) {
6492 if (i == mc_count)
6493 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306494 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6495 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6496 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006497 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306498 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006499 i++;
6500 }
6501 }
6502 return;
6503}
6504#endif
6505
6506/**---------------------------------------------------------------------------
6507
6508 \brief hdd_select_queue() -
6509
6510 This function is registered with the Linux OS for network
6511 core to decide which queue to use first.
6512
6513 \param - dev - Pointer to the WLAN device.
6514 - skb - Pointer to OS packet (sk_buff).
6515 \return - ac, Queue Index/access category corresponding to UP in IP header
6516
6517 --------------------------------------------------------------------------*/
6518v_U16_t hdd_select_queue(struct net_device *dev,
6519 struct sk_buff *skb)
6520{
6521 return hdd_wmm_select_queue(dev, skb);
6522}
6523
6524
6525/**---------------------------------------------------------------------------
6526
6527 \brief hdd_wlan_initial_scan() -
6528
6529 This function triggers the initial scan
6530
6531 \param - pAdapter - Pointer to the HDD adapter.
6532
6533 --------------------------------------------------------------------------*/
6534void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6535{
6536 tCsrScanRequest scanReq;
6537 tCsrChannelInfo channelInfo;
6538 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006539 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6541
6542 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6543 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6544 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6545
6546 if(sme_Is11dSupported(pHddCtx->hHal))
6547 {
6548 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6549 if ( HAL_STATUS_SUCCESS( halStatus ) )
6550 {
6551 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6552 if( !scanReq.ChannelInfo.ChannelList )
6553 {
6554 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6555 vos_mem_free(channelInfo.ChannelList);
6556 return;
6557 }
6558 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6559 channelInfo.numOfChannels);
6560 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6561 vos_mem_free(channelInfo.ChannelList);
6562 }
6563
6564 scanReq.scanType = eSIR_PASSIVE_SCAN;
6565 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6566 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6567 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6568 }
6569 else
6570 {
6571 scanReq.scanType = eSIR_ACTIVE_SCAN;
6572 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6573 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6574 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6575 }
6576
6577 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6578 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6579 {
6580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6581 __func__, halStatus );
6582 }
6583
6584 if(sme_Is11dSupported(pHddCtx->hHal))
6585 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6586}
6587
6588struct fullPowerContext
6589{
6590 struct completion completion;
6591 unsigned int magic;
6592};
6593#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6594
6595/**---------------------------------------------------------------------------
6596
6597 \brief hdd_full_power_callback() - HDD full power callback function
6598
6599 This is the function invoked by SME to inform the result of a full power
6600 request issued by HDD
6601
6602 \param - callbackcontext - Pointer to cookie
6603 \param - status - result of request
6604
6605 \return - None
6606
6607 --------------------------------------------------------------------------*/
6608static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6609{
6610 struct fullPowerContext *pContext = callbackContext;
6611
6612 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306613 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006614
6615 if (NULL == callbackContext)
6616 {
6617 hddLog(VOS_TRACE_LEVEL_ERROR,
6618 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006619 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006620 return;
6621 }
6622
6623 /* there is a race condition that exists between this callback function
6624 and the caller since the caller could time out either before or
6625 while this code is executing. we'll assume the timeout hasn't
6626 occurred, but we'll verify that right before we save our work */
6627
6628 if (POWER_CONTEXT_MAGIC != pContext->magic)
6629 {
6630 /* the caller presumably timed out so there is nothing we can do */
6631 hddLog(VOS_TRACE_LEVEL_WARN,
6632 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006633 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006634 return;
6635 }
6636
6637 /* the race is on. caller could have timed out immediately after
6638 we verified the magic, but if so, caller will wait a short time
6639 for us to notify the caller, so the context will stay valid */
6640 complete(&pContext->completion);
6641}
6642
6643/**---------------------------------------------------------------------------
6644
6645 \brief hdd_wlan_exit() - HDD WLAN exit function
6646
6647 This is the driver exit point (invoked during rmmod)
6648
6649 \param - pHddCtx - Pointer to the HDD Context
6650
6651 \return - None
6652
6653 --------------------------------------------------------------------------*/
6654void hdd_wlan_exit(hdd_context_t *pHddCtx)
6655{
6656 eHalStatus halStatus;
6657 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6658 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306659 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006660 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006661 struct fullPowerContext powerContext;
6662 long lrc;
6663
6664 ENTER();
6665
Jeff Johnson88ba7742013-02-27 14:36:02 -08006666 if (VOS_FTM_MODE != hdd_get_conparam())
6667 {
6668 // Unloading, restart logic is no more required.
6669 wlan_hdd_restart_deinit(pHddCtx);
6670 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006671
Jeff Johnson295189b2012-06-20 16:38:30 -07006672 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006674 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006675 {
6676 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6677 WLAN_HDD_INFRA_STATION);
6678 if (pAdapter == NULL)
6679 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6680
6681 if (pAdapter != NULL)
6682 {
6683 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6684 hdd_UnregisterWext(pAdapter->dev);
6685 }
6686 }
6687 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006688
Jeff Johnson295189b2012-06-20 16:38:30 -07006689 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006690 {
6691 wlan_hdd_ftm_close(pHddCtx);
6692 goto free_hdd_ctx;
6693 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006694 //Stop the Interface TX queue.
6695 //netif_tx_disable(pWlanDev);
6696 //netif_carrier_off(pWlanDev);
6697
Jeff Johnson295189b2012-06-20 16:38:30 -07006698 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6699 {
6700 pAdapter = hdd_get_adapter(pHddCtx,
6701 WLAN_HDD_SOFTAP);
6702 }
6703 else
6704 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006705 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006706 {
6707 pAdapter = hdd_get_adapter(pHddCtx,
6708 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006709 if (pAdapter == NULL)
6710 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006711 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 /* DeRegister with platform driver as client for Suspend/Resume */
6714 vosStatus = hddDeregisterPmOps(pHddCtx);
6715 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6716 {
6717 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6718 VOS_ASSERT(0);
6719 }
6720
6721 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6722 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6723 {
6724 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006726
6727 // Cancel any outstanding scan requests. We are about to close all
6728 // of our adapters, but an adapter structure is what SME passes back
6729 // to our callback function. Hence if there are any outstanding scan
6730 // requests then there is a race condition between when the adapter
6731 // is closed and when the callback is invoked. We try to resolve that
6732 // race condition here by canceling any outstanding scans before we
6733 // close the adapters.
6734 // Note that the scans may be cancelled in an asynchronous manner, so
6735 // ideally there needs to be some kind of synchronization. Rather than
6736 // introduce a new synchronization here, we will utilize the fact that
6737 // we are about to Request Full Power, and since that is synchronized,
6738 // the expectation is that by the time Request Full Power has completed,
6739 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006740 if (NULL != pAdapter)
6741 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6742 else
6743 hddLog(VOS_TRACE_LEVEL_ERROR,
6744 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006745
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006746 //Stop the traffic monitor timer
6747 if ( VOS_TIMER_STATE_RUNNING ==
6748 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6749 {
6750 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6751 }
6752
6753 // Destroy the traffic monitor timer
6754 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6755 &pHddCtx->tx_rx_trafficTmr)))
6756 {
6757 hddLog(VOS_TRACE_LEVEL_ERROR,
6758 "%s: Cannot deallocate Traffic monitor timer", __func__);
6759 }
6760
Jeff Johnson295189b2012-06-20 16:38:30 -07006761 //Disable IMPS/BMPS as we do not want the device to enter any power
6762 //save mode during shutdown
6763 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6764 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6765 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6766
6767 //Ensure that device is in full power as we will touch H/W during vos_Stop
6768 init_completion(&powerContext.completion);
6769 powerContext.magic = POWER_CONTEXT_MAGIC;
6770
6771 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6772 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6773
6774 if (eHAL_STATUS_SUCCESS != halStatus)
6775 {
6776 if (eHAL_STATUS_PMC_PENDING == halStatus)
6777 {
6778 /* request was sent -- wait for the response */
6779 lrc = wait_for_completion_interruptible_timeout(
6780 &powerContext.completion,
6781 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6782 /* either we have a response or we timed out
6783 either way, first invalidate our magic */
6784 powerContext.magic = 0;
6785 if (lrc <= 0)
6786 {
6787 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006788 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006789 /* there is a race condition such that the callback
6790 function could be executing at the same time we are. of
6791 primary concern is if the callback function had already
6792 verified the "magic" but hasn't yet set the completion
6793 variable. Since the completion variable is on our
6794 stack, we'll delay just a bit to make sure the data is
6795 still valid if that is the case */
6796 msleep(50);
6797 }
6798 }
6799 else
6800 {
6801 hddLog(VOS_TRACE_LEVEL_ERROR,
6802 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006803 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006804 VOS_ASSERT(0);
6805 /* continue -- need to clean up as much as possible */
6806 }
6807 }
6808
Yue Ma0d4891e2013-08-06 17:01:45 -07006809 hdd_debugfs_exit(pHddCtx);
6810
Jeff Johnson295189b2012-06-20 16:38:30 -07006811 // Unregister the Net Device Notifier
6812 unregister_netdevice_notifier(&hdd_netdev_notifier);
6813
Jeff Johnson295189b2012-06-20 16:38:30 -07006814 hdd_stop_all_adapters( pHddCtx );
6815
Jeff Johnson295189b2012-06-20 16:38:30 -07006816#ifdef WLAN_BTAMP_FEATURE
6817 vosStatus = WLANBAP_Stop(pVosContext);
6818 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6819 {
6820 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6821 "%s: Failed to stop BAP",__func__);
6822 }
6823#endif //WLAN_BTAMP_FEATURE
6824
6825 //Stop all the modules
6826 vosStatus = vos_stop( pVosContext );
6827 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6828 {
6829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6830 "%s: Failed to stop VOSS",__func__);
6831 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6832 }
6833
Jeff Johnson295189b2012-06-20 16:38:30 -07006834 //Assert Deep sleep signal now to put Libra HW in lowest power state
6835 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6836 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6837
6838 //Vote off any PMIC voltage supplies
6839 vos_chipPowerDown(NULL, NULL, NULL);
6840
6841 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6842
Leo Chang59cdc7e2013-07-10 10:08:21 -07006843
Jeff Johnson295189b2012-06-20 16:38:30 -07006844 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006845 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006846
6847 //Close the scheduler before calling vos_close to make sure no thread is
6848 // scheduled after the each module close is called i.e after all the data
6849 // structures are freed.
6850 vosStatus = vos_sched_close( pVosContext );
6851 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6852 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6853 "%s: Failed to close VOSS Scheduler",__func__);
6854 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6855 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006856#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006857#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6858 /* Destroy the wake lock */
6859 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6860#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006861 /* Destroy the wake lock */
6862 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006863#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006864
6865 //Close VOSS
6866 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6867 vos_close(pVosContext);
6868
Jeff Johnson295189b2012-06-20 16:38:30 -07006869 //Close Watchdog
6870 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6871 vos_watchdog_close(pVosContext);
6872
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306873 //Clean up HDD Nlink Service
6874 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006875#ifdef WLAN_KD_READY_NOTIFIER
6876 nl_srv_exit(pHddCtx->ptt_pid);
6877#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306878 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006879#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306880
Jeff Johnson295189b2012-06-20 16:38:30 -07006881 /* Cancel the vote for XO Core ON.
6882 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6883 * exited at this point
6884 */
6885 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6886 " when WLAN is turned OFF\n");
6887 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6888 {
6889 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6890 " Not returning failure."
6891 " Power consumed will be high\n");
6892 }
6893
6894 hdd_close_all_adapters( pHddCtx );
6895
6896
6897 //Free up dynamically allocated members inside HDD Adapter
6898 kfree(pHddCtx->cfg_ini);
6899 pHddCtx->cfg_ini= NULL;
6900
6901 /* free the power on lock from platform driver */
6902 if (free_riva_power_on_lock("wlan"))
6903 {
6904 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6905 __func__);
6906 }
6907
Jeff Johnson88ba7742013-02-27 14:36:02 -08006908free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006909 /* FTM mode, WIPHY did not registered
6910 If un-register here, system crash will happen */
6911 if (VOS_FTM_MODE != hdd_get_conparam())
6912 {
6913 wiphy_unregister(wiphy) ;
6914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006915 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006916 if (hdd_is_ssr_required())
6917 {
6918 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006919 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006920 msleep(5000);
6921 }
6922 hdd_set_ssr_required (VOS_FALSE);
6923}
6924
6925
6926/**---------------------------------------------------------------------------
6927
6928 \brief hdd_update_config_from_nv() - Function to update the contents of
6929 the running configuration with parameters taken from NV storage
6930
6931 \param - pHddCtx - Pointer to the HDD global context
6932
6933 \return - VOS_STATUS_SUCCESS if successful
6934
6935 --------------------------------------------------------------------------*/
6936static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6937{
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 v_BOOL_t itemIsValid = VOS_FALSE;
6939 VOS_STATUS status;
6940 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6941 v_U8_t macLoop;
6942
6943 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6944 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6945 if(status != VOS_STATUS_SUCCESS)
6946 {
6947 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6948 return VOS_STATUS_E_FAILURE;
6949 }
6950
6951 if (itemIsValid == VOS_TRUE)
6952 {
6953 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6954 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6955 VOS_MAX_CONCURRENCY_PERSONA);
6956 if(status != VOS_STATUS_SUCCESS)
6957 {
6958 /* Get MAC from NV fail, not update CFG info
6959 * INI MAC value will be used for MAC setting */
6960 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6961 return VOS_STATUS_E_FAILURE;
6962 }
6963
6964 /* If first MAC is not valid, treat all others are not valid
6965 * Then all MACs will be got from ini file */
6966 if(vos_is_macaddr_zero(&macFromNV[0]))
6967 {
6968 /* MAC address in NV file is not configured yet */
6969 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6970 return VOS_STATUS_E_INVAL;
6971 }
6972
6973 /* Get MAC address from NV, update CFG info */
6974 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6975 {
6976 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6977 {
6978 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6979 /* This MAC is not valid, skip it
6980 * This MAC will be got from ini file */
6981 }
6982 else
6983 {
6984 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6985 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6986 VOS_MAC_ADDR_SIZE);
6987 }
6988 }
6989 }
6990 else
6991 {
6992 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6993 return VOS_STATUS_E_FAILURE;
6994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006995
Jeff Johnson295189b2012-06-20 16:38:30 -07006996
6997 return VOS_STATUS_SUCCESS;
6998}
6999
7000/**---------------------------------------------------------------------------
7001
7002 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7003
7004 \param - pAdapter - Pointer to the HDD
7005
7006 \return - None
7007
7008 --------------------------------------------------------------------------*/
7009VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7010{
7011 eHalStatus halStatus;
7012 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307013 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007014
Jeff Johnson295189b2012-06-20 16:38:30 -07007015
7016 // Send ready indication to the HDD. This will kick off the MAC
7017 // into a 'running' state and should kick off an initial scan.
7018 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7019 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7020 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307021 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 "code %08d [x%08x]",__func__, halStatus, halStatus );
7023 return VOS_STATUS_E_FAILURE;
7024 }
7025
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307026 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007027 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7028 // And RIVA will crash
7029 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7030 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307031 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7032 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7033
7034
Jeff Johnson295189b2012-06-20 16:38:30 -07007035 return VOS_STATUS_SUCCESS;
7036}
7037
Jeff Johnson295189b2012-06-20 16:38:30 -07007038/* wake lock APIs for HDD */
7039void hdd_prevent_suspend(void)
7040{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007041#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007042 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007043#else
7044 wcnss_prevent_suspend();
7045#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007046}
7047
7048void hdd_allow_suspend(void)
7049{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007050#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007052#else
7053 wcnss_allow_suspend();
7054#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007055}
7056
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007057void hdd_allow_suspend_timeout(v_U32_t timeout)
7058{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007059#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007060 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007061#else
7062 /* Do nothing as there is no API in wcnss for timeout*/
7063#endif
7064}
7065
Jeff Johnson295189b2012-06-20 16:38:30 -07007066/**---------------------------------------------------------------------------
7067
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007068 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7069 information between Host and Riva
7070
7071 This function gets reported version of FW
7072 It also finds the version of Riva headers used to compile the host
7073 It compares the above two and prints a warning if they are different
7074 It gets the SW and HW version string
7075 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7076 indicating the features they support through a bitmap
7077
7078 \param - pHddCtx - Pointer to HDD context
7079
7080 \return - void
7081
7082 --------------------------------------------------------------------------*/
7083
7084void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7085{
7086
7087 tSirVersionType versionCompiled;
7088 tSirVersionType versionReported;
7089 tSirVersionString versionString;
7090 tANI_U8 fwFeatCapsMsgSupported = 0;
7091 VOS_STATUS vstatus;
7092
7093 /* retrieve and display WCNSS version information */
7094 do {
7095
7096 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7097 &versionCompiled);
7098 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7099 {
7100 hddLog(VOS_TRACE_LEVEL_FATAL,
7101 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007102 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007103 break;
7104 }
7105
7106 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7107 &versionReported);
7108 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7109 {
7110 hddLog(VOS_TRACE_LEVEL_FATAL,
7111 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007112 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007113 break;
7114 }
7115
7116 if ((versionCompiled.major != versionReported.major) ||
7117 (versionCompiled.minor != versionReported.minor) ||
7118 (versionCompiled.version != versionReported.version) ||
7119 (versionCompiled.revision != versionReported.revision))
7120 {
7121 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7122 "Host expected %u.%u.%u.%u\n",
7123 WLAN_MODULE_NAME,
7124 (int)versionReported.major,
7125 (int)versionReported.minor,
7126 (int)versionReported.version,
7127 (int)versionReported.revision,
7128 (int)versionCompiled.major,
7129 (int)versionCompiled.minor,
7130 (int)versionCompiled.version,
7131 (int)versionCompiled.revision);
7132 }
7133 else
7134 {
7135 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7136 WLAN_MODULE_NAME,
7137 (int)versionReported.major,
7138 (int)versionReported.minor,
7139 (int)versionReported.version,
7140 (int)versionReported.revision);
7141 }
7142
7143 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7144 versionString,
7145 sizeof(versionString));
7146 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7147 {
7148 hddLog(VOS_TRACE_LEVEL_FATAL,
7149 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007150 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007151 break;
7152 }
7153
7154 pr_info("%s: WCNSS software version %s\n",
7155 WLAN_MODULE_NAME, versionString);
7156
7157 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7158 versionString,
7159 sizeof(versionString));
7160 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7161 {
7162 hddLog(VOS_TRACE_LEVEL_FATAL,
7163 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007164 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007165 break;
7166 }
7167
7168 pr_info("%s: WCNSS hardware version %s\n",
7169 WLAN_MODULE_NAME, versionString);
7170
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007171 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7172 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007173 send the message only if it the riva is 1.1
7174 minor numbers for different riva branches:
7175 0 -> (1.0)Mainline Build
7176 1 -> (1.1)Mainline Build
7177 2->(1.04) Stability Build
7178 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007179 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007180 ((versionReported.minor>=1) && (versionReported.version>=1)))
7181 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7182 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007183
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007184 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007185 {
7186#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7187 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7188 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7189#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007190 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7191 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7192 {
7193 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7194 }
7195
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007196 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007197 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007198
7199 } while (0);
7200
7201}
7202
7203/**---------------------------------------------------------------------------
7204
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307205 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7206
7207 \param - pHddCtx - Pointer to the hdd context
7208
7209 \return - true if hardware supports 5GHz
7210
7211 --------------------------------------------------------------------------*/
7212static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7213{
7214 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7215 * then hardware support 5Ghz.
7216 */
7217 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7218 {
7219 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7220 return true;
7221 }
7222 else
7223 {
7224 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7225 __func__);
7226 return false;
7227 }
7228}
7229
7230
7231/**---------------------------------------------------------------------------
7232
Jeff Johnson295189b2012-06-20 16:38:30 -07007233 \brief hdd_wlan_startup() - HDD init function
7234
7235 This is the driver startup code executed once a WLAN device has been detected
7236
7237 \param - dev - Pointer to the underlying device
7238
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007239 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007240
7241 --------------------------------------------------------------------------*/
7242
7243int hdd_wlan_startup(struct device *dev )
7244{
7245 VOS_STATUS status;
7246 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007247 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007248 hdd_context_t *pHddCtx = NULL;
7249 v_CONTEXT_t pVosContext= NULL;
7250#ifdef WLAN_BTAMP_FEATURE
7251 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7252 WLANBAP_ConfigType btAmpConfig;
7253 hdd_config_t *pConfig;
7254#endif
7255 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007256 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007257
7258 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007259 /*
7260 * cfg80211: wiphy allocation
7261 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307262 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007263
7264 if(wiphy == NULL)
7265 {
7266 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007267 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 }
7269
7270 pHddCtx = wiphy_priv(wiphy);
7271
Jeff Johnson295189b2012-06-20 16:38:30 -07007272 //Initialize the adapter context to zeros.
7273 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7274
Jeff Johnson295189b2012-06-20 16:38:30 -07007275 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007276 hdd_prevent_suspend();
7277 pHddCtx->isLoadUnloadInProgress = TRUE;
7278
7279 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7280
7281 /*Get vos context here bcoz vos_open requires it*/
7282 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7283
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007284 if(pVosContext == NULL)
7285 {
7286 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7287 goto err_free_hdd_context;
7288 }
7289
Jeff Johnson295189b2012-06-20 16:38:30 -07007290 //Save the Global VOSS context in adapter context for future.
7291 pHddCtx->pvosContext = pVosContext;
7292
7293 //Save the adapter context in global context for future.
7294 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7295
Jeff Johnson295189b2012-06-20 16:38:30 -07007296 pHddCtx->parent_dev = dev;
7297
7298 init_completion(&pHddCtx->full_pwr_comp_var);
7299 init_completion(&pHddCtx->standby_comp_var);
7300 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007301 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007302 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307303 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007304
7305#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007306 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007307#else
7308 init_completion(&pHddCtx->driver_crda_req);
7309#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007310
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307311 spin_lock_init(&pHddCtx->schedScan_lock);
7312
Jeff Johnson295189b2012-06-20 16:38:30 -07007313 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7314
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307315#ifdef FEATURE_WLAN_TDLS
7316 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7317 * invoked by other instances also) to protect the concurrent
7318 * access for the Adapters by TDLS module.
7319 */
7320 mutex_init(&pHddCtx->tdls_lock);
7321#endif
7322
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307323 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007324 // Load all config first as TL config is needed during vos_open
7325 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7326 if(pHddCtx->cfg_ini == NULL)
7327 {
7328 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7329 goto err_free_hdd_context;
7330 }
7331
7332 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7333
7334 // Read and parse the qcom_cfg.ini file
7335 status = hdd_parse_config_ini( pHddCtx );
7336 if ( VOS_STATUS_SUCCESS != status )
7337 {
7338 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7339 __func__, WLAN_INI_FILE);
7340 goto err_config;
7341 }
7342
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307343 /* INI has been read, initialise the configuredMcastBcastFilter with
7344 * INI value as this will serve as the default value
7345 */
7346 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7347 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7348 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307349
7350 if (false == hdd_is_5g_supported(pHddCtx))
7351 {
7352 //5Ghz is not supported.
7353 if (1 != pHddCtx->cfg_ini->nBandCapability)
7354 {
7355 hddLog(VOS_TRACE_LEVEL_INFO,
7356 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7357 pHddCtx->cfg_ini->nBandCapability = 1;
7358 }
7359 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307360
7361 /* If SNR Monitoring is enabled, FW has to parse all beacons
7362 * for calcaluting and storing the average SNR, so set Nth beacon
7363 * filter to 1 to enable FW to parse all the beaocons
7364 */
7365 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7366 {
7367 /* The log level is deliberately set to WARN as overriding
7368 * nthBeaconFilter to 1 will increase power cosumption and this
7369 * might just prove helpful to detect the power issue.
7370 */
7371 hddLog(VOS_TRACE_LEVEL_WARN,
7372 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7373 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007375 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307376 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007377 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307378 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007379 {
7380 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307381 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7382 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007384
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007385 // Update VOS trace levels based upon the cfg.ini
7386 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7387 pHddCtx->cfg_ini->vosTraceEnableBAP);
7388 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7389 pHddCtx->cfg_ini->vosTraceEnableTL);
7390 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7391 pHddCtx->cfg_ini->vosTraceEnableWDI);
7392 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7393 pHddCtx->cfg_ini->vosTraceEnableHDD);
7394 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7395 pHddCtx->cfg_ini->vosTraceEnableSME);
7396 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7397 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307398 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7399 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007400 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7401 pHddCtx->cfg_ini->vosTraceEnableWDA);
7402 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7403 pHddCtx->cfg_ini->vosTraceEnableSYS);
7404 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7405 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007406 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7407 pHddCtx->cfg_ini->vosTraceEnableSAP);
7408 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7409 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007410
Jeff Johnson295189b2012-06-20 16:38:30 -07007411 // Update WDI trace levels based upon the cfg.ini
7412 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7413 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7414 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7415 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7416 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7417 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7418 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7419 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007420
Jeff Johnson88ba7742013-02-27 14:36:02 -08007421 if (VOS_FTM_MODE == hdd_get_conparam())
7422 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007423 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7424 {
7425 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7426 goto err_free_hdd_context;
7427 }
7428 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7429 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007430 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007431
Jeff Johnson88ba7742013-02-27 14:36:02 -08007432 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007433 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7434 {
7435 status = vos_watchdog_open(pVosContext,
7436 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7437
7438 if(!VOS_IS_STATUS_SUCCESS( status ))
7439 {
7440 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307441 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007442 }
7443 }
7444
7445 pHddCtx->isLogpInProgress = FALSE;
7446 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7447
Jeff Johnson295189b2012-06-20 16:38:30 -07007448 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7449 if(!VOS_IS_STATUS_SUCCESS(status))
7450 {
7451 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007452 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007453 }
7454
Amar Singhala49cbc52013-10-08 18:37:44 -07007455#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007456 /* initialize the NV module. This is required so that
7457 we can initialize the channel information in wiphy
7458 from the NV.bin data. The channel information in
7459 wiphy needs to be initialized before wiphy registration */
7460
7461 status = vos_nv_open();
7462 if (!VOS_IS_STATUS_SUCCESS(status))
7463 {
7464 /* NV module cannot be initialized */
7465 hddLog( VOS_TRACE_LEVEL_FATAL,
7466 "%s: vos_nv_open failed", __func__);
7467 goto err_clkvote;
7468 }
7469
7470 status = vos_init_wiphy_from_nv_bin();
7471 if (!VOS_IS_STATUS_SUCCESS(status))
7472 {
7473 /* NV module cannot be initialized */
7474 hddLog( VOS_TRACE_LEVEL_FATAL,
7475 "%s: vos_init_wiphy failed", __func__);
7476 goto err_vos_nv_close;
7477 }
7478
Amar Singhala49cbc52013-10-08 18:37:44 -07007479 /* registration of wiphy dev with cfg80211 */
7480 if (0 > wlan_hdd_cfg80211_register(wiphy))
7481 {
7482 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007483 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007484 }
7485#endif
7486
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 status = vos_open( &pVosContext, 0);
7488 if ( !VOS_IS_STATUS_SUCCESS( status ))
7489 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007490 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007491 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007492 }
7493
Jeff Johnson295189b2012-06-20 16:38:30 -07007494 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7495
7496 if ( NULL == pHddCtx->hHal )
7497 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007498 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007499 goto err_vosclose;
7500 }
7501
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007502 status = vos_preStart( pHddCtx->pvosContext );
7503 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7504 {
7505 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7506 goto err_vosclose;
7507 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007508
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007509 /* Note that the vos_preStart() sequence triggers the cfg download.
7510 The cfg download must occur before we update the SME config
7511 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007512 status = hdd_set_sme_config( pHddCtx );
7513
7514 if ( VOS_STATUS_SUCCESS != status )
7515 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007516 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7517 goto err_vosclose;
7518 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007519
7520 //Initialize the WMM module
7521 status = hdd_wmm_init(pHddCtx);
7522 if (!VOS_IS_STATUS_SUCCESS(status))
7523 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007524 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007525 goto err_vosclose;
7526 }
7527
Jeff Johnson295189b2012-06-20 16:38:30 -07007528 /* In the integrated architecture we update the configuration from
7529 the INI file and from NV before vOSS has been started so that
7530 the final contents are available to send down to the cCPU */
7531
7532 // Apply the cfg.ini to cfg.dat
7533 if (FALSE == hdd_update_config_dat(pHddCtx))
7534 {
7535 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7536 goto err_vosclose;
7537 }
7538
7539 // Apply the NV to cfg.dat
7540 /* Prima Update MAC address only at here */
7541 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7542 {
7543#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7544 /* There was not a valid set of MAC Addresses in NV. See if the
7545 default addresses were modified by the cfg.ini settings. If so,
7546 we'll use them, but if not, we'll autogenerate a set of MAC
7547 addresses based upon the device serial number */
7548
7549 static const v_MACADDR_t default_address =
7550 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7551 unsigned int serialno;
7552 int i;
7553
7554 serialno = wcnss_get_serial_number();
7555 if ((0 != serialno) &&
7556 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7557 sizeof(default_address))))
7558 {
7559 /* cfg.ini has the default address, invoke autogen logic */
7560
7561 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7562 bytes of the serial number that can be used to generate
7563 the other 3 bytes of the MAC address. Mask off all but
7564 the lower 3 bytes (this will also make sure we don't
7565 overflow in the next step) */
7566 serialno &= 0x00FFFFFF;
7567
7568 /* we need a unique address for each session */
7569 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7570
7571 /* autogen all addresses */
7572 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7573 {
7574 /* start with the entire default address */
7575 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7576 /* then replace the lower 3 bytes */
7577 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7578 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7579 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7580
7581 serialno++;
7582 }
7583
7584 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7585 MAC_ADDRESS_STR,
7586 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7587 }
7588 else
7589#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7590 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007591 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007592 "%s: Invalid MAC address in NV, using MAC from ini file "
7593 MAC_ADDRESS_STR, __func__,
7594 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7595 }
7596 }
7597 {
7598 eHalStatus halStatus;
7599 // Set the MAC Address
7600 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7601 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7602 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7603 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7604
7605 if (!HAL_STATUS_SUCCESS( halStatus ))
7606 {
7607 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7608 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007609 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 }
7611 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007612
7613 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7614 Note: Firmware image will be read and downloaded inside vos_start API */
7615 status = vos_start( pHddCtx->pvosContext );
7616 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7617 {
7618 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7619 goto err_vosclose;
7620 }
7621
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007622 /* Exchange capability info between Host and FW and also get versioning info from FW */
7623 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007624
7625 status = hdd_post_voss_start_config( pHddCtx );
7626 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7627 {
7628 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7629 __func__);
7630 goto err_vosstop;
7631 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007632
7633#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307634 wlan_hdd_cfg80211_update_reg_info( wiphy );
7635
7636 /* registration of wiphy dev with cfg80211 */
7637 if (0 > wlan_hdd_cfg80211_register(wiphy))
7638 {
7639 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7640 goto err_vosstop;
7641 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007642#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007643
Jeff Johnson295189b2012-06-20 16:38:30 -07007644 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7645 {
7646 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7647 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7648 }
7649 else
7650 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007651 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7652 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7653 if (pAdapter != NULL)
7654 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307655 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007656 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307657 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7658 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7659 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007660
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307661 /* Generate the P2P Device Address. This consists of the device's
7662 * primary MAC address with the locally administered bit set.
7663 */
7664 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007665 }
7666 else
7667 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307668 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7669 if (p2p_dev_addr != NULL)
7670 {
7671 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7672 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7673 }
7674 else
7675 {
7676 hddLog(VOS_TRACE_LEVEL_FATAL,
7677 "%s: Failed to allocate mac_address for p2p_device",
7678 __func__);
7679 goto err_close_adapter;
7680 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007681 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007682
7683 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7684 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7685 if ( NULL == pP2pAdapter )
7686 {
7687 hddLog(VOS_TRACE_LEVEL_FATAL,
7688 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007689 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007690 goto err_close_adapter;
7691 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007692 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007694
7695 if( pAdapter == NULL )
7696 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7698 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007700
Jeff Johnson295189b2012-06-20 16:38:30 -07007701#ifdef WLAN_BTAMP_FEATURE
7702 vStatus = WLANBAP_Open(pVosContext);
7703 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7704 {
7705 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7706 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007707 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007708 }
7709
7710 vStatus = BSL_Init(pVosContext);
7711 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7712 {
7713 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7714 "%s: Failed to Init BSL",__func__);
7715 goto err_bap_close;
7716 }
7717 vStatus = WLANBAP_Start(pVosContext);
7718 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7719 {
7720 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7721 "%s: Failed to start TL",__func__);
7722 goto err_bap_close;
7723 }
7724
7725 pConfig = pHddCtx->cfg_ini;
7726 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7727 status = WLANBAP_SetConfig(&btAmpConfig);
7728
7729#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007730
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007731#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7732 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7733 {
7734 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7735 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7736 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7737 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7738 }
7739#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007740#ifdef FEATURE_WLAN_SCAN_PNO
7741 /*SME must send channel update configuration to RIVA*/
7742 sme_UpdateChannelConfig(pHddCtx->hHal);
7743#endif
7744
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 /* Register with platform driver as client for Suspend/Resume */
7746 status = hddRegisterPmOps(pHddCtx);
7747 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7748 {
7749 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7750#ifdef WLAN_BTAMP_FEATURE
7751 goto err_bap_stop;
7752#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007753 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007754#endif //WLAN_BTAMP_FEATURE
7755 }
7756
Yue Ma0d4891e2013-08-06 17:01:45 -07007757 /* Open debugfs interface */
7758 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7759 {
7760 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7761 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007762 }
7763
Jeff Johnson295189b2012-06-20 16:38:30 -07007764 /* Register TM level change handler function to the platform */
7765 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7766 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7767 {
7768 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7769 goto err_unregister_pmops;
7770 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007771
7772 /* register for riva power on lock to platform driver */
7773 if (req_riva_power_on_lock("wlan"))
7774 {
7775 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7776 __func__);
7777 goto err_unregister_pmops;
7778 }
7779
Jeff Johnson295189b2012-06-20 16:38:30 -07007780 // register net device notifier for device change notification
7781 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7782
7783 if(ret < 0)
7784 {
7785 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7786 goto err_free_power_on_lock;
7787 }
7788
7789 //Initialize the nlink service
7790 if(nl_srv_init() != 0)
7791 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007793 goto err_reg_netdev;
7794 }
7795
Leo Chang4ce1cc52013-10-21 18:27:15 -07007796#ifdef WLAN_KD_READY_NOTIFIER
7797 pHddCtx->kd_nl_init = 1;
7798#endif /* WLAN_KD_READY_NOTIFIER */
7799
Jeff Johnson295189b2012-06-20 16:38:30 -07007800 //Initialize the BTC service
7801 if(btc_activate_service(pHddCtx) != 0)
7802 {
7803 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7804 goto err_nl_srv;
7805 }
7806
7807#ifdef PTT_SOCK_SVC_ENABLE
7808 //Initialize the PTT service
7809 if(ptt_sock_activate_svc(pHddCtx) != 0)
7810 {
7811 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7812 goto err_nl_srv;
7813 }
7814#endif
7815
Jeff Johnson295189b2012-06-20 16:38:30 -07007816 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007817 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007819 /* Action frame registered in one adapter which will
7820 * applicable to all interfaces
7821 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007822 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007823 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007824
7825 mutex_init(&pHddCtx->sap_lock);
7826
7827 pHddCtx->isLoadUnloadInProgress = FALSE;
7828
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007829#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007830#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7831 /* Initialize the wake lcok */
7832 wake_lock_init(&pHddCtx->rx_wake_lock,
7833 WAKE_LOCK_SUSPEND,
7834 "qcom_rx_wakelock");
7835#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007836 /* Initialize the wake lcok */
7837 wake_lock_init(&pHddCtx->sap_wake_lock,
7838 WAKE_LOCK_SUSPEND,
7839 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007840#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007841
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007842 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7843 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007844
7845 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7846 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307847
Jeff Johnsone7245742012-09-05 17:12:55 -07007848 // Initialize the restart logic
7849 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307850
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007851 //Register the traffic monitor timer now
7852 if ( pHddCtx->cfg_ini->dynSplitscan)
7853 {
7854 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7855 VOS_TIMER_TYPE_SW,
7856 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7857 (void *)pHddCtx);
7858 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007859 goto success;
7860
7861err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007862#ifdef WLAN_KD_READY_NOTIFIER
7863 nl_srv_exit(pHddCtx->ptt_pid);
7864#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007865 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007866#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007867err_reg_netdev:
7868 unregister_netdevice_notifier(&hdd_netdev_notifier);
7869
7870err_free_power_on_lock:
7871 free_riva_power_on_lock("wlan");
7872
7873err_unregister_pmops:
7874 hddDevTmUnregisterNotifyCallback(pHddCtx);
7875 hddDeregisterPmOps(pHddCtx);
7876
Yue Ma0d4891e2013-08-06 17:01:45 -07007877 hdd_debugfs_exit(pHddCtx);
7878
Jeff Johnson295189b2012-06-20 16:38:30 -07007879#ifdef WLAN_BTAMP_FEATURE
7880err_bap_stop:
7881 WLANBAP_Stop(pVosContext);
7882#endif
7883
7884#ifdef WLAN_BTAMP_FEATURE
7885err_bap_close:
7886 WLANBAP_Close(pVosContext);
7887#endif
7888
Jeff Johnson295189b2012-06-20 16:38:30 -07007889err_close_adapter:
7890 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007891
7892#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307893 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007894#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007895
7896err_vosstop:
7897 vos_stop(pVosContext);
7898
Amar Singhala49cbc52013-10-08 18:37:44 -07007899err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 status = vos_sched_close( pVosContext );
7901 if (!VOS_IS_STATUS_SUCCESS(status)) {
7902 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7903 "%s: Failed to close VOSS Scheduler", __func__);
7904 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7905 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007906 vos_close(pVosContext );
7907
7908err_wiphy_unregister:
7909
7910#ifdef CONFIG_ENABLE_LINUX_REG
7911 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007912
Amar Singhal0a402232013-10-11 20:57:16 -07007913err_vos_nv_close:
7914
7915 vos_nv_close();
7916
Jeff Johnson295189b2012-06-20 16:38:30 -07007917err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007918#endif
7919
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007920 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007921
7922err_wdclose:
7923 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7924 vos_watchdog_close(pVosContext);
7925
Jeff Johnson295189b2012-06-20 16:38:30 -07007926err_config:
7927 kfree(pHddCtx->cfg_ini);
7928 pHddCtx->cfg_ini= NULL;
7929
7930err_free_hdd_context:
7931 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007932 wiphy_free(wiphy) ;
7933 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007934 VOS_BUG(1);
7935
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007936 if (hdd_is_ssr_required())
7937 {
7938 /* WDI timeout had happened during load, so SSR is needed here */
7939 subsystem_restart("wcnss");
7940 msleep(5000);
7941 }
7942 hdd_set_ssr_required (VOS_FALSE);
7943
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007944 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007945
7946success:
7947 EXIT();
7948 return 0;
7949}
7950
7951/**---------------------------------------------------------------------------
7952
Jeff Johnson32d95a32012-09-10 13:15:23 -07007953 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007954
Jeff Johnson32d95a32012-09-10 13:15:23 -07007955 This is the driver entry point - called in different timeline depending
7956 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007957
7958 \param - None
7959
7960 \return - 0 for success, non zero for failure
7961
7962 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007963static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007964{
7965 VOS_STATUS status;
7966 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007967 struct device *dev = NULL;
7968 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007969#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7970 int max_retries = 0;
7971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007972
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307973#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7974 vos_wconn_trace_init();
7975#endif
7976
Jeff Johnson295189b2012-06-20 16:38:30 -07007977 ENTER();
7978
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007979#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007980 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007981#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007982
7983 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7984 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7985
7986 //Power Up Libra WLAN card first if not already powered up
7987 status = vos_chipPowerUp(NULL,NULL,NULL);
7988 if (!VOS_IS_STATUS_SUCCESS(status))
7989 {
7990 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7991 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307992#ifdef WLAN_OPEN_SOURCE
7993 wake_lock_destroy(&wlan_wake_lock);
7994#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007995 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007996 }
7997
Jeff Johnson295189b2012-06-20 16:38:30 -07007998#ifdef ANI_BUS_TYPE_PCI
7999
8000 dev = wcnss_wlan_get_device();
8001
8002#endif // ANI_BUS_TYPE_PCI
8003
8004#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008005
8006#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8007 /* wait until WCNSS driver downloads NV */
8008 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8009 msleep(1000);
8010 }
8011 if (max_retries >= 5) {
8012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308013#ifdef WLAN_OPEN_SOURCE
8014 wake_lock_destroy(&wlan_wake_lock);
8015#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008016 return -ENODEV;
8017 }
8018#endif
8019
Jeff Johnson295189b2012-06-20 16:38:30 -07008020 dev = wcnss_wlan_get_device();
8021#endif // ANI_BUS_TYPE_PLATFORM
8022
8023
8024 do {
8025 if (NULL == dev) {
8026 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8027 ret_status = -1;
8028 break;
8029 }
8030
8031#ifdef MEMORY_DEBUG
8032 vos_mem_init();
8033#endif
8034
8035#ifdef TIMER_MANAGER
8036 vos_timer_manager_init();
8037#endif
8038
8039 /* Preopen VOSS so that it is ready to start at least SAL */
8040 status = vos_preOpen(&pVosContext);
8041
8042 if (!VOS_IS_STATUS_SUCCESS(status))
8043 {
8044 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8045 ret_status = -1;
8046 break;
8047 }
8048
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008049#ifndef MODULE
8050 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8051 */
8052 hdd_set_conparam((v_UINT_t)con_mode);
8053#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008054
8055 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008056 if (hdd_wlan_startup(dev))
8057 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008058 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008059 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 vos_preClose( &pVosContext );
8061 ret_status = -1;
8062 break;
8063 }
8064
8065 /* Cancel the vote for XO Core ON
8066 * This is done here for safety purposes in case we re-initialize without turning
8067 * it OFF in any error scenario.
8068 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008069 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008070 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008071 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008072 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8073 {
8074 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8075 " Power consumed will be high\n");
8076 }
8077 } while (0);
8078
8079 if (0 != ret_status)
8080 {
8081 //Assert Deep sleep signal now to put Libra HW in lowest power state
8082 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8083 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8084
8085 //Vote off any PMIC voltage supplies
8086 vos_chipPowerDown(NULL, NULL, NULL);
8087#ifdef TIMER_MANAGER
8088 vos_timer_exit();
8089#endif
8090#ifdef MEMORY_DEBUG
8091 vos_mem_exit();
8092#endif
8093
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008094#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008095 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008096#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008097 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8098 }
8099 else
8100 {
8101 //Send WLAN UP indication to Nlink Service
8102 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8103
8104 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 }
8106
8107 EXIT();
8108
8109 return ret_status;
8110}
8111
Jeff Johnson32d95a32012-09-10 13:15:23 -07008112/**---------------------------------------------------------------------------
8113
8114 \brief hdd_module_init() - Init Function
8115
8116 This is the driver entry point (invoked when module is loaded using insmod)
8117
8118 \param - None
8119
8120 \return - 0 for success, non zero for failure
8121
8122 --------------------------------------------------------------------------*/
8123#ifdef MODULE
8124static int __init hdd_module_init ( void)
8125{
8126 return hdd_driver_init();
8127}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008128#else /* #ifdef MODULE */
8129static int __init hdd_module_init ( void)
8130{
8131 /* Driver initialization is delayed to fwpath_changed_handler */
8132 return 0;
8133}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008134#endif /* #ifdef MODULE */
8135
Jeff Johnson295189b2012-06-20 16:38:30 -07008136
8137/**---------------------------------------------------------------------------
8138
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008139 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008140
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008141 This is the driver exit point (invoked when module is unloaded using rmmod
8142 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008143
8144 \param - None
8145
8146 \return - None
8147
8148 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008149static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008150{
8151 hdd_context_t *pHddCtx = NULL;
8152 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008153 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008154
8155 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8156
8157 //Get the global vos context
8158 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8159
8160 if(!pVosContext)
8161 {
8162 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8163 goto done;
8164 }
8165
8166 //Get the HDD context.
8167 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8168
8169 if(!pHddCtx)
8170 {
8171 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8172 }
8173 else
8174 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008175 while(isWDresetInProgress()) {
8176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8177 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008178 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008179
8180 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8182 "%s:SSR never completed, fatal error", __func__);
8183 VOS_BUG(0);
8184 }
8185 }
8186
Jeff Johnson295189b2012-06-20 16:38:30 -07008187
8188 pHddCtx->isLoadUnloadInProgress = TRUE;
8189 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8190
8191 //Do all the cleanup before deregistering the driver
8192 hdd_wlan_exit(pHddCtx);
8193 }
8194
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 vos_preClose( &pVosContext );
8196
8197#ifdef TIMER_MANAGER
8198 vos_timer_exit();
8199#endif
8200#ifdef MEMORY_DEBUG
8201 vos_mem_exit();
8202#endif
8203
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308204#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8205 vos_wconn_trace_exit();
8206#endif
8207
Jeff Johnson295189b2012-06-20 16:38:30 -07008208done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008209#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008210 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008212 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8213}
8214
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008215/**---------------------------------------------------------------------------
8216
8217 \brief hdd_module_exit() - Exit function
8218
8219 This is the driver exit point (invoked when module is unloaded using rmmod)
8220
8221 \param - None
8222
8223 \return - None
8224
8225 --------------------------------------------------------------------------*/
8226static void __exit hdd_module_exit(void)
8227{
8228 hdd_driver_exit();
8229}
8230
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008231#ifdef MODULE
8232static int fwpath_changed_handler(const char *kmessage,
8233 struct kernel_param *kp)
8234{
Jeff Johnson76052702013-04-16 13:55:05 -07008235 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008236}
8237
8238static int con_mode_handler(const char *kmessage,
8239 struct kernel_param *kp)
8240{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008241 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008242}
8243#else /* #ifdef MODULE */
8244/**---------------------------------------------------------------------------
8245
Jeff Johnson76052702013-04-16 13:55:05 -07008246 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008247
Jeff Johnson76052702013-04-16 13:55:05 -07008248 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008249 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008250 - invoked when module parameter fwpath is modified from userspace to signal
8251 initializing the WLAN driver or when con_mode is modified from userspace
8252 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008253
8254 \return - 0 for success, non zero for failure
8255
8256 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008257static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008258{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008259 int ret_status;
8260
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008261 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008262 ret_status = hdd_driver_init();
8263 wlan_hdd_inited = ret_status ? 0 : 1;
8264 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008265 }
8266
8267 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008268
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008269 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008270
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008271 ret_status = hdd_driver_init();
8272 wlan_hdd_inited = ret_status ? 0 : 1;
8273 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008274}
8275
Jeff Johnson295189b2012-06-20 16:38:30 -07008276/**---------------------------------------------------------------------------
8277
Jeff Johnson76052702013-04-16 13:55:05 -07008278 \brief fwpath_changed_handler() - Handler Function
8279
8280 Handle changes to the fwpath parameter
8281
8282 \return - 0 for success, non zero for failure
8283
8284 --------------------------------------------------------------------------*/
8285static int fwpath_changed_handler(const char *kmessage,
8286 struct kernel_param *kp)
8287{
8288 int ret;
8289
8290 ret = param_set_copystring(kmessage, kp);
8291 if (0 == ret)
8292 ret = kickstart_driver();
8293 return ret;
8294}
8295
8296/**---------------------------------------------------------------------------
8297
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008298 \brief con_mode_handler() -
8299
8300 Handler function for module param con_mode when it is changed by userspace
8301 Dynamically linked - do nothing
8302 Statically linked - exit and init driver, as in rmmod and insmod
8303
Jeff Johnson76052702013-04-16 13:55:05 -07008304 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008305
Jeff Johnson76052702013-04-16 13:55:05 -07008306 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008307
8308 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008309static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008310{
Jeff Johnson76052702013-04-16 13:55:05 -07008311 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008312
Jeff Johnson76052702013-04-16 13:55:05 -07008313 ret = param_set_int(kmessage, kp);
8314 if (0 == ret)
8315 ret = kickstart_driver();
8316 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008317}
8318#endif /* #ifdef MODULE */
8319
8320/**---------------------------------------------------------------------------
8321
Jeff Johnson295189b2012-06-20 16:38:30 -07008322 \brief hdd_get_conparam() -
8323
8324 This is the driver exit point (invoked when module is unloaded using rmmod)
8325
8326 \param - None
8327
8328 \return - tVOS_CON_MODE
8329
8330 --------------------------------------------------------------------------*/
8331tVOS_CON_MODE hdd_get_conparam ( void )
8332{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008333#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008334 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008335#else
8336 return (tVOS_CON_MODE)curr_con_mode;
8337#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008338}
8339void hdd_set_conparam ( v_UINT_t newParam )
8340{
8341 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008342#ifndef MODULE
8343 curr_con_mode = con_mode;
8344#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008345}
8346/**---------------------------------------------------------------------------
8347
8348 \brief hdd_softap_sta_deauth() - function
8349
8350 This to take counter measure to handle deauth req from HDD
8351
8352 \param - pAdapter - Pointer to the HDD
8353
8354 \param - enable - boolean value
8355
8356 \return - None
8357
8358 --------------------------------------------------------------------------*/
8359
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008360VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008361{
Jeff Johnson295189b2012-06-20 16:38:30 -07008362 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008363 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008364
8365 ENTER();
8366
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008367 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8368 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008369
8370 //Ignore request to deauth bcmc station
8371 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008372 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008373
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008374 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008375
8376 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008377 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008378}
8379
8380/**---------------------------------------------------------------------------
8381
8382 \brief hdd_softap_sta_disassoc() - function
8383
8384 This to take counter measure to handle deauth req from HDD
8385
8386 \param - pAdapter - Pointer to the HDD
8387
8388 \param - enable - boolean value
8389
8390 \return - None
8391
8392 --------------------------------------------------------------------------*/
8393
8394void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8395{
8396 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8397
8398 ENTER();
8399
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308400 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008401
8402 //Ignore request to disassoc bcmc station
8403 if( pDestMacAddress[0] & 0x1 )
8404 return;
8405
8406 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8407}
8408
8409void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8410{
8411 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8412
8413 ENTER();
8414
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308415 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008416
8417 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8418}
8419
Jeff Johnson295189b2012-06-20 16:38:30 -07008420/**---------------------------------------------------------------------------
8421 *
8422 * \brief hdd_get__concurrency_mode() -
8423 *
8424 *
8425 * \param - None
8426 *
8427 * \return - CONCURRENCY MODE
8428 *
8429 * --------------------------------------------------------------------------*/
8430tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8431{
8432 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8433 hdd_context_t *pHddCtx;
8434
8435 if (NULL != pVosContext)
8436 {
8437 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8438 if (NULL != pHddCtx)
8439 {
8440 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8441 }
8442 }
8443
8444 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008445 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008446 return VOS_STA;
8447}
8448
8449/* Decide whether to allow/not the apps power collapse.
8450 * Allow apps power collapse if we are in connected state.
8451 * if not, allow only if we are in IMPS */
8452v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8453{
8454 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008455 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008456 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008457 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8458 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8459 hdd_adapter_t *pAdapter = NULL;
8460 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008461 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008462
Jeff Johnson295189b2012-06-20 16:38:30 -07008463 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8464 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008465
Yathish9f22e662012-12-10 14:21:35 -08008466 concurrent_state = hdd_get_concurrency_mode();
8467
8468#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8469 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8470 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8471 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8472 return TRUE;
8473#endif
8474
Jeff Johnson295189b2012-06-20 16:38:30 -07008475 /*loop through all adapters. TBD fix for Concurrency */
8476 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8477 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8478 {
8479 pAdapter = pAdapterNode->pAdapter;
8480 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8481 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8482 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008483 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008484 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008485 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008486 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8487 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008488 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008489 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008490 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8491 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008492 return FALSE;
8493 }
8494 }
8495 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8496 pAdapterNode = pNext;
8497 }
8498 return TRUE;
8499}
8500
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008501/* Decides whether to send suspend notification to Riva
8502 * if any adapter is in BMPS; then it is required */
8503v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8504{
8505 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8506 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8507
8508 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8509 {
8510 return TRUE;
8511 }
8512 return FALSE;
8513}
8514
Jeff Johnson295189b2012-06-20 16:38:30 -07008515void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8516{
8517 switch(mode)
8518 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008519 case VOS_STA_MODE:
8520 case VOS_P2P_CLIENT_MODE:
8521 case VOS_P2P_GO_MODE:
8522 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008523 pHddCtx->concurrency_mode |= (1 << mode);
8524 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008525 break;
8526 default:
8527 break;
8528
8529 }
8530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8531 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8532}
8533
8534
8535void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8536{
8537 switch(mode)
8538 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008539 case VOS_STA_MODE:
8540 case VOS_P2P_CLIENT_MODE:
8541 case VOS_P2P_GO_MODE:
8542 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008543 pHddCtx->no_of_sessions[mode]--;
8544 if (!(pHddCtx->no_of_sessions[mode]))
8545 pHddCtx->concurrency_mode &= (~(1 << mode));
8546 break;
8547 default:
8548 break;
8549 }
8550 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8551 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8552}
8553
Jeff Johnsone7245742012-09-05 17:12:55 -07008554/**---------------------------------------------------------------------------
8555 *
8556 * \brief wlan_hdd_restart_init
8557 *
8558 * This function initalizes restart timer/flag. An internal function.
8559 *
8560 * \param - pHddCtx
8561 *
8562 * \return - None
8563 *
8564 * --------------------------------------------------------------------------*/
8565
8566static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8567{
8568 /* Initialize */
8569 pHddCtx->hdd_restart_retries = 0;
8570 atomic_set(&pHddCtx->isRestartInProgress, 0);
8571 vos_timer_init(&pHddCtx->hdd_restart_timer,
8572 VOS_TIMER_TYPE_SW,
8573 wlan_hdd_restart_timer_cb,
8574 pHddCtx);
8575}
8576/**---------------------------------------------------------------------------
8577 *
8578 * \brief wlan_hdd_restart_deinit
8579 *
8580 * This function cleans up the resources used. An internal function.
8581 *
8582 * \param - pHddCtx
8583 *
8584 * \return - None
8585 *
8586 * --------------------------------------------------------------------------*/
8587
8588static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8589{
8590
8591 VOS_STATUS vos_status;
8592 /* Block any further calls */
8593 atomic_set(&pHddCtx->isRestartInProgress, 1);
8594 /* Cleanup */
8595 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8596 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008597 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008598 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8599 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008600 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008601
8602}
8603
8604/**---------------------------------------------------------------------------
8605 *
8606 * \brief wlan_hdd_framework_restart
8607 *
8608 * This function uses a cfg80211 API to start a framework initiated WLAN
8609 * driver module unload/load.
8610 *
8611 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8612 *
8613 *
8614 * \param - pHddCtx
8615 *
8616 * \return - VOS_STATUS_SUCCESS: Success
8617 * VOS_STATUS_E_EMPTY: Adapter is Empty
8618 * VOS_STATUS_E_NOMEM: No memory
8619
8620 * --------------------------------------------------------------------------*/
8621
8622static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8623{
8624 VOS_STATUS status = VOS_STATUS_SUCCESS;
8625 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008626 int len = (sizeof (struct ieee80211_mgmt));
8627 struct ieee80211_mgmt *mgmt = NULL;
8628
8629 /* Prepare the DEAUTH managment frame with reason code */
8630 mgmt = kzalloc(len, GFP_KERNEL);
8631 if(mgmt == NULL)
8632 {
8633 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8634 "%s: memory allocation failed (%d bytes)", __func__, len);
8635 return VOS_STATUS_E_NOMEM;
8636 }
8637 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008638
8639 /* Iterate over all adapters/devices */
8640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8641 do
8642 {
8643 if( (status == VOS_STATUS_SUCCESS) &&
8644 pAdapterNode &&
8645 pAdapterNode->pAdapter)
8646 {
8647 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8648 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8649 pAdapterNode->pAdapter->dev->name,
8650 pAdapterNode->pAdapter->device_mode,
8651 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008652 /*
8653 * CFG80211 event to restart the driver
8654 *
8655 * 'cfg80211_send_unprot_deauth' sends a
8656 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8657 * of SME(Linux Kernel) state machine.
8658 *
8659 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8660 * the driver.
8661 *
8662 */
8663
8664 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008665 }
8666 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8667 pAdapterNode = pNext;
8668 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8669
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008670
8671 /* Free the allocated management frame */
8672 kfree(mgmt);
8673
Jeff Johnsone7245742012-09-05 17:12:55 -07008674 /* Retry until we unload or reach max count */
8675 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8676 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8677
8678 return status;
8679
8680}
8681/**---------------------------------------------------------------------------
8682 *
8683 * \brief wlan_hdd_restart_timer_cb
8684 *
8685 * Restart timer callback. An internal function.
8686 *
8687 * \param - User data:
8688 *
8689 * \return - None
8690 *
8691 * --------------------------------------------------------------------------*/
8692
8693void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8694{
8695 hdd_context_t *pHddCtx = usrDataForCallback;
8696 wlan_hdd_framework_restart(pHddCtx);
8697 return;
8698
8699}
8700
8701
8702/**---------------------------------------------------------------------------
8703 *
8704 * \brief wlan_hdd_restart_driver
8705 *
8706 * This function sends an event to supplicant to restart the WLAN driver.
8707 *
8708 * This function is called from vos_wlanRestart.
8709 *
8710 * \param - pHddCtx
8711 *
8712 * \return - VOS_STATUS_SUCCESS: Success
8713 * VOS_STATUS_E_EMPTY: Adapter is Empty
8714 * VOS_STATUS_E_ALREADY: Request already in progress
8715
8716 * --------------------------------------------------------------------------*/
8717VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8718{
8719 VOS_STATUS status = VOS_STATUS_SUCCESS;
8720
8721 /* A tight check to make sure reentrancy */
8722 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8723 {
8724 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8725 "%s: WLAN restart is already in progress", __func__);
8726
8727 return VOS_STATUS_E_ALREADY;
8728 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008729 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008730#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008731 wcnss_reset_intr();
8732#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008733
Jeff Johnsone7245742012-09-05 17:12:55 -07008734 return status;
8735}
8736
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008737/*
8738 * API to find if there is any STA or P2P-Client is connected
8739 */
8740VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8741{
8742 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8743}
Jeff Johnsone7245742012-09-05 17:12:55 -07008744
Jeff Johnson295189b2012-06-20 16:38:30 -07008745//Register the module init/exit functions
8746module_init(hdd_module_init);
8747module_exit(hdd_module_exit);
8748
8749MODULE_LICENSE("Dual BSD/GPL");
8750MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8751MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8752
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008753module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8754 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008755
Jeff Johnson76052702013-04-16 13:55:05 -07008756module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008757 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);