blob: d759d095cc0a572c7ebac2bbfc2a29ffa323f27d [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 {
Leo Chang614d2072013-08-22 14:59:44 -07003148 tANI_U8 *value = command;
3149 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003150 tSirRateUpdateInd *rateUpdate;
3151 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003152
3153 /* Only valid for SAP mode */
3154 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3155 {
3156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3157 "%s: SAP mode is not running", __func__);
3158 ret = -EFAULT;
3159 goto exit;
3160 }
3161
3162 /* Move pointer to ahead of SETMCRATE<delimiter> */
3163 /* input value is in units of hundred kbps */
3164 value = value + 10;
3165 /* Convert the value from ascii to integer, decimal base */
3166 ret = kstrtouint(value, 10, &targetRate);
3167
Leo Chang1f98cbd2013-10-17 15:03:52 -07003168 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3169 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003170 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003171 hddLog(VOS_TRACE_LEVEL_ERROR,
3172 "%s: SETMCRATE indication alloc fail", __func__);
3173 ret = -EFAULT;
3174 goto exit;
3175 }
3176 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3177
3178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3179 "MC Target rate %d", targetRate);
3180 /* Ignore unicast */
3181 rateUpdate->ucastDataRate = -1;
3182 rateUpdate->mcastDataRate24GHz = targetRate;
3183 rateUpdate->mcastDataRate5GHz = targetRate;
3184 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3185 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3186 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3187 if (eHAL_STATUS_SUCCESS != status)
3188 {
3189 hddLog(VOS_TRACE_LEVEL_ERROR,
3190 "%s: SET_MC_RATE failed", __func__);
3191 vos_mem_free(rateUpdate);
3192 ret = -EFAULT;
3193 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003194 }
3195 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303196#ifdef FEATURE_WLAN_BATCH_SCAN
3197 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3198 {
3199 char extra[32];
3200 tANI_U8 len = 0;
3201 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3202
3203 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3204 {
3205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3206 "%s: Batch scan feature is not supported by FW", __func__);
3207 ret = -EINVAL;
3208 goto exit;
3209 }
3210
3211 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3212 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3213 {
3214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3215 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3216 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3217 " mode",
3218 pAdapter->device_mode);
3219 ret = -EINVAL;
3220 goto exit;
3221 }
3222
3223 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3224 version);
3225 if (copy_to_user(priv_data.buf, &extra, len + 1))
3226 {
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "%s: failed to copy data to user buffer", __func__);
3229 ret = -EFAULT;
3230 goto exit;
3231 }
3232 ret = HDD_BATCH_SCAN_VERSION;
3233 }
3234 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3235 {
3236 int status;
3237 tANI_U8 *value = (command + 16);
3238 eHalStatus halStatus;
3239 unsigned long rc;
3240 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3241 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3242
3243 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3244 {
3245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3246 "%s: Batch scan feature is not supported by FW", __func__);
3247 ret = -EINVAL;
3248 goto exit;
3249 }
3250
Rajeev Kumar20140c12013-10-21 19:39:02 -07003251
Rajeev79dbe4c2013-10-05 11:03:42 +05303252 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3253 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3254 {
3255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003256 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303257 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3258 pAdapter->device_mode);
3259 ret = -EINVAL;
3260 goto exit;
3261 }
3262
Rajeev Kumar20140c12013-10-21 19:39:02 -07003263
Rajeev79dbe4c2013-10-05 11:03:42 +05303264 status = hdd_parse_set_batchscan_command(value, pReq);
3265 if (status)
3266 {
3267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003268 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303269 ret = -EINVAL;
3270 goto exit;
3271 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003272
3273
Rajeev79dbe4c2013-10-05 11:03:42 +05303274 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3275 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3276 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3277 pAdapter);
3278
3279 if ( eHAL_STATUS_SUCCESS == halStatus )
3280 {
3281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3282 "sme_SetBatchScanReq returned success halStatus %d",
3283 halStatus);
3284 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3285 {
3286 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3287 rc = wait_for_completion_timeout(
3288 &pAdapter->hdd_set_batch_scan_req_var,
3289 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3290 if (0 == rc)
3291 {
3292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3293 "%s: Timeout waiting for set batch scan to complete",
3294 __func__);
3295 ret = -EINVAL;
3296 goto exit;
3297 }
3298 }
3299 if ( !pRsp->nScansToBatch )
3300 {
3301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3302 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003303 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303304 ret = -EINVAL;
3305 goto exit;
3306 }
3307 /*As per the Batch Scan Framework API we should return the MIN of
3308 either MSCAN or the max # of scans firmware can cache*/
3309 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3310
Rajeev Kumar20140c12013-10-21 19:39:02 -07003311 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3312
Rajeev79dbe4c2013-10-05 11:03:42 +05303313 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3314 "%s: request MSCAN %d response MSCAN %d ret %d",
3315 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3316 }
3317 else
3318 {
3319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3320 "sme_SetBatchScanReq returned failure halStatus %d",
3321 halStatus);
3322 ret = -EINVAL;
3323 goto exit;
3324 }
3325 }
3326 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3327 {
3328 eHalStatus halStatus;
3329 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3330 pInd->param = 0;
3331
3332 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3333 {
3334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3335 "%s: Batch scan feature is not supported by FW", __func__);
3336 ret = -EINVAL;
3337 goto exit;
3338 }
3339
Rajeev Kumar20140c12013-10-21 19:39:02 -07003340 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303341 {
3342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003343 "Batch scan is not yet enabled batch scan state %d",
3344 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303345 ret = -EINVAL;
3346 goto exit;
3347 }
3348
Rajeev Kumar20140c12013-10-21 19:39:02 -07003349 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3350
Rajeev79dbe4c2013-10-05 11:03:42 +05303351 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3352 pAdapter->sessionId);
3353 if ( eHAL_STATUS_SUCCESS == halStatus )
3354 {
3355 ret = 0;
3356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3357 "sme_StopBatchScanInd returned success halStatus %d",
3358 halStatus);
3359 }
3360 else
3361 {
3362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3363 "sme_StopBatchScanInd returned failure halStatus %d",
3364 halStatus);
3365 ret = -EINVAL;
3366 goto exit;
3367 }
3368 }
3369 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3370 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003371 tANI_U32 remain_len;
3372
Rajeev79dbe4c2013-10-05 11:03:42 +05303373 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3374 {
3375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3376 "%s: Batch scan feature is not supported by FW", __func__);
3377 ret = -EINVAL;
3378 goto exit;
3379 }
3380
Rajeev Kumar20140c12013-10-21 19:39:02 -07003381 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303382 {
3383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003384 "Batch scan is not yet enabled could not return results"
3385 "Batch Scan state %d",
3386 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303387 ret = -EINVAL;
3388 goto exit;
3389 }
3390
3391 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003392 remain_len = priv_data.total_len - priv_data.used_len;
3393 if (remain_len < priv_data.total_len)
3394 {
3395 /*Clear previous batch scan response data if any*/
3396 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3397 }
3398 else
3399 {
3400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3401 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003402 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003403 priv_data.total_len, priv_data.used_len, remain_len);
3404 ret = -EINVAL;
3405 goto exit;
3406 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303407 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3408 }
3409#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003410#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3411 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3412 {
3413 tANI_U8 *value = command;
3414 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3415 tANI_U8 numChannels = 0;
3416 eHalStatus status = eHAL_STATUS_SUCCESS;
3417
3418 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3419 if (eHAL_STATUS_SUCCESS != status)
3420 {
3421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3422 "%s: Failed to parse channel list information", __func__);
3423 ret = -EINVAL;
3424 goto exit;
3425 }
3426
3427 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3428 {
3429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3430 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3431 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3432 ret = -EINVAL;
3433 goto exit;
3434 }
3435 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3436 ChannelList,
3437 numChannels);
3438 if (eHAL_STATUS_SUCCESS != status)
3439 {
3440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3441 "%s: Failed to update channel list information", __func__);
3442 ret = -EINVAL;
3443 goto exit;
3444 }
3445 }
3446 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3447 {
3448 tANI_U8 *value = command;
3449 char extra[128] = {0};
3450 int len = 0;
3451 tANI_U8 tid = 0;
3452 hdd_station_ctx_t *pHddStaCtx = NULL;
3453 tAniTrafStrmMetrics tsmMetrics;
3454 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3455
3456 /* if not associated, return error */
3457 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3458 {
3459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3460 ret = -EINVAL;
3461 goto exit;
3462 }
3463
3464 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3465 value = value + 12;
3466 /* Convert the value from ascii to integer */
3467 ret = kstrtou8(value, 10, &tid);
3468 if (ret < 0)
3469 {
3470 /* If the input value is greater than max value of datatype, then also
3471 kstrtou8 fails */
3472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3473 "%s: kstrtou8 failed range [%d - %d]", __func__,
3474 TID_MIN_VALUE,
3475 TID_MAX_VALUE);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3481 {
3482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3483 "tid value %d is out of range"
3484 " (Min: %d Max: %d)", tid,
3485 TID_MIN_VALUE,
3486 TID_MAX_VALUE);
3487 ret = -EINVAL;
3488 goto exit;
3489 }
3490
3491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3492 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3493
3494 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3495 {
3496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3497 "%s: failed to get tsm stats", __func__);
3498 ret = -EFAULT;
3499 goto exit;
3500 }
3501
3502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3503 "UplinkPktQueueDly(%d)\n"
3504 "UplinkPktQueueDlyHist[0](%d)\n"
3505 "UplinkPktQueueDlyHist[1](%d)\n"
3506 "UplinkPktQueueDlyHist[2](%d)\n"
3507 "UplinkPktQueueDlyHist[3](%d)\n"
3508 "UplinkPktTxDly(%lu)\n"
3509 "UplinkPktLoss(%d)\n"
3510 "UplinkPktCount(%d)\n"
3511 "RoamingCount(%d)\n"
3512 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3513 tsmMetrics.UplinkPktQueueDlyHist[0],
3514 tsmMetrics.UplinkPktQueueDlyHist[1],
3515 tsmMetrics.UplinkPktQueueDlyHist[2],
3516 tsmMetrics.UplinkPktQueueDlyHist[3],
3517 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3518 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3519
3520 /* Output TSM stats is of the format
3521 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3522 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3523 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3524 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3525 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3526 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3527 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3528 tsmMetrics.RoamingDly);
3529
3530 if (copy_to_user(priv_data.buf, &extra, len + 1))
3531 {
3532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3533 "%s: failed to copy data to user buffer", __func__);
3534 ret = -EFAULT;
3535 goto exit;
3536 }
3537 }
3538 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3539 {
3540 tANI_U8 *value = command;
3541 tANI_U8 *cckmIe = NULL;
3542 tANI_U8 cckmIeLen = 0;
3543 eHalStatus status = eHAL_STATUS_SUCCESS;
3544
3545 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3546 if (eHAL_STATUS_SUCCESS != status)
3547 {
3548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3549 "%s: Failed to parse cckm ie data", __func__);
3550 ret = -EINVAL;
3551 goto exit;
3552 }
3553
3554 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3555 {
3556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3557 "%s: CCKM Ie input length is more than max[%d]", __func__,
3558 DOT11F_IE_RSN_MAX_LEN);
3559 if (NULL != cckmIe)
3560 {
3561 vos_mem_free(cckmIe);
3562 }
3563 ret = -EINVAL;
3564 goto exit;
3565 }
3566 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3567 if (NULL != cckmIe)
3568 {
3569 vos_mem_free(cckmIe);
3570 }
3571 }
3572#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003573 else {
3574 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3575 __func__, command);
3576 }
3577
Jeff Johnson295189b2012-06-20 16:38:30 -07003578 }
3579exit:
3580 if (command)
3581 {
3582 kfree(command);
3583 }
3584 return ret;
3585}
3586
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003587
3588
3589#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3590static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3591{
3592 struct statsContext *pStatsContext = NULL;
3593 hdd_adapter_t *pAdapter = NULL;
3594
3595 if (NULL == pContext)
3596 {
3597 hddLog(VOS_TRACE_LEVEL_ERROR,
3598 "%s: Bad param, pContext [%p]",
3599 __func__, pContext);
3600 return;
3601 }
3602
3603 /* there is a race condition that exists between this callback function
3604 and the caller since the caller could time out either before or
3605 while this code is executing. we'll assume the timeout hasn't
3606 occurred, but we'll verify that right before we save our work */
3607
3608 pStatsContext = pContext;
3609 pAdapter = pStatsContext->pAdapter;
3610 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3611 {
3612 /* the caller presumably timed out so there is nothing we can do */
3613 hddLog(VOS_TRACE_LEVEL_WARN,
3614 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3615 __func__, pAdapter, pStatsContext->magic);
3616 return;
3617 }
3618
3619 /* the race is on. caller could have timed out immediately after
3620 we verified the magic, but if so, caller will wait a short time
3621 for us to copy over the tsm stats */
3622 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3623 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3624 tsmMetrics.UplinkPktQueueDlyHist,
3625 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3626 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3627 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3628 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3629 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3630 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3631 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3632
3633 /* and notify the caller */
3634 complete(&pStatsContext->completion);
3635}
3636
3637
3638
3639static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3640 tAniTrafStrmMetrics* pTsmMetrics)
3641{
3642 hdd_station_ctx_t *pHddStaCtx = NULL;
3643 eHalStatus hstatus;
3644 long lrc;
3645 struct statsContext context;
3646 hdd_context_t *pHddCtx = NULL;
3647
3648 if (NULL == pAdapter)
3649 {
3650 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3651 return VOS_STATUS_E_FAULT;
3652 }
3653
3654 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3655 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3656
3657 /* we are connected prepare our callback context */
3658 init_completion(&context.completion);
3659 context.pAdapter = pAdapter;
3660 context.magic = STATS_CONTEXT_MAGIC;
3661
3662 /* query tsm stats */
3663 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3664 pHddStaCtx->conn_info.staId[ 0 ],
3665 pHddStaCtx->conn_info.bssId,
3666 &context, pHddCtx->pvosContext, tid);
3667
3668 if (eHAL_STATUS_SUCCESS != hstatus)
3669 {
3670 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3671 return hstatus;
3672 }
3673 else
3674 {
3675 /* request was sent -- wait for the response */
3676 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3677 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3678 /* either we have a response or we timed out
3679 either way, first invalidate our magic */
3680 context.magic = 0;
3681 if (lrc <= 0)
3682 {
3683 hddLog(VOS_TRACE_LEVEL_ERROR,
3684 "%s: SME %s while retrieving statistics",
3685 __func__, (0 == lrc) ? "timeout" : "interrupt");
3686 /* there is a race condition such that the callback
3687 function could be executing at the same time we are. of
3688 primary concern is if the callback function had already
3689 verified the "magic" but hasn't yet set the completion
3690 variable. Since the completion variable is on our
3691 stack, we'll delay just a bit to make sure the data is
3692 still valid if that is the case */
3693 msleep(50);
3694 return (VOS_STATUS_E_TIMEOUT);
3695 }
3696 }
3697 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3698 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3699 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3700 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3701 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3702 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3703 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3704 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3705 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3706 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3707
3708 return VOS_STATUS_SUCCESS;
3709}
3710#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3711
Srinivas Girigowdade697412013-02-14 16:31:48 -08003712#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3713void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3714{
3715 eCsrBand band = -1;
3716 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3717 switch (band)
3718 {
3719 case eCSR_BAND_ALL:
3720 *pBand = WLAN_HDD_UI_BAND_AUTO;
3721 break;
3722
3723 case eCSR_BAND_24:
3724 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3725 break;
3726
3727 case eCSR_BAND_5G:
3728 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3729 break;
3730
3731 default:
3732 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3733 *pBand = -1;
3734 break;
3735 }
3736}
3737
3738/**---------------------------------------------------------------------------
3739
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003740 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3741
3742 This function parses the send action frame data passed in the format
3743 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3744
Srinivas Girigowda56076852013-08-20 14:00:50 -07003745 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003746 \param - pTargetApBssid Pointer to target Ap bssid
3747 \param - pChannel Pointer to the Target AP channel
3748 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3749 \param - pBuf Pointer to data
3750 \param - pBufLen Pointer to data length
3751
3752 \return - 0 for success non-zero for failure
3753
3754 --------------------------------------------------------------------------*/
3755VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3756 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3757{
3758 tANI_U8 *inPtr = pValue;
3759 tANI_U8 *dataEnd;
3760 int tempInt;
3761 int j = 0;
3762 int i = 0;
3763 int v = 0;
3764 tANI_U8 tempBuf[32];
3765 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003766 /* 12 hexa decimal digits and 5 ':' */
3767 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003768
3769 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3770 /*no argument after the command*/
3771 if (NULL == inPtr)
3772 {
3773 return -EINVAL;
3774 }
3775
3776 /*no space after the command*/
3777 else if (SPACE_ASCII_VALUE != *inPtr)
3778 {
3779 return -EINVAL;
3780 }
3781
3782 /*removing empty spaces*/
3783 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3784
3785 /*no argument followed by spaces*/
3786 if ('\0' == *inPtr)
3787 {
3788 return -EINVAL;
3789 }
3790
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003791 v = sscanf(inPtr, "%17s", macAddress);
3792 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003793 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3795 "Invalid MAC address or All hex inputs are not read (%d)", v);
3796 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003797 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003798
3799 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3800 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3801 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3802 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3803 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3804 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003805
3806 /* point to the next argument */
3807 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3808 /*no argument after the command*/
3809 if (NULL == inPtr) return -EINVAL;
3810
3811 /*removing empty spaces*/
3812 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3813
3814 /*no argument followed by spaces*/
3815 if ('\0' == *inPtr)
3816 {
3817 return -EINVAL;
3818 }
3819
3820 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003821 v = sscanf(inPtr, "%32s ", tempBuf);
3822 if (1 != v) return -EINVAL;
3823
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003824 v = kstrtos32(tempBuf, 10, &tempInt);
3825 if ( v < 0) return -EINVAL;
3826
3827 *pChannel = tempInt;
3828
3829 /* point to the next argument */
3830 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3831 /*no argument after the command*/
3832 if (NULL == inPtr) return -EINVAL;
3833 /*removing empty spaces*/
3834 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3835
3836 /*no argument followed by spaces*/
3837 if ('\0' == *inPtr)
3838 {
3839 return -EINVAL;
3840 }
3841
3842 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003843 v = sscanf(inPtr, "%32s ", tempBuf);
3844 if (1 != v) return -EINVAL;
3845
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003846 v = kstrtos32(tempBuf, 10, &tempInt);
3847 if ( v < 0) return -EINVAL;
3848
3849 *pDwellTime = tempInt;
3850
3851 /* point to the next argument */
3852 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3853 /*no argument after the command*/
3854 if (NULL == inPtr) return -EINVAL;
3855 /*removing empty spaces*/
3856 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3857
3858 /*no argument followed by spaces*/
3859 if ('\0' == *inPtr)
3860 {
3861 return -EINVAL;
3862 }
3863
3864 /* find the length of data */
3865 dataEnd = inPtr;
3866 while(('\0' != *dataEnd) )
3867 {
3868 dataEnd++;
3869 ++(*pBufLen);
3870 }
3871 if ( *pBufLen <= 0) return -EINVAL;
3872
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003873 /* Allocate the number of bytes based on the number of input characters
3874 whether it is even or odd.
3875 if the number of input characters are even, then we need N/2 byte.
3876 if the number of input characters are odd, then we need do (N+1)/2 to
3877 compensate rounding off.
3878 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3879 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3880 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003881 if (NULL == *pBuf)
3882 {
3883 hddLog(VOS_TRACE_LEVEL_FATAL,
3884 "%s: vos_mem_alloc failed ", __func__);
3885 return -EINVAL;
3886 }
3887
3888 /* the buffer received from the upper layer is character buffer,
3889 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3890 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3891 and f0 in 3rd location */
3892 for (i = 0, j = 0; j < *pBufLen; j += 2)
3893 {
3894 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3895 (*pBuf)[i++] = tempByte;
3896 }
3897 *pBufLen = i;
3898 return VOS_STATUS_SUCCESS;
3899}
3900
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003901/**---------------------------------------------------------------------------
3902
Srinivas Girigowdade697412013-02-14 16:31:48 -08003903 \brief hdd_parse_channellist() - HDD Parse channel list
3904
3905 This function parses the channel list passed in the format
3906 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003907 if the Number of channels (N) does not match with the actual number of channels passed
3908 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3909 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3910 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3911 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003912
3913 \param - pValue Pointer to input channel list
3914 \param - ChannelList Pointer to local output array to record channel list
3915 \param - pNumChannels Pointer to number of roam scan channels
3916
3917 \return - 0 for success non-zero for failure
3918
3919 --------------------------------------------------------------------------*/
3920VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3921{
3922 tANI_U8 *inPtr = pValue;
3923 int tempInt;
3924 int j = 0;
3925 int v = 0;
3926 char buf[32];
3927
3928 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3929 /*no argument after the command*/
3930 if (NULL == inPtr)
3931 {
3932 return -EINVAL;
3933 }
3934
3935 /*no space after the command*/
3936 else if (SPACE_ASCII_VALUE != *inPtr)
3937 {
3938 return -EINVAL;
3939 }
3940
3941 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003942 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003943
3944 /*no argument followed by spaces*/
3945 if ('\0' == *inPtr)
3946 {
3947 return -EINVAL;
3948 }
3949
3950 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003951 v = sscanf(inPtr, "%32s ", buf);
3952 if (1 != v) return -EINVAL;
3953
Srinivas Girigowdade697412013-02-14 16:31:48 -08003954 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003955 if ((v < 0) ||
3956 (tempInt <= 0) ||
3957 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3958 {
3959 return -EINVAL;
3960 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003961
3962 *pNumChannels = tempInt;
3963
3964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3965 "Number of channels are: %d", *pNumChannels);
3966
3967 for (j = 0; j < (*pNumChannels); j++)
3968 {
3969 /*inPtr pointing to the beginning of first space after number of channels*/
3970 inPtr = strpbrk( inPtr, " " );
3971 /*no channel list after the number of channels argument*/
3972 if (NULL == inPtr)
3973 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003974 if (0 != j)
3975 {
3976 *pNumChannels = j;
3977 return VOS_STATUS_SUCCESS;
3978 }
3979 else
3980 {
3981 return -EINVAL;
3982 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003983 }
3984
3985 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003986 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003987
3988 /*no channel list after the number of channels argument and spaces*/
3989 if ( '\0' == *inPtr )
3990 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003991 if (0 != j)
3992 {
3993 *pNumChannels = j;
3994 return VOS_STATUS_SUCCESS;
3995 }
3996 else
3997 {
3998 return -EINVAL;
3999 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004000 }
4001
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004002 v = sscanf(inPtr, "%32s ", buf);
4003 if (1 != v) return -EINVAL;
4004
Srinivas Girigowdade697412013-02-14 16:31:48 -08004005 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004006 if ((v < 0) ||
4007 (tempInt <= 0) ||
4008 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4009 {
4010 return -EINVAL;
4011 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004012 pChannelList[j] = tempInt;
4013
4014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4015 "Channel %d added to preferred channel list",
4016 pChannelList[j] );
4017 }
4018
Srinivas Girigowdade697412013-02-14 16:31:48 -08004019 return VOS_STATUS_SUCCESS;
4020}
4021
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004022
4023/**---------------------------------------------------------------------------
4024
4025 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4026
4027 This function parses the reasoc command data passed in the format
4028 REASSOC<space><bssid><space><channel>
4029
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004030 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004031 \param - pTargetApBssid Pointer to target Ap bssid
4032 \param - pChannel Pointer to the Target AP channel
4033
4034 \return - 0 for success non-zero for failure
4035
4036 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004037VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4038 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004039{
4040 tANI_U8 *inPtr = pValue;
4041 int tempInt;
4042 int v = 0;
4043 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004044 /* 12 hexa decimal digits and 5 ':' */
4045 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004046
4047 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4048 /*no argument after the command*/
4049 if (NULL == inPtr)
4050 {
4051 return -EINVAL;
4052 }
4053
4054 /*no space after the command*/
4055 else if (SPACE_ASCII_VALUE != *inPtr)
4056 {
4057 return -EINVAL;
4058 }
4059
4060 /*removing empty spaces*/
4061 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4062
4063 /*no argument followed by spaces*/
4064 if ('\0' == *inPtr)
4065 {
4066 return -EINVAL;
4067 }
4068
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004069 v = sscanf(inPtr, "%17s", macAddress);
4070 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004071 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4073 "Invalid MAC address or All hex inputs are not read (%d)", v);
4074 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004075 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004076
4077 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4078 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4079 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4080 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4081 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4082 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004083
4084 /* point to the next argument */
4085 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4086 /*no argument after the command*/
4087 if (NULL == inPtr) return -EINVAL;
4088
4089 /*removing empty spaces*/
4090 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4091
4092 /*no argument followed by spaces*/
4093 if ('\0' == *inPtr)
4094 {
4095 return -EINVAL;
4096 }
4097
4098 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004099 v = sscanf(inPtr, "%32s ", tempBuf);
4100 if (1 != v) return -EINVAL;
4101
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004102 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004103 if ((v < 0) ||
4104 (tempInt <= 0) ||
4105 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4106 {
4107 return -EINVAL;
4108 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004109
4110 *pChannel = tempInt;
4111 return VOS_STATUS_SUCCESS;
4112}
4113
4114#endif
4115
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004116#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4117/**---------------------------------------------------------------------------
4118
4119 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4120
4121 This function parses the SETCCKM IE command
4122 SETCCKMIE<space><ie data>
4123
4124 \param - pValue Pointer to input data
4125 \param - pCckmIe Pointer to output cckm Ie
4126 \param - pCckmIeLen Pointer to output cckm ie length
4127
4128 \return - 0 for success non-zero for failure
4129
4130 --------------------------------------------------------------------------*/
4131VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4132 tANI_U8 *pCckmIeLen)
4133{
4134 tANI_U8 *inPtr = pValue;
4135 tANI_U8 *dataEnd;
4136 int j = 0;
4137 int i = 0;
4138 tANI_U8 tempByte = 0;
4139
4140 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4141 /*no argument after the command*/
4142 if (NULL == inPtr)
4143 {
4144 return -EINVAL;
4145 }
4146
4147 /*no space after the command*/
4148 else if (SPACE_ASCII_VALUE != *inPtr)
4149 {
4150 return -EINVAL;
4151 }
4152
4153 /*removing empty spaces*/
4154 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4155
4156 /*no argument followed by spaces*/
4157 if ('\0' == *inPtr)
4158 {
4159 return -EINVAL;
4160 }
4161
4162 /* find the length of data */
4163 dataEnd = inPtr;
4164 while(('\0' != *dataEnd) )
4165 {
4166 dataEnd++;
4167 ++(*pCckmIeLen);
4168 }
4169 if ( *pCckmIeLen <= 0) return -EINVAL;
4170
4171 /* Allocate the number of bytes based on the number of input characters
4172 whether it is even or odd.
4173 if the number of input characters are even, then we need N/2 byte.
4174 if the number of input characters are odd, then we need do (N+1)/2 to
4175 compensate rounding off.
4176 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4177 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4178 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4179 if (NULL == *pCckmIe)
4180 {
4181 hddLog(VOS_TRACE_LEVEL_FATAL,
4182 "%s: vos_mem_alloc failed ", __func__);
4183 return -EINVAL;
4184 }
4185 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4186 /* the buffer received from the upper layer is character buffer,
4187 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4188 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4189 and f0 in 3rd location */
4190 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4191 {
4192 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4193 (*pCckmIe)[i++] = tempByte;
4194 }
4195 *pCckmIeLen = i;
4196
4197 return VOS_STATUS_SUCCESS;
4198}
4199#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4200
Jeff Johnson295189b2012-06-20 16:38:30 -07004201/**---------------------------------------------------------------------------
4202
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004203 \brief hdd_is_valid_mac_address() - Validate MAC address
4204
4205 This function validates whether the given MAC address is valid or not
4206 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4207 where X is the hexa decimal digit character and separated by ':'
4208 This algorithm works even if MAC address is not separated by ':'
4209
4210 This code checks given input string mac contains exactly 12 hexadecimal digits.
4211 and a separator colon : appears in the input string only after
4212 an even number of hex digits.
4213
4214 \param - pMacAddr pointer to the input MAC address
4215 \return - 1 for valid and 0 for invalid
4216
4217 --------------------------------------------------------------------------*/
4218
4219v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4220{
4221 int xdigit = 0;
4222 int separator = 0;
4223 while (*pMacAddr)
4224 {
4225 if (isxdigit(*pMacAddr))
4226 {
4227 xdigit++;
4228 }
4229 else if (':' == *pMacAddr)
4230 {
4231 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4232 break;
4233
4234 ++separator;
4235 }
4236 else
4237 {
4238 separator = -1;
4239 /* Invalid MAC found */
4240 return 0;
4241 }
4242 ++pMacAddr;
4243 }
4244 return (xdigit == 12 && (separator == 5 || separator == 0));
4245}
4246
4247/**---------------------------------------------------------------------------
4248
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 \brief hdd_open() - HDD Open function
4250
4251 This is called in response to ifconfig up
4252
4253 \param - dev Pointer to net_device structure
4254
4255 \return - 0 for success non-zero for failure
4256
4257 --------------------------------------------------------------------------*/
4258int hdd_open (struct net_device *dev)
4259{
4260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4261 hdd_context_t *pHddCtx;
4262 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4263 VOS_STATUS status;
4264 v_BOOL_t in_standby = TRUE;
4265
4266 if (NULL == pAdapter)
4267 {
4268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004269 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004270 return -ENODEV;
4271 }
4272
4273 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4274 if (NULL == pHddCtx)
4275 {
4276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004277 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004278 return -ENODEV;
4279 }
4280
4281 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4282 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4283 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004284 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4285 {
4286 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304287 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004288 in_standby = FALSE;
4289 break;
4290 }
4291 else
4292 {
4293 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4294 pAdapterNode = pNext;
4295 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 }
4297
4298 if (TRUE == in_standby)
4299 {
4300 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4301 {
4302 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4303 "wlan out of power save", __func__);
4304 return -EINVAL;
4305 }
4306 }
4307
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004308 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4310 {
4311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004312 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004313 /* Enable TX queues only when we are connected */
4314 netif_tx_start_all_queues(dev);
4315 }
4316
4317 return 0;
4318}
4319
4320int hdd_mon_open (struct net_device *dev)
4321{
4322 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4323
4324 if(pAdapter == NULL) {
4325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004326 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004327 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004328 }
4329
4330 netif_start_queue(dev);
4331
4332 return 0;
4333}
4334/**---------------------------------------------------------------------------
4335
4336 \brief hdd_stop() - HDD stop function
4337
4338 This is called in response to ifconfig down
4339
4340 \param - dev Pointer to net_device structure
4341
4342 \return - 0 for success non-zero for failure
4343
4344 --------------------------------------------------------------------------*/
4345
4346int hdd_stop (struct net_device *dev)
4347{
4348 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4349 hdd_context_t *pHddCtx;
4350 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4351 VOS_STATUS status;
4352 v_BOOL_t enter_standby = TRUE;
4353
4354 ENTER();
4355
4356 if (NULL == pAdapter)
4357 {
4358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004359 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 return -ENODEV;
4361 }
4362
4363 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4364 if (NULL == pHddCtx)
4365 {
4366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004367 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 return -ENODEV;
4369 }
4370
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004371 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004372 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4373 netif_tx_disable(pAdapter->dev);
4374 netif_carrier_off(pAdapter->dev);
4375
4376
4377 /* SoftAP ifaces should never go in power save mode
4378 making sure same here. */
4379 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4380 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004382 )
4383 {
4384 /* SoftAP mode, so return from here */
4385 EXIT();
4386 return 0;
4387 }
4388
4389 /* Find if any iface is up then
4390 if any iface is up then can't put device to sleep/ power save mode. */
4391 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4392 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4393 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004394 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4395 {
4396 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304397 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004398 enter_standby = FALSE;
4399 break;
4400 }
4401 else
4402 {
4403 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4404 pAdapterNode = pNext;
4405 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004406 }
4407
4408 if (TRUE == enter_standby)
4409 {
4410 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4411 "entering standby", __func__);
4412 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4413 {
4414 /*log and return success*/
4415 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4416 "wlan in power save", __func__);
4417 }
4418 }
4419
4420 EXIT();
4421 return 0;
4422}
4423
4424/**---------------------------------------------------------------------------
4425
4426 \brief hdd_uninit() - HDD uninit function
4427
4428 This is called during the netdev unregister to uninitialize all data
4429associated with the device
4430
4431 \param - dev Pointer to net_device structure
4432
4433 \return - void
4434
4435 --------------------------------------------------------------------------*/
4436static void hdd_uninit (struct net_device *dev)
4437{
4438 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4439
4440 ENTER();
4441
4442 do
4443 {
4444 if (NULL == pAdapter)
4445 {
4446 hddLog(VOS_TRACE_LEVEL_FATAL,
4447 "%s: NULL pAdapter", __func__);
4448 break;
4449 }
4450
4451 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4452 {
4453 hddLog(VOS_TRACE_LEVEL_FATAL,
4454 "%s: Invalid magic", __func__);
4455 break;
4456 }
4457
4458 if (NULL == pAdapter->pHddCtx)
4459 {
4460 hddLog(VOS_TRACE_LEVEL_FATAL,
4461 "%s: NULL pHddCtx", __func__);
4462 break;
4463 }
4464
4465 if (dev != pAdapter->dev)
4466 {
4467 hddLog(VOS_TRACE_LEVEL_FATAL,
4468 "%s: Invalid device reference", __func__);
4469 /* we haven't validated all cases so let this go for now */
4470 }
4471
4472 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4473
4474 /* after uninit our adapter structure will no longer be valid */
4475 pAdapter->dev = NULL;
4476 pAdapter->magic = 0;
4477 } while (0);
4478
4479 EXIT();
4480}
4481
4482/**---------------------------------------------------------------------------
4483
4484 \brief hdd_release_firmware() -
4485
4486 This function calls the release firmware API to free the firmware buffer.
4487
4488 \param - pFileName Pointer to the File Name.
4489 pCtx - Pointer to the adapter .
4490
4491
4492 \return - 0 for success, non zero for failure
4493
4494 --------------------------------------------------------------------------*/
4495
4496VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4497{
4498 VOS_STATUS status = VOS_STATUS_SUCCESS;
4499 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4500 ENTER();
4501
4502
4503 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4504
4505 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4506
4507 if(pHddCtx->fw) {
4508 release_firmware(pHddCtx->fw);
4509 pHddCtx->fw = NULL;
4510 }
4511 else
4512 status = VOS_STATUS_E_FAILURE;
4513 }
4514 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4515 if(pHddCtx->nv) {
4516 release_firmware(pHddCtx->nv);
4517 pHddCtx->nv = NULL;
4518 }
4519 else
4520 status = VOS_STATUS_E_FAILURE;
4521
4522 }
4523
4524 EXIT();
4525 return status;
4526}
4527
4528/**---------------------------------------------------------------------------
4529
4530 \brief hdd_request_firmware() -
4531
4532 This function reads the firmware file using the request firmware
4533 API and returns the the firmware data and the firmware file size.
4534
4535 \param - pfileName - Pointer to the file name.
4536 - pCtx - Pointer to the adapter .
4537 - ppfw_data - Pointer to the pointer of the firmware data.
4538 - pSize - Pointer to the file size.
4539
4540 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4541
4542 --------------------------------------------------------------------------*/
4543
4544
4545VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4546{
4547 int status;
4548 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4549 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4550 ENTER();
4551
4552 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4553
4554 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4555
4556 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4557 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4558 __func__, pfileName);
4559 retval = VOS_STATUS_E_FAILURE;
4560 }
4561
4562 else {
4563 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4564 *pSize = pHddCtx->fw->size;
4565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4566 __func__, *pSize);
4567 }
4568 }
4569 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4570
4571 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4572
4573 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4574 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4575 __func__, pfileName);
4576 retval = VOS_STATUS_E_FAILURE;
4577 }
4578
4579 else {
4580 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4581 *pSize = pHddCtx->nv->size;
4582 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4583 __func__, *pSize);
4584 }
4585 }
4586
4587 EXIT();
4588 return retval;
4589}
4590/**---------------------------------------------------------------------------
4591 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4592
4593 This is the function invoked by SME to inform the result of a full power
4594 request issued by HDD
4595
4596 \param - callbackcontext - Pointer to cookie
4597 status - result of request
4598
4599 \return - None
4600
4601--------------------------------------------------------------------------*/
4602void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4603{
4604 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4605
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004606 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 if(&pHddCtx->full_pwr_comp_var)
4608 {
4609 complete(&pHddCtx->full_pwr_comp_var);
4610 }
4611}
4612
4613/**---------------------------------------------------------------------------
4614
4615 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4616
4617 This is the function invoked by SME to inform the result of BMPS
4618 request issued by HDD
4619
4620 \param - callbackcontext - Pointer to cookie
4621 status - result of request
4622
4623 \return - None
4624
4625--------------------------------------------------------------------------*/
4626void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4627{
4628
4629 struct completion *completion_var = (struct completion*) callbackContext;
4630
4631 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4632 if(completion_var != NULL)
4633 {
4634 complete(completion_var);
4635 }
4636}
4637
4638/**---------------------------------------------------------------------------
4639
4640 \brief hdd_get_cfg_file_size() -
4641
4642 This function reads the configuration file using the request firmware
4643 API and returns the configuration file size.
4644
4645 \param - pCtx - Pointer to the adapter .
4646 - pFileName - Pointer to the file name.
4647 - pBufSize - Pointer to the buffer size.
4648
4649 \return - 0 for success, non zero for failure
4650
4651 --------------------------------------------------------------------------*/
4652
4653VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4654{
4655 int status;
4656 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4657
4658 ENTER();
4659
4660 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4661
4662 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4663 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4664 status = VOS_STATUS_E_FAILURE;
4665 }
4666 else {
4667 *pBufSize = pHddCtx->fw->size;
4668 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4669 release_firmware(pHddCtx->fw);
4670 pHddCtx->fw = NULL;
4671 }
4672
4673 EXIT();
4674 return VOS_STATUS_SUCCESS;
4675}
4676
4677/**---------------------------------------------------------------------------
4678
4679 \brief hdd_read_cfg_file() -
4680
4681 This function reads the configuration file using the request firmware
4682 API and returns the cfg data and the buffer size of the configuration file.
4683
4684 \param - pCtx - Pointer to the adapter .
4685 - pFileName - Pointer to the file name.
4686 - pBuffer - Pointer to the data buffer.
4687 - pBufSize - Pointer to the buffer size.
4688
4689 \return - 0 for success, non zero for failure
4690
4691 --------------------------------------------------------------------------*/
4692
4693VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4694 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4695{
4696 int status;
4697 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4698
4699 ENTER();
4700
4701 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4702
4703 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4704 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4705 return VOS_STATUS_E_FAILURE;
4706 }
4707 else {
4708 if(*pBufSize != pHddCtx->fw->size) {
4709 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4710 "file size", __func__);
4711 release_firmware(pHddCtx->fw);
4712 pHddCtx->fw = NULL;
4713 return VOS_STATUS_E_FAILURE;
4714 }
4715 else {
4716 if(pBuffer) {
4717 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4718 }
4719 release_firmware(pHddCtx->fw);
4720 pHddCtx->fw = NULL;
4721 }
4722 }
4723
4724 EXIT();
4725
4726 return VOS_STATUS_SUCCESS;
4727}
4728
4729/**---------------------------------------------------------------------------
4730
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 \brief hdd_set_mac_address() -
4732
4733 This function sets the user specified mac address using
4734 the command ifconfig wlanX hw ether <mac adress>.
4735
4736 \param - dev - Pointer to the net device.
4737 - addr - Pointer to the sockaddr.
4738 \return - 0 for success, non zero for failure
4739
4740 --------------------------------------------------------------------------*/
4741
4742static int hdd_set_mac_address(struct net_device *dev, void *addr)
4743{
4744 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4745 struct sockaddr *psta_mac_addr = addr;
4746 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4747
4748 ENTER();
4749
4750 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4751
4752#ifdef HDD_SESSIONIZE
4753 // set the MAC address though the STA ID CFG.
4754 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4755 (v_U8_t *)&pAdapter->macAddressCurrent,
4756 sizeof( pAdapter->macAddressCurrent ),
4757 hdd_set_mac_addr_cb, VOS_FALSE );
4758#endif
4759
4760 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4761
4762 EXIT();
4763 return halStatus;
4764}
4765
4766tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4767{
4768 int i;
4769 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4770 {
4771 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4772 break;
4773 }
4774
4775 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4776 return NULL;
4777
4778 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4779 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4780}
4781
4782void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4783{
4784 int i;
4785 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4786 {
4787 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4788 {
4789 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4790 break;
4791 }
4792 }
4793 return;
4794}
4795
4796#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4797 static struct net_device_ops wlan_drv_ops = {
4798 .ndo_open = hdd_open,
4799 .ndo_stop = hdd_stop,
4800 .ndo_uninit = hdd_uninit,
4801 .ndo_start_xmit = hdd_hard_start_xmit,
4802 .ndo_tx_timeout = hdd_tx_timeout,
4803 .ndo_get_stats = hdd_stats,
4804 .ndo_do_ioctl = hdd_ioctl,
4805 .ndo_set_mac_address = hdd_set_mac_address,
4806 .ndo_select_queue = hdd_select_queue,
4807#ifdef WLAN_FEATURE_PACKET_FILTERING
4808#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4809 .ndo_set_rx_mode = hdd_set_multicast_list,
4810#else
4811 .ndo_set_multicast_list = hdd_set_multicast_list,
4812#endif //LINUX_VERSION_CODE
4813#endif
4814 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 static struct net_device_ops wlan_mon_drv_ops = {
4816 .ndo_open = hdd_mon_open,
4817 .ndo_stop = hdd_stop,
4818 .ndo_uninit = hdd_uninit,
4819 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4820 .ndo_tx_timeout = hdd_tx_timeout,
4821 .ndo_get_stats = hdd_stats,
4822 .ndo_do_ioctl = hdd_ioctl,
4823 .ndo_set_mac_address = hdd_set_mac_address,
4824 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004825
4826#endif
4827
4828void hdd_set_station_ops( struct net_device *pWlanDev )
4829{
4830#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4831 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4832 pWlanDev->netdev_ops = &wlan_drv_ops;
4833#else
4834 pWlanDev->open = hdd_open;
4835 pWlanDev->stop = hdd_stop;
4836 pWlanDev->uninit = hdd_uninit;
4837 pWlanDev->hard_start_xmit = NULL;
4838 pWlanDev->tx_timeout = hdd_tx_timeout;
4839 pWlanDev->get_stats = hdd_stats;
4840 pWlanDev->do_ioctl = hdd_ioctl;
4841 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4842 pWlanDev->set_mac_address = hdd_set_mac_address;
4843#endif
4844}
4845
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004846static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004847{
4848 struct net_device *pWlanDev = NULL;
4849 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004850 /*
4851 * cfg80211 initialization and registration....
4852 */
4853 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4854
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 if(pWlanDev != NULL)
4856 {
4857
4858 //Save the pointer to the net_device in the HDD adapter
4859 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4860
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4862
4863 pAdapter->dev = pWlanDev;
4864 pAdapter->pHddCtx = pHddCtx;
4865 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4866
4867 init_completion(&pAdapter->session_open_comp_var);
4868 init_completion(&pAdapter->session_close_comp_var);
4869 init_completion(&pAdapter->disconnect_comp_var);
4870 init_completion(&pAdapter->linkup_event_var);
4871 init_completion(&pAdapter->cancel_rem_on_chan_var);
4872 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004873#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4874 init_completion(&pAdapter->offchannel_tx_event);
4875#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004877#ifdef FEATURE_WLAN_TDLS
4878 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004879 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004880 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304881 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004882#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 init_completion(&pHddCtx->mc_sus_event_var);
4884 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304885 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004886 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004887 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004888
Rajeev79dbe4c2013-10-05 11:03:42 +05304889#ifdef FEATURE_WLAN_BATCH_SCAN
4890 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4891 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4892 pAdapter->pBatchScanRsp = NULL;
4893 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004894 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304895 mutex_init(&pAdapter->hdd_batch_scan_lock);
4896#endif
4897
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 pAdapter->isLinkUpSvcNeeded = FALSE;
4899 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4900 //Init the net_device structure
4901 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4902
4903 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4904 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4905 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4906 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4907
4908 hdd_set_station_ops( pAdapter->dev );
4909
4910 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4912 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4913 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 /* set pWlanDev's parent to underlying device */
4915 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4916 }
4917
4918 return pAdapter;
4919}
4920
4921VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4922{
4923 struct net_device *pWlanDev = pAdapter->dev;
4924 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4925 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4926 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4927
4928 if( rtnl_lock_held )
4929 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004930 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4932 {
4933 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4934 return VOS_STATUS_E_FAILURE;
4935 }
4936 }
4937 if (register_netdevice(pWlanDev))
4938 {
4939 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4940 return VOS_STATUS_E_FAILURE;
4941 }
4942 }
4943 else
4944 {
4945 if(register_netdev(pWlanDev))
4946 {
4947 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4948 return VOS_STATUS_E_FAILURE;
4949 }
4950 }
4951 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4952
4953 return VOS_STATUS_SUCCESS;
4954}
4955
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004956static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004957{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004958 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004959
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004960 if (NULL == pAdapter)
4961 {
4962 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4963 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004965
4966 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4967 {
4968 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4969 return eHAL_STATUS_NOT_INITIALIZED;
4970 }
4971
4972 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4973
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004974#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004975 /* need to make sure all of our scheduled work has completed.
4976 * This callback is called from MC thread context, so it is safe to
4977 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004978 *
4979 * Even though this is called from MC thread context, if there is a faulty
4980 * work item in the system, that can hang this call forever. So flushing
4981 * this global work queue is not safe; and now we make sure that
4982 * individual work queues are stopped correctly. But the cancel work queue
4983 * is a GPL only API, so the proprietary version of the driver would still
4984 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004985 */
4986 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004987#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004988
4989 /* We can be blocked while waiting for scheduled work to be
4990 * flushed, and the adapter structure can potentially be freed, in
4991 * which case the magic will have been reset. So make sure the
4992 * magic is still good, and hence the adapter structure is still
4993 * valid, before signaling completion */
4994 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4995 {
4996 complete(&pAdapter->session_close_comp_var);
4997 }
4998
Jeff Johnson295189b2012-06-20 16:38:30 -07004999 return eHAL_STATUS_SUCCESS;
5000}
5001
5002VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5003{
5004 struct net_device *pWlanDev = pAdapter->dev;
5005 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5006 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5007 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5008 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5009 int rc = 0;
5010
5011 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005012 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 //Open a SME session for future operation
5014 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005015 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005016 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5017 {
5018 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005019 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005020 halStatus, halStatus );
5021 status = VOS_STATUS_E_FAILURE;
5022 goto error_sme_open;
5023 }
5024
5025 //Block on a completion variable. Can't wait forever though.
5026 rc = wait_for_completion_interruptible_timeout(
5027 &pAdapter->session_open_comp_var,
5028 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5029 if (!rc)
5030 {
5031 hddLog(VOS_TRACE_LEVEL_FATAL,
5032 "Session is not opened within timeout period code %08d", rc );
5033 status = VOS_STATUS_E_FAILURE;
5034 goto error_sme_open;
5035 }
5036
5037 // Register wireless extensions
5038 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5039 {
5040 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005041 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005042 halStatus, halStatus );
5043 status = VOS_STATUS_E_FAILURE;
5044 goto error_register_wext;
5045 }
5046 //Safe to register the hard_start_xmit function again
5047#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5048 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5049#else
5050 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5051#endif
5052
5053 //Set the Connection State to Not Connected
5054 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5055
5056 //Set the default operation channel
5057 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5058
5059 /* Make the default Auth Type as OPEN*/
5060 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5061
5062 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5063 {
5064 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005065 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 status, status );
5067 goto error_init_txrx;
5068 }
5069
5070 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5071
5072 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5073 {
5074 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005075 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005076 status, status );
5077 goto error_wmm_init;
5078 }
5079
5080 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5081
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005082#ifdef FEATURE_WLAN_TDLS
5083 if(0 != wlan_hdd_tdls_init(pAdapter))
5084 {
5085 status = VOS_STATUS_E_FAILURE;
5086 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5087 goto error_tdls_init;
5088 }
5089 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5090#endif
5091
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 return VOS_STATUS_SUCCESS;
5093
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005094#ifdef FEATURE_WLAN_TDLS
5095error_tdls_init:
5096 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5097 hdd_wmm_adapter_close(pAdapter);
5098#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005099error_wmm_init:
5100 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5101 hdd_deinit_tx_rx(pAdapter);
5102error_init_txrx:
5103 hdd_UnregisterWext(pWlanDev);
5104error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005105 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 {
5107 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005108 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005110 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 {
5112 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005113 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005114 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005115 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 }
5117}
5118error_sme_open:
5119 return status;
5120}
5121
Jeff Johnson295189b2012-06-20 16:38:30 -07005122void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5123{
5124 hdd_cfg80211_state_t *cfgState;
5125
5126 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5127
5128 if( NULL != cfgState->buf )
5129 {
5130 int rc;
5131 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5132 rc = wait_for_completion_interruptible_timeout(
5133 &pAdapter->tx_action_cnf_event,
5134 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5135 if(!rc)
5136 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005137 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5139 }
5140 }
5141 return;
5142}
Jeff Johnson295189b2012-06-20 16:38:30 -07005143
5144void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5145{
5146 ENTER();
5147 switch ( pAdapter->device_mode )
5148 {
5149 case WLAN_HDD_INFRA_STATION:
5150 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005151 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005152 {
5153 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5154 {
5155 hdd_deinit_tx_rx( pAdapter );
5156 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5157 }
5158
5159 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5160 {
5161 hdd_wmm_adapter_close( pAdapter );
5162 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5163 }
5164
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005166#ifdef FEATURE_WLAN_TDLS
5167 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5168 {
5169 wlan_hdd_tdls_exit(pAdapter);
5170 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5171 }
5172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005173
5174 break;
5175 }
5176
5177 case WLAN_HDD_SOFTAP:
5178 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305180
5181 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5182 {
5183 hdd_wmm_adapter_close( pAdapter );
5184 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5185 }
5186
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005188
5189 hdd_unregister_hostapd(pAdapter);
5190 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 break;
5193 }
5194
5195 case WLAN_HDD_MONITOR:
5196 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005197 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005198 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5199 {
5200 hdd_deinit_tx_rx( pAdapter );
5201 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005203 if(NULL != pAdapterforTx)
5204 {
5205 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5206 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005207 break;
5208 }
5209
5210
5211 default:
5212 break;
5213 }
5214
5215 EXIT();
5216}
5217
5218void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5219{
5220 struct net_device *pWlanDev = pAdapter->dev;
5221
Rajeev79dbe4c2013-10-05 11:03:42 +05305222#ifdef FEATURE_WLAN_BATCH_SCAN
5223 tHddBatchScanRsp *pNode;
5224 tHddBatchScanRsp *pPrev;
5225 if (pAdapter)
5226 {
5227 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5228 pNode = pAdapter->pBatchScanRsp;
5229 while (pNode)
5230 {
5231 pPrev = pNode;
5232 pNode = pNode->pNext;
5233 vos_mem_free((v_VOID_t * )pPrev);
5234 }
5235 pAdapter->pBatchScanRsp = NULL;
5236 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5237 }
5238#endif
5239
Jeff Johnson295189b2012-06-20 16:38:30 -07005240 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5241 if( rtnl_held )
5242 {
5243 unregister_netdevice(pWlanDev);
5244 }
5245 else
5246 {
5247 unregister_netdev(pWlanDev);
5248 }
5249 // note that the pAdapter is no longer valid at this point
5250 // since the memory has been reclaimed
5251 }
5252
5253}
5254
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005255void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5256{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305257 VOS_STATUS status;
5258 hdd_adapter_t *pAdapter = NULL;
5259 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005260
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305261 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005262
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305263 /*loop through all adapters.*/
5264 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005265 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305266 pAdapter = pAdapterNode->pAdapter;
5267 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5268 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005269
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305270 { // we skip this registration for modes other than STA and P2P client modes.
5271 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5272 pAdapterNode = pNext;
5273 continue;
5274 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005275
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305276 //Apply Dynamic DTIM For P2P
5277 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5278 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5279 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5280 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5281 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5282 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5283 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5284 (eConnectionState_Associated ==
5285 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5286 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5287 {
5288 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005289
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305290 powerRequest.uIgnoreDTIM = 1;
5291 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5292
5293 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5294 {
5295 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5296 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5297 }
5298 else
5299 {
5300 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5301 }
5302
5303 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5304 * specified during Enter/Exit BMPS when LCD off*/
5305 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5306 NULL, eANI_BOOLEAN_FALSE);
5307 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5308 NULL, eANI_BOOLEAN_FALSE);
5309
5310 /* switch to the DTIM specified in cfg.ini */
5311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5312 "Switch to DTIM %d", powerRequest.uListenInterval);
5313 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5314 break;
5315
5316 }
5317
5318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5319 pAdapterNode = pNext;
5320 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005321}
5322
5323void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5324{
5325 /*Switch back to DTIM 1*/
5326 tSirSetPowerParamsReq powerRequest = { 0 };
5327
5328 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5329 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005330 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005331
5332 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5333 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5334 NULL, eANI_BOOLEAN_FALSE);
5335 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5336 NULL, eANI_BOOLEAN_FALSE);
5337
5338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5339 "Switch to DTIM%d",powerRequest.uListenInterval);
5340 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5341
5342}
5343
Jeff Johnson295189b2012-06-20 16:38:30 -07005344VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5345{
5346 VOS_STATUS status = VOS_STATUS_SUCCESS;
5347
5348 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5349 {
5350 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5351 }
5352
5353 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5354 {
5355 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5356 }
5357
5358 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5359 {
5360 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5361 }
5362
5363 return status;
5364}
5365
5366VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5367{
5368 hdd_adapter_t *pAdapter = NULL;
5369 eHalStatus halStatus;
5370 VOS_STATUS status = VOS_STATUS_E_INVAL;
5371 v_BOOL_t disableBmps = FALSE;
5372 v_BOOL_t disableImps = FALSE;
5373
5374 switch(session_type)
5375 {
5376 case WLAN_HDD_INFRA_STATION:
5377 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 case WLAN_HDD_P2P_CLIENT:
5379 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 //Exit BMPS -> Is Sta/P2P Client is already connected
5381 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5382 if((NULL != pAdapter)&&
5383 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5384 {
5385 disableBmps = TRUE;
5386 }
5387
5388 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5389 if((NULL != pAdapter)&&
5390 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5391 {
5392 disableBmps = TRUE;
5393 }
5394
5395 //Exit both Bmps and Imps incase of Go/SAP Mode
5396 if((WLAN_HDD_SOFTAP == session_type) ||
5397 (WLAN_HDD_P2P_GO == session_type))
5398 {
5399 disableBmps = TRUE;
5400 disableImps = TRUE;
5401 }
5402
5403 if(TRUE == disableImps)
5404 {
5405 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5406 {
5407 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5408 }
5409 }
5410
5411 if(TRUE == disableBmps)
5412 {
5413 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5414 {
5415 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5416
5417 if(eHAL_STATUS_SUCCESS != halStatus)
5418 {
5419 status = VOS_STATUS_E_FAILURE;
5420 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5421 VOS_ASSERT(0);
5422 return status;
5423 }
5424 }
5425
5426 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5427 {
5428 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5429
5430 if(eHAL_STATUS_SUCCESS != halStatus)
5431 {
5432 status = VOS_STATUS_E_FAILURE;
5433 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5434 VOS_ASSERT(0);
5435 return status;
5436 }
5437 }
5438 }
5439
5440 if((TRUE == disableBmps) ||
5441 (TRUE == disableImps))
5442 {
5443 /* Now, get the chip into Full Power now */
5444 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5445 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5446 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5447
5448 if(halStatus != eHAL_STATUS_SUCCESS)
5449 {
5450 if(halStatus == eHAL_STATUS_PMC_PENDING)
5451 {
5452 //Block on a completion variable. Can't wait forever though
5453 wait_for_completion_interruptible_timeout(
5454 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5455 }
5456 else
5457 {
5458 status = VOS_STATUS_E_FAILURE;
5459 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5460 VOS_ASSERT(0);
5461 return status;
5462 }
5463 }
5464
5465 status = VOS_STATUS_SUCCESS;
5466 }
5467
5468 break;
5469 }
5470 return status;
5471}
5472
5473hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005474 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 tANI_U8 rtnl_held )
5476{
5477 hdd_adapter_t *pAdapter = NULL;
5478 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5479 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5480 VOS_STATUS exitbmpsStatus;
5481
5482 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5483
5484 //Disable BMPS incase of Concurrency
5485 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5486
5487 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5488 {
5489 //Fail to Exit BMPS
5490 VOS_ASSERT(0);
5491 return NULL;
5492 }
5493
5494 switch(session_type)
5495 {
5496 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005498 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 {
5500 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5501
5502 if( NULL == pAdapter )
5503 return NULL;
5504
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305505#ifdef FEATURE_WLAN_TDLS
5506 /* A Mutex Lock is introduced while changing/initializing the mode to
5507 * protect the concurrent access for the Adapters by TDLS module.
5508 */
5509 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5510 {
5511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5512 "%s: unable to lock list", __func__);
5513 return NULL;
5514 }
5515#endif
5516
Jeff Johnsone7245742012-09-05 17:12:55 -07005517 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5518 NL80211_IFTYPE_P2P_CLIENT:
5519 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005520
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 pAdapter->device_mode = session_type;
5522
5523 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305524#ifdef FEATURE_WLAN_TDLS
5525 mutex_unlock(&pHddCtx->tdls_lock);
5526#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005527 if( VOS_STATUS_SUCCESS != status )
5528 goto err_free_netdev;
5529
5530 status = hdd_register_interface( pAdapter, rtnl_held );
5531 if( VOS_STATUS_SUCCESS != status )
5532 {
5533 hdd_deinit_adapter(pHddCtx, pAdapter);
5534 goto err_free_netdev;
5535 }
5536 //Stop the Interface TX queue.
5537 netif_tx_disable(pAdapter->dev);
5538 //netif_tx_disable(pWlanDev);
5539 netif_carrier_off(pAdapter->dev);
5540
5541 break;
5542 }
5543
Jeff Johnson295189b2012-06-20 16:38:30 -07005544 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005545 case WLAN_HDD_SOFTAP:
5546 {
5547 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5548 if( NULL == pAdapter )
5549 return NULL;
5550
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5552 NL80211_IFTYPE_AP:
5553 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 pAdapter->device_mode = session_type;
5555
5556 status = hdd_init_ap_mode(pAdapter);
5557 if( VOS_STATUS_SUCCESS != status )
5558 goto err_free_netdev;
5559
5560 status = hdd_register_hostapd( pAdapter, rtnl_held );
5561 if( VOS_STATUS_SUCCESS != status )
5562 {
5563 hdd_deinit_adapter(pHddCtx, pAdapter);
5564 goto err_free_netdev;
5565 }
5566
5567 netif_tx_disable(pAdapter->dev);
5568 netif_carrier_off(pAdapter->dev);
5569
5570 hdd_set_conparam( 1 );
5571 break;
5572 }
5573 case WLAN_HDD_MONITOR:
5574 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005575 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5576 if( NULL == pAdapter )
5577 return NULL;
5578
5579 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5580 pAdapter->device_mode = session_type;
5581 status = hdd_register_interface( pAdapter, rtnl_held );
5582#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5583 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5584#else
5585 pAdapter->dev->open = hdd_mon_open;
5586 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5587#endif
5588 hdd_init_tx_rx( pAdapter );
5589 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5590 //Set adapter to be used for data tx. It will use either GO or softap.
5591 pAdapter->sessionCtx.monitor.pAdapterForTx =
5592 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005593 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5594 {
5595 pAdapter->sessionCtx.monitor.pAdapterForTx =
5596 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5597 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 /* This workqueue will be used to transmit management packet over
5599 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005600 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5601 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5602 return NULL;
5603 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005604
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5606 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 }
5608 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005609 case WLAN_HDD_FTM:
5610 {
5611 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5612
5613 if( NULL == pAdapter )
5614 return NULL;
5615 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5616 * message while loading driver in FTM mode. */
5617 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5618 pAdapter->device_mode = session_type;
5619 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305620
5621 hdd_init_tx_rx( pAdapter );
5622
5623 //Stop the Interface TX queue.
5624 netif_tx_disable(pAdapter->dev);
5625 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 }
5627 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 default:
5629 {
5630 VOS_ASSERT(0);
5631 return NULL;
5632 }
5633 }
5634
5635
5636 if( VOS_STATUS_SUCCESS == status )
5637 {
5638 //Add it to the hdd's session list.
5639 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5640 if( NULL == pHddAdapterNode )
5641 {
5642 status = VOS_STATUS_E_NOMEM;
5643 }
5644 else
5645 {
5646 pHddAdapterNode->pAdapter = pAdapter;
5647 status = hdd_add_adapter_back ( pHddCtx,
5648 pHddAdapterNode );
5649 }
5650 }
5651
5652 if( VOS_STATUS_SUCCESS != status )
5653 {
5654 if( NULL != pAdapter )
5655 {
5656 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5657 pAdapter = NULL;
5658 }
5659 if( NULL != pHddAdapterNode )
5660 {
5661 vos_mem_free( pHddAdapterNode );
5662 }
5663
5664 goto resume_bmps;
5665 }
5666
5667 if(VOS_STATUS_SUCCESS == status)
5668 {
5669 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5670
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005671 //Initialize the WoWL service
5672 if(!hdd_init_wowl(pAdapter))
5673 {
5674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5675 goto err_free_netdev;
5676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005677 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005678 return pAdapter;
5679
5680err_free_netdev:
5681 free_netdev(pAdapter->dev);
5682 wlan_hdd_release_intf_addr( pHddCtx,
5683 pAdapter->macAddressCurrent.bytes );
5684
5685resume_bmps:
5686 //If bmps disabled enable it
5687 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5688 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305689 if (pHddCtx->hdd_wlan_suspended)
5690 {
5691 hdd_set_pwrparams(pHddCtx);
5692 }
5693 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005694 }
5695 return NULL;
5696}
5697
5698VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5699 tANI_U8 rtnl_held )
5700{
5701 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5702 VOS_STATUS status;
5703
5704 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5705 if( VOS_STATUS_SUCCESS != status )
5706 return status;
5707
5708 while ( pCurrent->pAdapter != pAdapter )
5709 {
5710 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5711 if( VOS_STATUS_SUCCESS != status )
5712 break;
5713
5714 pCurrent = pNext;
5715 }
5716 pAdapterNode = pCurrent;
5717 if( VOS_STATUS_SUCCESS == status )
5718 {
5719 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5720 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305721
5722#ifdef FEATURE_WLAN_TDLS
5723
5724 /* A Mutex Lock is introduced while changing/initializing the mode to
5725 * protect the concurrent access for the Adapters by TDLS module.
5726 */
5727 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5728 {
5729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5730 "%s: unable to lock list", __func__);
5731 return VOS_STATUS_E_FAILURE;
5732 }
5733#endif
5734
Jeff Johnson295189b2012-06-20 16:38:30 -07005735 hdd_remove_adapter( pHddCtx, pAdapterNode );
5736 vos_mem_free( pAdapterNode );
5737
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305738#ifdef FEATURE_WLAN_TDLS
5739 mutex_unlock(&pHddCtx->tdls_lock);
5740#endif
5741
Jeff Johnson295189b2012-06-20 16:38:30 -07005742
5743 /* If there is a single session of STA/P2P client, re-enable BMPS */
5744 if ((!vos_concurrent_sessions_running()) &&
5745 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5746 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5747 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305748 if (pHddCtx->hdd_wlan_suspended)
5749 {
5750 hdd_set_pwrparams(pHddCtx);
5751 }
5752 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 }
5754
5755 return VOS_STATUS_SUCCESS;
5756 }
5757
5758 return VOS_STATUS_E_FAILURE;
5759}
5760
5761VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5762{
5763 hdd_adapter_list_node_t *pHddAdapterNode;
5764 VOS_STATUS status;
5765
5766 ENTER();
5767
5768 do
5769 {
5770 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5771 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5772 {
5773 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5774 vos_mem_free( pHddAdapterNode );
5775 }
5776 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5777
5778 EXIT();
5779
5780 return VOS_STATUS_SUCCESS;
5781}
5782
5783void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5784{
5785 v_U8_t addIE[1] = {0};
5786
5787 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5788 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5789 eANI_BOOLEAN_FALSE) )
5790 {
5791 hddLog(LOGE,
5792 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5793 }
5794
5795 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5796 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5797 eANI_BOOLEAN_FALSE) )
5798 {
5799 hddLog(LOGE,
5800 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5801 }
5802
5803 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5804 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5805 eANI_BOOLEAN_FALSE) )
5806 {
5807 hddLog(LOGE,
5808 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5809 }
5810}
5811
5812VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5813{
5814 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5816 union iwreq_data wrqu;
5817
5818 ENTER();
5819
5820 switch(pAdapter->device_mode)
5821 {
5822 case WLAN_HDD_INFRA_STATION:
5823 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005824 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005825 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5826 {
5827 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5828 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5829 pAdapter->sessionId,
5830 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5831 else
5832 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5833 pAdapter->sessionId,
5834 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5835 //success implies disconnect command got queued up successfully
5836 if(halStatus == eHAL_STATUS_SUCCESS)
5837 {
5838 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5839 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5840 }
5841 memset(&wrqu, '\0', sizeof(wrqu));
5842 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5843 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5844 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5845 }
5846 else
5847 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305848 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 }
5850
5851 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5852 {
5853 INIT_COMPLETION(pAdapter->session_close_comp_var);
5854 if (eHAL_STATUS_SUCCESS ==
5855 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5856 hdd_smeCloseSessionCallback, pAdapter))
5857 {
5858 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005859 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 &pAdapter->session_close_comp_var,
5861 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5862 }
5863 }
5864
5865 break;
5866
5867 case WLAN_HDD_SOFTAP:
5868 case WLAN_HDD_P2P_GO:
5869 //Any softap specific cleanup here...
5870 mutex_lock(&pHddCtx->sap_lock);
5871 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5872 {
5873 VOS_STATUS status;
5874 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5875
5876 //Stop Bss.
5877 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5878 if (VOS_IS_STATUS_SUCCESS(status))
5879 {
5880 hdd_hostapd_state_t *pHostapdState =
5881 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5882
5883 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5884
5885 if (!VOS_IS_STATUS_SUCCESS(status))
5886 {
5887 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005888 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 }
5890 }
5891 else
5892 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005893 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 }
5895 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5896
5897 if (eHAL_STATUS_FAILURE ==
5898 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5899 0, NULL, eANI_BOOLEAN_FALSE))
5900 {
5901 hddLog(LOGE,
5902 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005903 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 }
5905
5906 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5907 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5908 eANI_BOOLEAN_FALSE) )
5909 {
5910 hddLog(LOGE,
5911 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5912 }
5913
5914 // Reset WNI_CFG_PROBE_RSP Flags
5915 wlan_hdd_reset_prob_rspies(pAdapter);
5916 kfree(pAdapter->sessionCtx.ap.beacon);
5917 pAdapter->sessionCtx.ap.beacon = NULL;
5918 }
5919 mutex_unlock(&pHddCtx->sap_lock);
5920 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005921
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005923#ifdef WLAN_OPEN_SOURCE
5924 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
5925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005927
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 default:
5929 break;
5930 }
5931
5932 EXIT();
5933 return VOS_STATUS_SUCCESS;
5934}
5935
5936VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5937{
5938 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5939 VOS_STATUS status;
5940 hdd_adapter_t *pAdapter;
5941
5942 ENTER();
5943
5944 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5945
5946 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5947 {
5948 pAdapter = pAdapterNode->pAdapter;
5949 netif_tx_disable(pAdapter->dev);
5950 netif_carrier_off(pAdapter->dev);
5951
5952 hdd_stop_adapter( pHddCtx, pAdapter );
5953
5954 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5955 pAdapterNode = pNext;
5956 }
5957
5958 EXIT();
5959
5960 return VOS_STATUS_SUCCESS;
5961}
5962
5963VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5964{
5965 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5966 VOS_STATUS status;
5967 hdd_adapter_t *pAdapter;
5968
5969 ENTER();
5970
5971 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5972
5973 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5974 {
5975 pAdapter = pAdapterNode->pAdapter;
5976 netif_tx_disable(pAdapter->dev);
5977 netif_carrier_off(pAdapter->dev);
5978
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005979 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5980
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305982 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5983 {
5984 hdd_wmm_adapter_close( pAdapter );
5985 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005987
5988 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5989 pAdapterNode = pNext;
5990 }
5991
5992 EXIT();
5993
5994 return VOS_STATUS_SUCCESS;
5995}
5996
5997VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5998{
5999 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6000 VOS_STATUS status;
6001 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306002 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006003
6004 ENTER();
6005
6006 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6007
6008 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6009 {
6010 pAdapter = pAdapterNode->pAdapter;
6011
6012 switch(pAdapter->device_mode)
6013 {
6014 case WLAN_HDD_INFRA_STATION:
6015 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006016 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306017
6018 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6019
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 hdd_init_station_mode(pAdapter);
6021 /* Open the gates for HDD to receive Wext commands */
6022 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006023 pHddCtx->scan_info.mScanPending = FALSE;
6024 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006025
6026 //Trigger the initial scan
6027 hdd_wlan_initial_scan(pAdapter);
6028
6029 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306030 if (eConnectionState_Associated == connState ||
6031 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 {
6033 union iwreq_data wrqu;
6034 memset(&wrqu, '\0', sizeof(wrqu));
6035 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6036 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6037 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006038 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006039
Jeff Johnson295189b2012-06-20 16:38:30 -07006040 /* indicate disconnected event to nl80211 */
6041 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6042 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306044 else if (eConnectionState_Connecting == connState)
6045 {
6046 /*
6047 * Indicate connect failure to supplicant if we were in the
6048 * process of connecting
6049 */
6050 cfg80211_connect_result(pAdapter->dev, NULL,
6051 NULL, 0, NULL, 0,
6052 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6053 GFP_KERNEL);
6054 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 break;
6056
6057 case WLAN_HDD_SOFTAP:
6058 /* softAP can handle SSR */
6059 break;
6060
6061 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006062 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006063 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006064 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006065 break;
6066
6067 case WLAN_HDD_MONITOR:
6068 /* monitor interface start */
6069 break;
6070 default:
6071 break;
6072 }
6073
6074 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6075 pAdapterNode = pNext;
6076 }
6077
6078 EXIT();
6079
6080 return VOS_STATUS_SUCCESS;
6081}
6082
6083VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6084{
6085 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6086 hdd_adapter_t *pAdapter;
6087 VOS_STATUS status;
6088 v_U32_t roamId;
6089
6090 ENTER();
6091
6092 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6093
6094 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6095 {
6096 pAdapter = pAdapterNode->pAdapter;
6097
6098 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6099 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6100 {
6101 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6102 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6103
6104 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6105 init_completion(&pAdapter->disconnect_comp_var);
6106 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6107 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6108
6109 wait_for_completion_interruptible_timeout(
6110 &pAdapter->disconnect_comp_var,
6111 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6112
6113 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6114 pHddCtx->isAmpAllowed = VOS_FALSE;
6115 sme_RoamConnect(pHddCtx->hHal,
6116 pAdapter->sessionId, &(pWextState->roamProfile),
6117 &roamId);
6118 }
6119
6120 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6121 pAdapterNode = pNext;
6122 }
6123
6124 EXIT();
6125
6126 return VOS_STATUS_SUCCESS;
6127}
6128
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006129void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6130{
6131 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6132 VOS_STATUS status;
6133 hdd_adapter_t *pAdapter;
6134 hdd_station_ctx_t *pHddStaCtx;
6135 hdd_ap_ctx_t *pHddApCtx;
6136 hdd_hostapd_state_t * pHostapdState;
6137 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6138 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6139 const char *p2pMode = "DEV";
6140 const char *ccMode = "Standalone";
6141 int n;
6142
6143 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6144 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6145 {
6146 pAdapter = pAdapterNode->pAdapter;
6147 switch (pAdapter->device_mode) {
6148 case WLAN_HDD_INFRA_STATION:
6149 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6150 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6151 staChannel = pHddStaCtx->conn_info.operationChannel;
6152 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6153 }
6154 break;
6155 case WLAN_HDD_P2P_CLIENT:
6156 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6157 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6158 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6159 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6160 p2pMode = "CLI";
6161 }
6162 break;
6163 case WLAN_HDD_P2P_GO:
6164 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6165 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6166 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6167 p2pChannel = pHddApCtx->operatingChannel;
6168 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6169 }
6170 p2pMode = "GO";
6171 break;
6172 case WLAN_HDD_SOFTAP:
6173 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6174 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6175 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6176 apChannel = pHddApCtx->operatingChannel;
6177 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6178 }
6179 break;
6180 default:
6181 break;
6182 }
6183 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6184 pAdapterNode = pNext;
6185 }
6186 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6187 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6188 }
6189 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6190 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6191 if (p2pChannel > 0) {
6192 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6193 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6194 }
6195 if (apChannel > 0) {
6196 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6197 apChannel, MAC_ADDR_ARRAY(apBssid));
6198 }
6199
6200 if (p2pChannel > 0 && apChannel > 0) {
6201 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6202 }
6203}
6204
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006205bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006206{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006207 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006208}
6209
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006210/* Once SSR is disabled then it cannot be set. */
6211void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006212{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006213 if (HDD_SSR_DISABLED == isSsrRequired)
6214 return;
6215
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 isSsrRequired = value;
6217}
6218
6219VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6220 hdd_adapter_list_node_t** ppAdapterNode)
6221{
6222 VOS_STATUS status;
6223 spin_lock(&pHddCtx->hddAdapters.lock);
6224 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6225 (hdd_list_node_t**) ppAdapterNode );
6226 spin_unlock(&pHddCtx->hddAdapters.lock);
6227 return status;
6228}
6229
6230VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6231 hdd_adapter_list_node_t* pAdapterNode,
6232 hdd_adapter_list_node_t** pNextAdapterNode)
6233{
6234 VOS_STATUS status;
6235 spin_lock(&pHddCtx->hddAdapters.lock);
6236 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6237 (hdd_list_node_t*) pAdapterNode,
6238 (hdd_list_node_t**)pNextAdapterNode );
6239
6240 spin_unlock(&pHddCtx->hddAdapters.lock);
6241 return status;
6242}
6243
6244VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6245 hdd_adapter_list_node_t* pAdapterNode)
6246{
6247 VOS_STATUS status;
6248 spin_lock(&pHddCtx->hddAdapters.lock);
6249 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6250 &pAdapterNode->node );
6251 spin_unlock(&pHddCtx->hddAdapters.lock);
6252 return status;
6253}
6254
6255VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6256 hdd_adapter_list_node_t** ppAdapterNode)
6257{
6258 VOS_STATUS status;
6259 spin_lock(&pHddCtx->hddAdapters.lock);
6260 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6261 (hdd_list_node_t**) ppAdapterNode );
6262 spin_unlock(&pHddCtx->hddAdapters.lock);
6263 return status;
6264}
6265
6266VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6267 hdd_adapter_list_node_t* pAdapterNode)
6268{
6269 VOS_STATUS status;
6270 spin_lock(&pHddCtx->hddAdapters.lock);
6271 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6272 (hdd_list_node_t*) pAdapterNode );
6273 spin_unlock(&pHddCtx->hddAdapters.lock);
6274 return status;
6275}
6276
6277VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6278 hdd_adapter_list_node_t* pAdapterNode)
6279{
6280 VOS_STATUS status;
6281 spin_lock(&pHddCtx->hddAdapters.lock);
6282 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6283 (hdd_list_node_t*) pAdapterNode );
6284 spin_unlock(&pHddCtx->hddAdapters.lock);
6285 return status;
6286}
6287
6288hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6289 tSirMacAddr macAddr )
6290{
6291 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6292 hdd_adapter_t *pAdapter;
6293 VOS_STATUS status;
6294
6295 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6296
6297 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6298 {
6299 pAdapter = pAdapterNode->pAdapter;
6300
6301 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6302 macAddr, sizeof(tSirMacAddr) ) )
6303 {
6304 return pAdapter;
6305 }
6306 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6307 pAdapterNode = pNext;
6308 }
6309
6310 return NULL;
6311
6312}
6313
6314hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6315{
6316 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6317 hdd_adapter_t *pAdapter;
6318 VOS_STATUS status;
6319
6320 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6321
6322 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6323 {
6324 pAdapter = pAdapterNode->pAdapter;
6325
6326 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6327 IFNAMSIZ ) )
6328 {
6329 return pAdapter;
6330 }
6331 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6332 pAdapterNode = pNext;
6333 }
6334
6335 return NULL;
6336
6337}
6338
6339hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6340{
6341 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6342 hdd_adapter_t *pAdapter;
6343 VOS_STATUS status;
6344
6345 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6346
6347 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6348 {
6349 pAdapter = pAdapterNode->pAdapter;
6350
6351 if( pAdapter && (mode == pAdapter->device_mode) )
6352 {
6353 return pAdapter;
6354 }
6355 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6356 pAdapterNode = pNext;
6357 }
6358
6359 return NULL;
6360
6361}
6362
6363//Remove this function later
6364hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6365{
6366 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6367 hdd_adapter_t *pAdapter;
6368 VOS_STATUS status;
6369
6370 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6371
6372 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6373 {
6374 pAdapter = pAdapterNode->pAdapter;
6375
6376 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6377 {
6378 return pAdapter;
6379 }
6380
6381 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6382 pAdapterNode = pNext;
6383 }
6384
6385 return NULL;
6386
6387}
6388
Jeff Johnson295189b2012-06-20 16:38:30 -07006389/**---------------------------------------------------------------------------
6390
6391 \brief hdd_set_monitor_tx_adapter() -
6392
6393 This API initializes the adapter to be used while transmitting on monitor
6394 adapter.
6395
6396 \param - pHddCtx - Pointer to the HDD context.
6397 pAdapter - Adapter that will used for TX. This can be NULL.
6398 \return - None.
6399 --------------------------------------------------------------------------*/
6400void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6401{
6402 hdd_adapter_t *pMonAdapter;
6403
6404 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6405
6406 if( NULL != pMonAdapter )
6407 {
6408 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6409 }
6410}
Jeff Johnson295189b2012-06-20 16:38:30 -07006411/**---------------------------------------------------------------------------
6412
6413 \brief hdd_select_queue() -
6414
6415 This API returns the operating channel of the requested device mode
6416
6417 \param - pHddCtx - Pointer to the HDD context.
6418 - mode - Device mode for which operating channel is required
6419 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6420 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6421 \return - channel number. "0" id the requested device is not found OR it is not connected.
6422 --------------------------------------------------------------------------*/
6423v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6424{
6425 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6426 VOS_STATUS status;
6427 hdd_adapter_t *pAdapter;
6428 v_U8_t operatingChannel = 0;
6429
6430 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6431
6432 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6433 {
6434 pAdapter = pAdapterNode->pAdapter;
6435
6436 if( mode == pAdapter->device_mode )
6437 {
6438 switch(pAdapter->device_mode)
6439 {
6440 case WLAN_HDD_INFRA_STATION:
6441 case WLAN_HDD_P2P_CLIENT:
6442 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6443 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6444 break;
6445 case WLAN_HDD_SOFTAP:
6446 case WLAN_HDD_P2P_GO:
6447 /*softap connection info */
6448 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6449 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6450 break;
6451 default:
6452 break;
6453 }
6454
6455 break; //Found the device of interest. break the loop
6456 }
6457
6458 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6459 pAdapterNode = pNext;
6460 }
6461 return operatingChannel;
6462}
6463
6464#ifdef WLAN_FEATURE_PACKET_FILTERING
6465/**---------------------------------------------------------------------------
6466
6467 \brief hdd_set_multicast_list() -
6468
6469 This used to set the multicast address list.
6470
6471 \param - dev - Pointer to the WLAN device.
6472 - skb - Pointer to OS packet (sk_buff).
6473 \return - success/fail
6474
6475 --------------------------------------------------------------------------*/
6476static void hdd_set_multicast_list(struct net_device *dev)
6477{
6478 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006479 int mc_count;
6480 int i = 0;
6481 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306482
6483 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 {
6485 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306486 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006487 return;
6488 }
6489
6490 if (dev->flags & IFF_ALLMULTI)
6491 {
6492 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006493 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306494 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006495 }
6496 else
6497 {
6498 mc_count = netdev_mc_count(dev);
6499 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006500 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006501 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6502 {
6503 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006504 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306505 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006506 return;
6507 }
6508
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306509 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006510
6511 netdev_for_each_mc_addr(ha, dev) {
6512 if (i == mc_count)
6513 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306514 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6515 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6516 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306518 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006519 i++;
6520 }
6521 }
6522 return;
6523}
6524#endif
6525
6526/**---------------------------------------------------------------------------
6527
6528 \brief hdd_select_queue() -
6529
6530 This function is registered with the Linux OS for network
6531 core to decide which queue to use first.
6532
6533 \param - dev - Pointer to the WLAN device.
6534 - skb - Pointer to OS packet (sk_buff).
6535 \return - ac, Queue Index/access category corresponding to UP in IP header
6536
6537 --------------------------------------------------------------------------*/
6538v_U16_t hdd_select_queue(struct net_device *dev,
6539 struct sk_buff *skb)
6540{
6541 return hdd_wmm_select_queue(dev, skb);
6542}
6543
6544
6545/**---------------------------------------------------------------------------
6546
6547 \brief hdd_wlan_initial_scan() -
6548
6549 This function triggers the initial scan
6550
6551 \param - pAdapter - Pointer to the HDD adapter.
6552
6553 --------------------------------------------------------------------------*/
6554void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6555{
6556 tCsrScanRequest scanReq;
6557 tCsrChannelInfo channelInfo;
6558 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006559 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6561
6562 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6563 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6564 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6565
6566 if(sme_Is11dSupported(pHddCtx->hHal))
6567 {
6568 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6569 if ( HAL_STATUS_SUCCESS( halStatus ) )
6570 {
6571 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6572 if( !scanReq.ChannelInfo.ChannelList )
6573 {
6574 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6575 vos_mem_free(channelInfo.ChannelList);
6576 return;
6577 }
6578 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6579 channelInfo.numOfChannels);
6580 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6581 vos_mem_free(channelInfo.ChannelList);
6582 }
6583
6584 scanReq.scanType = eSIR_PASSIVE_SCAN;
6585 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6586 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6587 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6588 }
6589 else
6590 {
6591 scanReq.scanType = eSIR_ACTIVE_SCAN;
6592 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6593 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6594 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6595 }
6596
6597 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6598 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6599 {
6600 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6601 __func__, halStatus );
6602 }
6603
6604 if(sme_Is11dSupported(pHddCtx->hHal))
6605 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6606}
6607
6608struct fullPowerContext
6609{
6610 struct completion completion;
6611 unsigned int magic;
6612};
6613#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6614
6615/**---------------------------------------------------------------------------
6616
6617 \brief hdd_full_power_callback() - HDD full power callback function
6618
6619 This is the function invoked by SME to inform the result of a full power
6620 request issued by HDD
6621
6622 \param - callbackcontext - Pointer to cookie
6623 \param - status - result of request
6624
6625 \return - None
6626
6627 --------------------------------------------------------------------------*/
6628static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6629{
6630 struct fullPowerContext *pContext = callbackContext;
6631
6632 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306633 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006634
6635 if (NULL == callbackContext)
6636 {
6637 hddLog(VOS_TRACE_LEVEL_ERROR,
6638 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006639 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006640 return;
6641 }
6642
6643 /* there is a race condition that exists between this callback function
6644 and the caller since the caller could time out either before or
6645 while this code is executing. we'll assume the timeout hasn't
6646 occurred, but we'll verify that right before we save our work */
6647
6648 if (POWER_CONTEXT_MAGIC != pContext->magic)
6649 {
6650 /* the caller presumably timed out so there is nothing we can do */
6651 hddLog(VOS_TRACE_LEVEL_WARN,
6652 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006653 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006654 return;
6655 }
6656
6657 /* the race is on. caller could have timed out immediately after
6658 we verified the magic, but if so, caller will wait a short time
6659 for us to notify the caller, so the context will stay valid */
6660 complete(&pContext->completion);
6661}
6662
6663/**---------------------------------------------------------------------------
6664
6665 \brief hdd_wlan_exit() - HDD WLAN exit function
6666
6667 This is the driver exit point (invoked during rmmod)
6668
6669 \param - pHddCtx - Pointer to the HDD Context
6670
6671 \return - None
6672
6673 --------------------------------------------------------------------------*/
6674void hdd_wlan_exit(hdd_context_t *pHddCtx)
6675{
6676 eHalStatus halStatus;
6677 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6678 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306679 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006680 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006681 struct fullPowerContext powerContext;
6682 long lrc;
6683
6684 ENTER();
6685
Jeff Johnson88ba7742013-02-27 14:36:02 -08006686 if (VOS_FTM_MODE != hdd_get_conparam())
6687 {
6688 // Unloading, restart logic is no more required.
6689 wlan_hdd_restart_deinit(pHddCtx);
6690 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006691
Jeff Johnson295189b2012-06-20 16:38:30 -07006692 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006694 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006695 {
6696 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6697 WLAN_HDD_INFRA_STATION);
6698 if (pAdapter == NULL)
6699 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6700
6701 if (pAdapter != NULL)
6702 {
6703 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6704 hdd_UnregisterWext(pAdapter->dev);
6705 }
6706 }
6707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006708
Jeff Johnson295189b2012-06-20 16:38:30 -07006709 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006710 {
6711 wlan_hdd_ftm_close(pHddCtx);
6712 goto free_hdd_ctx;
6713 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006714 //Stop the Interface TX queue.
6715 //netif_tx_disable(pWlanDev);
6716 //netif_carrier_off(pWlanDev);
6717
Jeff Johnson295189b2012-06-20 16:38:30 -07006718 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6719 {
6720 pAdapter = hdd_get_adapter(pHddCtx,
6721 WLAN_HDD_SOFTAP);
6722 }
6723 else
6724 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006725 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 {
6727 pAdapter = hdd_get_adapter(pHddCtx,
6728 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006729 if (pAdapter == NULL)
6730 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006731 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006732 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006733 /* DeRegister with platform driver as client for Suspend/Resume */
6734 vosStatus = hddDeregisterPmOps(pHddCtx);
6735 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6736 {
6737 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6738 VOS_ASSERT(0);
6739 }
6740
6741 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6742 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6743 {
6744 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6745 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006746
6747 // Cancel any outstanding scan requests. We are about to close all
6748 // of our adapters, but an adapter structure is what SME passes back
6749 // to our callback function. Hence if there are any outstanding scan
6750 // requests then there is a race condition between when the adapter
6751 // is closed and when the callback is invoked. We try to resolve that
6752 // race condition here by canceling any outstanding scans before we
6753 // close the adapters.
6754 // Note that the scans may be cancelled in an asynchronous manner, so
6755 // ideally there needs to be some kind of synchronization. Rather than
6756 // introduce a new synchronization here, we will utilize the fact that
6757 // we are about to Request Full Power, and since that is synchronized,
6758 // the expectation is that by the time Request Full Power has completed,
6759 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006760 if (NULL != pAdapter)
6761 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6762 else
6763 hddLog(VOS_TRACE_LEVEL_ERROR,
6764 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006765
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006766 //Stop the traffic monitor timer
6767 if ( VOS_TIMER_STATE_RUNNING ==
6768 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6769 {
6770 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6771 }
6772
6773 // Destroy the traffic monitor timer
6774 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6775 &pHddCtx->tx_rx_trafficTmr)))
6776 {
6777 hddLog(VOS_TRACE_LEVEL_ERROR,
6778 "%s: Cannot deallocate Traffic monitor timer", __func__);
6779 }
6780
Jeff Johnson295189b2012-06-20 16:38:30 -07006781 //Disable IMPS/BMPS as we do not want the device to enter any power
6782 //save mode during shutdown
6783 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6784 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6785 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6786
6787 //Ensure that device is in full power as we will touch H/W during vos_Stop
6788 init_completion(&powerContext.completion);
6789 powerContext.magic = POWER_CONTEXT_MAGIC;
6790
6791 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6792 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6793
6794 if (eHAL_STATUS_SUCCESS != halStatus)
6795 {
6796 if (eHAL_STATUS_PMC_PENDING == halStatus)
6797 {
6798 /* request was sent -- wait for the response */
6799 lrc = wait_for_completion_interruptible_timeout(
6800 &powerContext.completion,
6801 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6802 /* either we have a response or we timed out
6803 either way, first invalidate our magic */
6804 powerContext.magic = 0;
6805 if (lrc <= 0)
6806 {
6807 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006808 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006809 /* there is a race condition such that the callback
6810 function could be executing at the same time we are. of
6811 primary concern is if the callback function had already
6812 verified the "magic" but hasn't yet set the completion
6813 variable. Since the completion variable is on our
6814 stack, we'll delay just a bit to make sure the data is
6815 still valid if that is the case */
6816 msleep(50);
6817 }
6818 }
6819 else
6820 {
6821 hddLog(VOS_TRACE_LEVEL_ERROR,
6822 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006823 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006824 VOS_ASSERT(0);
6825 /* continue -- need to clean up as much as possible */
6826 }
6827 }
6828
Yue Ma0d4891e2013-08-06 17:01:45 -07006829 hdd_debugfs_exit(pHddCtx);
6830
Jeff Johnson295189b2012-06-20 16:38:30 -07006831 // Unregister the Net Device Notifier
6832 unregister_netdevice_notifier(&hdd_netdev_notifier);
6833
Jeff Johnson295189b2012-06-20 16:38:30 -07006834 hdd_stop_all_adapters( pHddCtx );
6835
Jeff Johnson295189b2012-06-20 16:38:30 -07006836#ifdef WLAN_BTAMP_FEATURE
6837 vosStatus = WLANBAP_Stop(pVosContext);
6838 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6839 {
6840 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6841 "%s: Failed to stop BAP",__func__);
6842 }
6843#endif //WLAN_BTAMP_FEATURE
6844
6845 //Stop all the modules
6846 vosStatus = vos_stop( pVosContext );
6847 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6848 {
6849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6850 "%s: Failed to stop VOSS",__func__);
6851 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6852 }
6853
Jeff Johnson295189b2012-06-20 16:38:30 -07006854 //Assert Deep sleep signal now to put Libra HW in lowest power state
6855 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6856 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6857
6858 //Vote off any PMIC voltage supplies
6859 vos_chipPowerDown(NULL, NULL, NULL);
6860
6861 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6862
Leo Chang59cdc7e2013-07-10 10:08:21 -07006863
Jeff Johnson295189b2012-06-20 16:38:30 -07006864 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006866
6867 //Close the scheduler before calling vos_close to make sure no thread is
6868 // scheduled after the each module close is called i.e after all the data
6869 // structures are freed.
6870 vosStatus = vos_sched_close( pVosContext );
6871 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6872 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6873 "%s: Failed to close VOSS Scheduler",__func__);
6874 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6875 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006876#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006877#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6878 /* Destroy the wake lock */
6879 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6880#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006881 /* Destroy the wake lock */
6882 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006883#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006884
6885 //Close VOSS
6886 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6887 vos_close(pVosContext);
6888
Jeff Johnson295189b2012-06-20 16:38:30 -07006889 //Close Watchdog
6890 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6891 vos_watchdog_close(pVosContext);
6892
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306893 //Clean up HDD Nlink Service
6894 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006895#ifdef WLAN_KD_READY_NOTIFIER
6896 nl_srv_exit(pHddCtx->ptt_pid);
6897#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306898 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006899#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306900
Jeff Johnson295189b2012-06-20 16:38:30 -07006901 /* Cancel the vote for XO Core ON.
6902 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6903 * exited at this point
6904 */
6905 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6906 " when WLAN is turned OFF\n");
6907 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6908 {
6909 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6910 " Not returning failure."
6911 " Power consumed will be high\n");
6912 }
6913
6914 hdd_close_all_adapters( pHddCtx );
6915
6916
6917 //Free up dynamically allocated members inside HDD Adapter
6918 kfree(pHddCtx->cfg_ini);
6919 pHddCtx->cfg_ini= NULL;
6920
6921 /* free the power on lock from platform driver */
6922 if (free_riva_power_on_lock("wlan"))
6923 {
6924 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6925 __func__);
6926 }
6927
Jeff Johnson88ba7742013-02-27 14:36:02 -08006928free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006929 /* FTM mode, WIPHY did not registered
6930 If un-register here, system crash will happen */
6931 if (VOS_FTM_MODE != hdd_get_conparam())
6932 {
6933 wiphy_unregister(wiphy) ;
6934 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006935 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 if (hdd_is_ssr_required())
6937 {
6938 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006939 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006940 msleep(5000);
6941 }
6942 hdd_set_ssr_required (VOS_FALSE);
6943}
6944
6945
6946/**---------------------------------------------------------------------------
6947
6948 \brief hdd_update_config_from_nv() - Function to update the contents of
6949 the running configuration with parameters taken from NV storage
6950
6951 \param - pHddCtx - Pointer to the HDD global context
6952
6953 \return - VOS_STATUS_SUCCESS if successful
6954
6955 --------------------------------------------------------------------------*/
6956static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6957{
Jeff Johnson295189b2012-06-20 16:38:30 -07006958 v_BOOL_t itemIsValid = VOS_FALSE;
6959 VOS_STATUS status;
6960 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6961 v_U8_t macLoop;
6962
6963 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6964 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6965 if(status != VOS_STATUS_SUCCESS)
6966 {
6967 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6968 return VOS_STATUS_E_FAILURE;
6969 }
6970
6971 if (itemIsValid == VOS_TRUE)
6972 {
6973 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6974 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6975 VOS_MAX_CONCURRENCY_PERSONA);
6976 if(status != VOS_STATUS_SUCCESS)
6977 {
6978 /* Get MAC from NV fail, not update CFG info
6979 * INI MAC value will be used for MAC setting */
6980 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6981 return VOS_STATUS_E_FAILURE;
6982 }
6983
6984 /* If first MAC is not valid, treat all others are not valid
6985 * Then all MACs will be got from ini file */
6986 if(vos_is_macaddr_zero(&macFromNV[0]))
6987 {
6988 /* MAC address in NV file is not configured yet */
6989 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6990 return VOS_STATUS_E_INVAL;
6991 }
6992
6993 /* Get MAC address from NV, update CFG info */
6994 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6995 {
6996 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6997 {
6998 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6999 /* This MAC is not valid, skip it
7000 * This MAC will be got from ini file */
7001 }
7002 else
7003 {
7004 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7005 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7006 VOS_MAC_ADDR_SIZE);
7007 }
7008 }
7009 }
7010 else
7011 {
7012 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7013 return VOS_STATUS_E_FAILURE;
7014 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007015
Jeff Johnson295189b2012-06-20 16:38:30 -07007016
7017 return VOS_STATUS_SUCCESS;
7018}
7019
7020/**---------------------------------------------------------------------------
7021
7022 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7023
7024 \param - pAdapter - Pointer to the HDD
7025
7026 \return - None
7027
7028 --------------------------------------------------------------------------*/
7029VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7030{
7031 eHalStatus halStatus;
7032 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307033 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007034
Jeff Johnson295189b2012-06-20 16:38:30 -07007035
7036 // Send ready indication to the HDD. This will kick off the MAC
7037 // into a 'running' state and should kick off an initial scan.
7038 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7039 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7040 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307041 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007042 "code %08d [x%08x]",__func__, halStatus, halStatus );
7043 return VOS_STATUS_E_FAILURE;
7044 }
7045
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307046 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007047 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7048 // And RIVA will crash
7049 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7050 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307051 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7052 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7053
7054
Jeff Johnson295189b2012-06-20 16:38:30 -07007055 return VOS_STATUS_SUCCESS;
7056}
7057
Jeff Johnson295189b2012-06-20 16:38:30 -07007058/* wake lock APIs for HDD */
7059void hdd_prevent_suspend(void)
7060{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007061#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007062 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007063#else
7064 wcnss_prevent_suspend();
7065#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007066}
7067
7068void hdd_allow_suspend(void)
7069{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007070#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007071 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007072#else
7073 wcnss_allow_suspend();
7074#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007075}
7076
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007077void hdd_allow_suspend_timeout(v_U32_t timeout)
7078{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007079#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007080 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007081#else
7082 /* Do nothing as there is no API in wcnss for timeout*/
7083#endif
7084}
7085
Jeff Johnson295189b2012-06-20 16:38:30 -07007086/**---------------------------------------------------------------------------
7087
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007088 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7089 information between Host and Riva
7090
7091 This function gets reported version of FW
7092 It also finds the version of Riva headers used to compile the host
7093 It compares the above two and prints a warning if they are different
7094 It gets the SW and HW version string
7095 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7096 indicating the features they support through a bitmap
7097
7098 \param - pHddCtx - Pointer to HDD context
7099
7100 \return - void
7101
7102 --------------------------------------------------------------------------*/
7103
7104void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7105{
7106
7107 tSirVersionType versionCompiled;
7108 tSirVersionType versionReported;
7109 tSirVersionString versionString;
7110 tANI_U8 fwFeatCapsMsgSupported = 0;
7111 VOS_STATUS vstatus;
7112
7113 /* retrieve and display WCNSS version information */
7114 do {
7115
7116 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7117 &versionCompiled);
7118 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7119 {
7120 hddLog(VOS_TRACE_LEVEL_FATAL,
7121 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007122 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007123 break;
7124 }
7125
7126 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7127 &versionReported);
7128 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7129 {
7130 hddLog(VOS_TRACE_LEVEL_FATAL,
7131 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007132 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007133 break;
7134 }
7135
7136 if ((versionCompiled.major != versionReported.major) ||
7137 (versionCompiled.minor != versionReported.minor) ||
7138 (versionCompiled.version != versionReported.version) ||
7139 (versionCompiled.revision != versionReported.revision))
7140 {
7141 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7142 "Host expected %u.%u.%u.%u\n",
7143 WLAN_MODULE_NAME,
7144 (int)versionReported.major,
7145 (int)versionReported.minor,
7146 (int)versionReported.version,
7147 (int)versionReported.revision,
7148 (int)versionCompiled.major,
7149 (int)versionCompiled.minor,
7150 (int)versionCompiled.version,
7151 (int)versionCompiled.revision);
7152 }
7153 else
7154 {
7155 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7156 WLAN_MODULE_NAME,
7157 (int)versionReported.major,
7158 (int)versionReported.minor,
7159 (int)versionReported.version,
7160 (int)versionReported.revision);
7161 }
7162
7163 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7164 versionString,
7165 sizeof(versionString));
7166 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7167 {
7168 hddLog(VOS_TRACE_LEVEL_FATAL,
7169 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007170 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007171 break;
7172 }
7173
7174 pr_info("%s: WCNSS software version %s\n",
7175 WLAN_MODULE_NAME, versionString);
7176
7177 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7178 versionString,
7179 sizeof(versionString));
7180 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7181 {
7182 hddLog(VOS_TRACE_LEVEL_FATAL,
7183 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007184 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007185 break;
7186 }
7187
7188 pr_info("%s: WCNSS hardware version %s\n",
7189 WLAN_MODULE_NAME, versionString);
7190
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007191 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7192 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007193 send the message only if it the riva is 1.1
7194 minor numbers for different riva branches:
7195 0 -> (1.0)Mainline Build
7196 1 -> (1.1)Mainline Build
7197 2->(1.04) Stability Build
7198 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007199 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007200 ((versionReported.minor>=1) && (versionReported.version>=1)))
7201 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7202 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007203
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007204 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007205 {
7206#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7207 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7208 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7209#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007210 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7211 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7212 {
7213 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7214 }
7215
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007216 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007217 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007218
7219 } while (0);
7220
7221}
7222
7223/**---------------------------------------------------------------------------
7224
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307225 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7226
7227 \param - pHddCtx - Pointer to the hdd context
7228
7229 \return - true if hardware supports 5GHz
7230
7231 --------------------------------------------------------------------------*/
7232static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7233{
7234 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7235 * then hardware support 5Ghz.
7236 */
7237 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7238 {
7239 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7240 return true;
7241 }
7242 else
7243 {
7244 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7245 __func__);
7246 return false;
7247 }
7248}
7249
7250
7251/**---------------------------------------------------------------------------
7252
Jeff Johnson295189b2012-06-20 16:38:30 -07007253 \brief hdd_wlan_startup() - HDD init function
7254
7255 This is the driver startup code executed once a WLAN device has been detected
7256
7257 \param - dev - Pointer to the underlying device
7258
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007259 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007260
7261 --------------------------------------------------------------------------*/
7262
7263int hdd_wlan_startup(struct device *dev )
7264{
7265 VOS_STATUS status;
7266 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007267 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 hdd_context_t *pHddCtx = NULL;
7269 v_CONTEXT_t pVosContext= NULL;
7270#ifdef WLAN_BTAMP_FEATURE
7271 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7272 WLANBAP_ConfigType btAmpConfig;
7273 hdd_config_t *pConfig;
7274#endif
7275 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007276 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007277
7278 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007279 /*
7280 * cfg80211: wiphy allocation
7281 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307282 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007283
7284 if(wiphy == NULL)
7285 {
7286 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007287 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007288 }
7289
7290 pHddCtx = wiphy_priv(wiphy);
7291
Jeff Johnson295189b2012-06-20 16:38:30 -07007292 //Initialize the adapter context to zeros.
7293 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7294
Jeff Johnson295189b2012-06-20 16:38:30 -07007295 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007296 hdd_prevent_suspend();
7297 pHddCtx->isLoadUnloadInProgress = TRUE;
7298
7299 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7300
7301 /*Get vos context here bcoz vos_open requires it*/
7302 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7303
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007304 if(pVosContext == NULL)
7305 {
7306 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7307 goto err_free_hdd_context;
7308 }
7309
Jeff Johnson295189b2012-06-20 16:38:30 -07007310 //Save the Global VOSS context in adapter context for future.
7311 pHddCtx->pvosContext = pVosContext;
7312
7313 //Save the adapter context in global context for future.
7314 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7315
Jeff Johnson295189b2012-06-20 16:38:30 -07007316 pHddCtx->parent_dev = dev;
7317
7318 init_completion(&pHddCtx->full_pwr_comp_var);
7319 init_completion(&pHddCtx->standby_comp_var);
7320 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007321 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007322 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307323 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007324
7325#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007326 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007327#else
7328 init_completion(&pHddCtx->driver_crda_req);
7329#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007330
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307331 spin_lock_init(&pHddCtx->schedScan_lock);
7332
Jeff Johnson295189b2012-06-20 16:38:30 -07007333 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7334
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307335#ifdef FEATURE_WLAN_TDLS
7336 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7337 * invoked by other instances also) to protect the concurrent
7338 * access for the Adapters by TDLS module.
7339 */
7340 mutex_init(&pHddCtx->tdls_lock);
7341#endif
7342
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307343 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007344 // Load all config first as TL config is needed during vos_open
7345 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7346 if(pHddCtx->cfg_ini == NULL)
7347 {
7348 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7349 goto err_free_hdd_context;
7350 }
7351
7352 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7353
7354 // Read and parse the qcom_cfg.ini file
7355 status = hdd_parse_config_ini( pHddCtx );
7356 if ( VOS_STATUS_SUCCESS != status )
7357 {
7358 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7359 __func__, WLAN_INI_FILE);
7360 goto err_config;
7361 }
7362
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307363 /* INI has been read, initialise the configuredMcastBcastFilter with
7364 * INI value as this will serve as the default value
7365 */
7366 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7367 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7368 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307369
7370 if (false == hdd_is_5g_supported(pHddCtx))
7371 {
7372 //5Ghz is not supported.
7373 if (1 != pHddCtx->cfg_ini->nBandCapability)
7374 {
7375 hddLog(VOS_TRACE_LEVEL_INFO,
7376 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7377 pHddCtx->cfg_ini->nBandCapability = 1;
7378 }
7379 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307380
7381 /* If SNR Monitoring is enabled, FW has to parse all beacons
7382 * for calcaluting and storing the average SNR, so set Nth beacon
7383 * filter to 1 to enable FW to parse all the beaocons
7384 */
7385 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7386 {
7387 /* The log level is deliberately set to WARN as overriding
7388 * nthBeaconFilter to 1 will increase power cosumption and this
7389 * might just prove helpful to detect the power issue.
7390 */
7391 hddLog(VOS_TRACE_LEVEL_WARN,
7392 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7393 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007395 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307396 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007397 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307398 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007399 {
7400 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307401 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7402 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007403 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007404
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007405 // Update VOS trace levels based upon the cfg.ini
7406 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7407 pHddCtx->cfg_ini->vosTraceEnableBAP);
7408 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7409 pHddCtx->cfg_ini->vosTraceEnableTL);
7410 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7411 pHddCtx->cfg_ini->vosTraceEnableWDI);
7412 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7413 pHddCtx->cfg_ini->vosTraceEnableHDD);
7414 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7415 pHddCtx->cfg_ini->vosTraceEnableSME);
7416 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7417 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307418 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7419 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007420 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7421 pHddCtx->cfg_ini->vosTraceEnableWDA);
7422 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7423 pHddCtx->cfg_ini->vosTraceEnableSYS);
7424 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7425 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007426 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7427 pHddCtx->cfg_ini->vosTraceEnableSAP);
7428 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7429 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007430
Jeff Johnson295189b2012-06-20 16:38:30 -07007431 // Update WDI trace levels based upon the cfg.ini
7432 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7433 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7434 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7435 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7436 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7437 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7438 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7439 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007440
Jeff Johnson88ba7742013-02-27 14:36:02 -08007441 if (VOS_FTM_MODE == hdd_get_conparam())
7442 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007443 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7444 {
7445 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7446 goto err_free_hdd_context;
7447 }
7448 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7449 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007450 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007451
Jeff Johnson88ba7742013-02-27 14:36:02 -08007452 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007453 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7454 {
7455 status = vos_watchdog_open(pVosContext,
7456 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7457
7458 if(!VOS_IS_STATUS_SUCCESS( status ))
7459 {
7460 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307461 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 }
7463 }
7464
7465 pHddCtx->isLogpInProgress = FALSE;
7466 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7467
Jeff Johnson295189b2012-06-20 16:38:30 -07007468 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7469 if(!VOS_IS_STATUS_SUCCESS(status))
7470 {
7471 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007472 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007473 }
7474
Amar Singhala49cbc52013-10-08 18:37:44 -07007475#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007476 /* initialize the NV module. This is required so that
7477 we can initialize the channel information in wiphy
7478 from the NV.bin data. The channel information in
7479 wiphy needs to be initialized before wiphy registration */
7480
7481 status = vos_nv_open();
7482 if (!VOS_IS_STATUS_SUCCESS(status))
7483 {
7484 /* NV module cannot be initialized */
7485 hddLog( VOS_TRACE_LEVEL_FATAL,
7486 "%s: vos_nv_open failed", __func__);
7487 goto err_clkvote;
7488 }
7489
7490 status = vos_init_wiphy_from_nv_bin();
7491 if (!VOS_IS_STATUS_SUCCESS(status))
7492 {
7493 /* NV module cannot be initialized */
7494 hddLog( VOS_TRACE_LEVEL_FATAL,
7495 "%s: vos_init_wiphy failed", __func__);
7496 goto err_vos_nv_close;
7497 }
7498
Amar Singhala49cbc52013-10-08 18:37:44 -07007499 /* registration of wiphy dev with cfg80211 */
7500 if (0 > wlan_hdd_cfg80211_register(wiphy))
7501 {
7502 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007503 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007504 }
7505#endif
7506
Jeff Johnson295189b2012-06-20 16:38:30 -07007507 status = vos_open( &pVosContext, 0);
7508 if ( !VOS_IS_STATUS_SUCCESS( status ))
7509 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007510 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007511 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007512 }
7513
Jeff Johnson295189b2012-06-20 16:38:30 -07007514 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7515
7516 if ( NULL == pHddCtx->hHal )
7517 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007519 goto err_vosclose;
7520 }
7521
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007522 status = vos_preStart( pHddCtx->pvosContext );
7523 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7524 {
7525 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7526 goto err_vosclose;
7527 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007528
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007529 /* Note that the vos_preStart() sequence triggers the cfg download.
7530 The cfg download must occur before we update the SME config
7531 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007532 status = hdd_set_sme_config( pHddCtx );
7533
7534 if ( VOS_STATUS_SUCCESS != status )
7535 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007536 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7537 goto err_vosclose;
7538 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007539
7540 //Initialize the WMM module
7541 status = hdd_wmm_init(pHddCtx);
7542 if (!VOS_IS_STATUS_SUCCESS(status))
7543 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007544 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007545 goto err_vosclose;
7546 }
7547
Jeff Johnson295189b2012-06-20 16:38:30 -07007548 /* In the integrated architecture we update the configuration from
7549 the INI file and from NV before vOSS has been started so that
7550 the final contents are available to send down to the cCPU */
7551
7552 // Apply the cfg.ini to cfg.dat
7553 if (FALSE == hdd_update_config_dat(pHddCtx))
7554 {
7555 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7556 goto err_vosclose;
7557 }
7558
7559 // Apply the NV to cfg.dat
7560 /* Prima Update MAC address only at here */
7561 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7562 {
7563#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7564 /* There was not a valid set of MAC Addresses in NV. See if the
7565 default addresses were modified by the cfg.ini settings. If so,
7566 we'll use them, but if not, we'll autogenerate a set of MAC
7567 addresses based upon the device serial number */
7568
7569 static const v_MACADDR_t default_address =
7570 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7571 unsigned int serialno;
7572 int i;
7573
7574 serialno = wcnss_get_serial_number();
7575 if ((0 != serialno) &&
7576 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7577 sizeof(default_address))))
7578 {
7579 /* cfg.ini has the default address, invoke autogen logic */
7580
7581 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7582 bytes of the serial number that can be used to generate
7583 the other 3 bytes of the MAC address. Mask off all but
7584 the lower 3 bytes (this will also make sure we don't
7585 overflow in the next step) */
7586 serialno &= 0x00FFFFFF;
7587
7588 /* we need a unique address for each session */
7589 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7590
7591 /* autogen all addresses */
7592 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7593 {
7594 /* start with the entire default address */
7595 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7596 /* then replace the lower 3 bytes */
7597 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7598 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7599 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7600
7601 serialno++;
7602 }
7603
7604 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7605 MAC_ADDRESS_STR,
7606 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7607 }
7608 else
7609#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7610 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007611 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007612 "%s: Invalid MAC address in NV, using MAC from ini file "
7613 MAC_ADDRESS_STR, __func__,
7614 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7615 }
7616 }
7617 {
7618 eHalStatus halStatus;
7619 // Set the MAC Address
7620 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7621 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7622 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7623 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7624
7625 if (!HAL_STATUS_SUCCESS( halStatus ))
7626 {
7627 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7628 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007629 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 }
7631 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007632
7633 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7634 Note: Firmware image will be read and downloaded inside vos_start API */
7635 status = vos_start( pHddCtx->pvosContext );
7636 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7637 {
7638 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7639 goto err_vosclose;
7640 }
7641
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007642 /* Exchange capability info between Host and FW and also get versioning info from FW */
7643 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007644
7645 status = hdd_post_voss_start_config( pHddCtx );
7646 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7647 {
7648 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7649 __func__);
7650 goto err_vosstop;
7651 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007652
7653#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307654 wlan_hdd_cfg80211_update_reg_info( wiphy );
7655
7656 /* registration of wiphy dev with cfg80211 */
7657 if (0 > wlan_hdd_cfg80211_register(wiphy))
7658 {
7659 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7660 goto err_vosstop;
7661 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007662#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007663
Jeff Johnson295189b2012-06-20 16:38:30 -07007664 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7665 {
7666 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7667 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7668 }
7669 else
7670 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007671 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7672 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7673 if (pAdapter != NULL)
7674 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307675 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307677 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7678 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7679 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007680
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307681 /* Generate the P2P Device Address. This consists of the device's
7682 * primary MAC address with the locally administered bit set.
7683 */
7684 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007685 }
7686 else
7687 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307688 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7689 if (p2p_dev_addr != NULL)
7690 {
7691 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7692 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7693 }
7694 else
7695 {
7696 hddLog(VOS_TRACE_LEVEL_FATAL,
7697 "%s: Failed to allocate mac_address for p2p_device",
7698 __func__);
7699 goto err_close_adapter;
7700 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007702
7703 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7704 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7705 if ( NULL == pP2pAdapter )
7706 {
7707 hddLog(VOS_TRACE_LEVEL_FATAL,
7708 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007709 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007710 goto err_close_adapter;
7711 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007713 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007714
7715 if( pAdapter == NULL )
7716 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007717 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7718 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007719 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007720
Jeff Johnson295189b2012-06-20 16:38:30 -07007721#ifdef WLAN_BTAMP_FEATURE
7722 vStatus = WLANBAP_Open(pVosContext);
7723 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7724 {
7725 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7726 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007727 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007728 }
7729
7730 vStatus = BSL_Init(pVosContext);
7731 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7732 {
7733 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7734 "%s: Failed to Init BSL",__func__);
7735 goto err_bap_close;
7736 }
7737 vStatus = WLANBAP_Start(pVosContext);
7738 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7739 {
7740 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7741 "%s: Failed to start TL",__func__);
7742 goto err_bap_close;
7743 }
7744
7745 pConfig = pHddCtx->cfg_ini;
7746 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7747 status = WLANBAP_SetConfig(&btAmpConfig);
7748
7749#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007750
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007751#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7752 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7753 {
7754 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7755 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7756 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7757 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7758 }
7759#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007760#ifdef FEATURE_WLAN_SCAN_PNO
7761 /*SME must send channel update configuration to RIVA*/
7762 sme_UpdateChannelConfig(pHddCtx->hHal);
7763#endif
7764
Jeff Johnson295189b2012-06-20 16:38:30 -07007765 /* Register with platform driver as client for Suspend/Resume */
7766 status = hddRegisterPmOps(pHddCtx);
7767 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7768 {
7769 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7770#ifdef WLAN_BTAMP_FEATURE
7771 goto err_bap_stop;
7772#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007773 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007774#endif //WLAN_BTAMP_FEATURE
7775 }
7776
Yue Ma0d4891e2013-08-06 17:01:45 -07007777 /* Open debugfs interface */
7778 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7779 {
7780 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7781 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007782 }
7783
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 /* Register TM level change handler function to the platform */
7785 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7786 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7787 {
7788 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7789 goto err_unregister_pmops;
7790 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007791
7792 /* register for riva power on lock to platform driver */
7793 if (req_riva_power_on_lock("wlan"))
7794 {
7795 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7796 __func__);
7797 goto err_unregister_pmops;
7798 }
7799
Jeff Johnson295189b2012-06-20 16:38:30 -07007800 // register net device notifier for device change notification
7801 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7802
7803 if(ret < 0)
7804 {
7805 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7806 goto err_free_power_on_lock;
7807 }
7808
7809 //Initialize the nlink service
7810 if(nl_srv_init() != 0)
7811 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307812 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007813 goto err_reg_netdev;
7814 }
7815
Leo Chang4ce1cc52013-10-21 18:27:15 -07007816#ifdef WLAN_KD_READY_NOTIFIER
7817 pHddCtx->kd_nl_init = 1;
7818#endif /* WLAN_KD_READY_NOTIFIER */
7819
Jeff Johnson295189b2012-06-20 16:38:30 -07007820 //Initialize the BTC service
7821 if(btc_activate_service(pHddCtx) != 0)
7822 {
7823 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7824 goto err_nl_srv;
7825 }
7826
7827#ifdef PTT_SOCK_SVC_ENABLE
7828 //Initialize the PTT service
7829 if(ptt_sock_activate_svc(pHddCtx) != 0)
7830 {
7831 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7832 goto err_nl_srv;
7833 }
7834#endif
7835
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007837 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007839 /* Action frame registered in one adapter which will
7840 * applicable to all interfaces
7841 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007842 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007843 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007844
7845 mutex_init(&pHddCtx->sap_lock);
7846
7847 pHddCtx->isLoadUnloadInProgress = FALSE;
7848
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007849#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007850#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7851 /* Initialize the wake lcok */
7852 wake_lock_init(&pHddCtx->rx_wake_lock,
7853 WAKE_LOCK_SUSPEND,
7854 "qcom_rx_wakelock");
7855#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007856 /* Initialize the wake lcok */
7857 wake_lock_init(&pHddCtx->sap_wake_lock,
7858 WAKE_LOCK_SUSPEND,
7859 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007860#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007861
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007862 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7863 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007864
7865 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7866 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307867
Jeff Johnsone7245742012-09-05 17:12:55 -07007868 // Initialize the restart logic
7869 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307870
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007871 //Register the traffic monitor timer now
7872 if ( pHddCtx->cfg_ini->dynSplitscan)
7873 {
7874 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7875 VOS_TIMER_TYPE_SW,
7876 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7877 (void *)pHddCtx);
7878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007879 goto success;
7880
7881err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007882#ifdef WLAN_KD_READY_NOTIFIER
7883 nl_srv_exit(pHddCtx->ptt_pid);
7884#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007885 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007886#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007887err_reg_netdev:
7888 unregister_netdevice_notifier(&hdd_netdev_notifier);
7889
7890err_free_power_on_lock:
7891 free_riva_power_on_lock("wlan");
7892
7893err_unregister_pmops:
7894 hddDevTmUnregisterNotifyCallback(pHddCtx);
7895 hddDeregisterPmOps(pHddCtx);
7896
Yue Ma0d4891e2013-08-06 17:01:45 -07007897 hdd_debugfs_exit(pHddCtx);
7898
Jeff Johnson295189b2012-06-20 16:38:30 -07007899#ifdef WLAN_BTAMP_FEATURE
7900err_bap_stop:
7901 WLANBAP_Stop(pVosContext);
7902#endif
7903
7904#ifdef WLAN_BTAMP_FEATURE
7905err_bap_close:
7906 WLANBAP_Close(pVosContext);
7907#endif
7908
Jeff Johnson295189b2012-06-20 16:38:30 -07007909err_close_adapter:
7910 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007911
7912#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307913 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007914#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007915
7916err_vosstop:
7917 vos_stop(pVosContext);
7918
Amar Singhala49cbc52013-10-08 18:37:44 -07007919err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007920 status = vos_sched_close( pVosContext );
7921 if (!VOS_IS_STATUS_SUCCESS(status)) {
7922 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7923 "%s: Failed to close VOSS Scheduler", __func__);
7924 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7925 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007926 vos_close(pVosContext );
7927
7928err_wiphy_unregister:
7929
7930#ifdef CONFIG_ENABLE_LINUX_REG
7931 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007932
Amar Singhal0a402232013-10-11 20:57:16 -07007933err_vos_nv_close:
7934
7935 vos_nv_close();
7936
Jeff Johnson295189b2012-06-20 16:38:30 -07007937err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007938#endif
7939
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007940 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007941
7942err_wdclose:
7943 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7944 vos_watchdog_close(pVosContext);
7945
Jeff Johnson295189b2012-06-20 16:38:30 -07007946err_config:
7947 kfree(pHddCtx->cfg_ini);
7948 pHddCtx->cfg_ini= NULL;
7949
7950err_free_hdd_context:
7951 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007952 wiphy_free(wiphy) ;
7953 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007954 VOS_BUG(1);
7955
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007956 if (hdd_is_ssr_required())
7957 {
7958 /* WDI timeout had happened during load, so SSR is needed here */
7959 subsystem_restart("wcnss");
7960 msleep(5000);
7961 }
7962 hdd_set_ssr_required (VOS_FALSE);
7963
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007964 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007965
7966success:
7967 EXIT();
7968 return 0;
7969}
7970
7971/**---------------------------------------------------------------------------
7972
Jeff Johnson32d95a32012-09-10 13:15:23 -07007973 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007974
Jeff Johnson32d95a32012-09-10 13:15:23 -07007975 This is the driver entry point - called in different timeline depending
7976 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007977
7978 \param - None
7979
7980 \return - 0 for success, non zero for failure
7981
7982 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007983static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007984{
7985 VOS_STATUS status;
7986 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007987 struct device *dev = NULL;
7988 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007989#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7990 int max_retries = 0;
7991#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007992
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307993#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7994 vos_wconn_trace_init();
7995#endif
7996
Jeff Johnson295189b2012-06-20 16:38:30 -07007997 ENTER();
7998
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007999#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008000 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008001#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008002
8003 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8004 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8005
8006 //Power Up Libra WLAN card first if not already powered up
8007 status = vos_chipPowerUp(NULL,NULL,NULL);
8008 if (!VOS_IS_STATUS_SUCCESS(status))
8009 {
8010 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8011 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308012#ifdef WLAN_OPEN_SOURCE
8013 wake_lock_destroy(&wlan_wake_lock);
8014#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008015 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 }
8017
Jeff Johnson295189b2012-06-20 16:38:30 -07008018#ifdef ANI_BUS_TYPE_PCI
8019
8020 dev = wcnss_wlan_get_device();
8021
8022#endif // ANI_BUS_TYPE_PCI
8023
8024#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008025
8026#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8027 /* wait until WCNSS driver downloads NV */
8028 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8029 msleep(1000);
8030 }
8031 if (max_retries >= 5) {
8032 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308033#ifdef WLAN_OPEN_SOURCE
8034 wake_lock_destroy(&wlan_wake_lock);
8035#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008036 return -ENODEV;
8037 }
8038#endif
8039
Jeff Johnson295189b2012-06-20 16:38:30 -07008040 dev = wcnss_wlan_get_device();
8041#endif // ANI_BUS_TYPE_PLATFORM
8042
8043
8044 do {
8045 if (NULL == dev) {
8046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8047 ret_status = -1;
8048 break;
8049 }
8050
8051#ifdef MEMORY_DEBUG
8052 vos_mem_init();
8053#endif
8054
8055#ifdef TIMER_MANAGER
8056 vos_timer_manager_init();
8057#endif
8058
8059 /* Preopen VOSS so that it is ready to start at least SAL */
8060 status = vos_preOpen(&pVosContext);
8061
8062 if (!VOS_IS_STATUS_SUCCESS(status))
8063 {
8064 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8065 ret_status = -1;
8066 break;
8067 }
8068
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008069#ifndef MODULE
8070 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8071 */
8072 hdd_set_conparam((v_UINT_t)con_mode);
8073#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008074
8075 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008076 if (hdd_wlan_startup(dev))
8077 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008078 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008079 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008080 vos_preClose( &pVosContext );
8081 ret_status = -1;
8082 break;
8083 }
8084
8085 /* Cancel the vote for XO Core ON
8086 * This is done here for safety purposes in case we re-initialize without turning
8087 * it OFF in any error scenario.
8088 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008089 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008090 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008091 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008092 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8093 {
8094 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8095 " Power consumed will be high\n");
8096 }
8097 } while (0);
8098
8099 if (0 != ret_status)
8100 {
8101 //Assert Deep sleep signal now to put Libra HW in lowest power state
8102 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8103 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8104
8105 //Vote off any PMIC voltage supplies
8106 vos_chipPowerDown(NULL, NULL, NULL);
8107#ifdef TIMER_MANAGER
8108 vos_timer_exit();
8109#endif
8110#ifdef MEMORY_DEBUG
8111 vos_mem_exit();
8112#endif
8113
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008114#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008115 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008116#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8118 }
8119 else
8120 {
8121 //Send WLAN UP indication to Nlink Service
8122 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8123
8124 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008125 }
8126
8127 EXIT();
8128
8129 return ret_status;
8130}
8131
Jeff Johnson32d95a32012-09-10 13:15:23 -07008132/**---------------------------------------------------------------------------
8133
8134 \brief hdd_module_init() - Init Function
8135
8136 This is the driver entry point (invoked when module is loaded using insmod)
8137
8138 \param - None
8139
8140 \return - 0 for success, non zero for failure
8141
8142 --------------------------------------------------------------------------*/
8143#ifdef MODULE
8144static int __init hdd_module_init ( void)
8145{
8146 return hdd_driver_init();
8147}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008148#else /* #ifdef MODULE */
8149static int __init hdd_module_init ( void)
8150{
8151 /* Driver initialization is delayed to fwpath_changed_handler */
8152 return 0;
8153}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008154#endif /* #ifdef MODULE */
8155
Jeff Johnson295189b2012-06-20 16:38:30 -07008156
8157/**---------------------------------------------------------------------------
8158
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008159 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008160
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008161 This is the driver exit point (invoked when module is unloaded using rmmod
8162 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008163
8164 \param - None
8165
8166 \return - None
8167
8168 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008169static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008170{
8171 hdd_context_t *pHddCtx = NULL;
8172 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008173 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008174
8175 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8176
8177 //Get the global vos context
8178 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8179
8180 if(!pVosContext)
8181 {
8182 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8183 goto done;
8184 }
8185
8186 //Get the HDD context.
8187 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8188
8189 if(!pHddCtx)
8190 {
8191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8192 }
8193 else
8194 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008195 while(isWDresetInProgress()) {
8196 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8197 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008198 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008199
8200 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8202 "%s:SSR never completed, fatal error", __func__);
8203 VOS_BUG(0);
8204 }
8205 }
8206
Jeff Johnson295189b2012-06-20 16:38:30 -07008207
8208 pHddCtx->isLoadUnloadInProgress = TRUE;
8209 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8210
8211 //Do all the cleanup before deregistering the driver
8212 hdd_wlan_exit(pHddCtx);
8213 }
8214
Jeff Johnson295189b2012-06-20 16:38:30 -07008215 vos_preClose( &pVosContext );
8216
8217#ifdef TIMER_MANAGER
8218 vos_timer_exit();
8219#endif
8220#ifdef MEMORY_DEBUG
8221 vos_mem_exit();
8222#endif
8223
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308224#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8225 vos_wconn_trace_exit();
8226#endif
8227
Jeff Johnson295189b2012-06-20 16:38:30 -07008228done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008229#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008230 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008231#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008232 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8233}
8234
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008235/**---------------------------------------------------------------------------
8236
8237 \brief hdd_module_exit() - Exit function
8238
8239 This is the driver exit point (invoked when module is unloaded using rmmod)
8240
8241 \param - None
8242
8243 \return - None
8244
8245 --------------------------------------------------------------------------*/
8246static void __exit hdd_module_exit(void)
8247{
8248 hdd_driver_exit();
8249}
8250
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008251#ifdef MODULE
8252static int fwpath_changed_handler(const char *kmessage,
8253 struct kernel_param *kp)
8254{
Jeff Johnson76052702013-04-16 13:55:05 -07008255 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008256}
8257
8258static int con_mode_handler(const char *kmessage,
8259 struct kernel_param *kp)
8260{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008261 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008262}
8263#else /* #ifdef MODULE */
8264/**---------------------------------------------------------------------------
8265
Jeff Johnson76052702013-04-16 13:55:05 -07008266 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008267
Jeff Johnson76052702013-04-16 13:55:05 -07008268 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008269 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008270 - invoked when module parameter fwpath is modified from userspace to signal
8271 initializing the WLAN driver or when con_mode is modified from userspace
8272 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008273
8274 \return - 0 for success, non zero for failure
8275
8276 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008277static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008278{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008279 int ret_status;
8280
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008281 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008282 ret_status = hdd_driver_init();
8283 wlan_hdd_inited = ret_status ? 0 : 1;
8284 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008285 }
8286
8287 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008288
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008289 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008290
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008291 ret_status = hdd_driver_init();
8292 wlan_hdd_inited = ret_status ? 0 : 1;
8293 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008294}
8295
Jeff Johnson295189b2012-06-20 16:38:30 -07008296/**---------------------------------------------------------------------------
8297
Jeff Johnson76052702013-04-16 13:55:05 -07008298 \brief fwpath_changed_handler() - Handler Function
8299
8300 Handle changes to the fwpath parameter
8301
8302 \return - 0 for success, non zero for failure
8303
8304 --------------------------------------------------------------------------*/
8305static int fwpath_changed_handler(const char *kmessage,
8306 struct kernel_param *kp)
8307{
8308 int ret;
8309
8310 ret = param_set_copystring(kmessage, kp);
8311 if (0 == ret)
8312 ret = kickstart_driver();
8313 return ret;
8314}
8315
8316/**---------------------------------------------------------------------------
8317
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008318 \brief con_mode_handler() -
8319
8320 Handler function for module param con_mode when it is changed by userspace
8321 Dynamically linked - do nothing
8322 Statically linked - exit and init driver, as in rmmod and insmod
8323
Jeff Johnson76052702013-04-16 13:55:05 -07008324 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008325
Jeff Johnson76052702013-04-16 13:55:05 -07008326 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008327
8328 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008329static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008330{
Jeff Johnson76052702013-04-16 13:55:05 -07008331 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008332
Jeff Johnson76052702013-04-16 13:55:05 -07008333 ret = param_set_int(kmessage, kp);
8334 if (0 == ret)
8335 ret = kickstart_driver();
8336 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008337}
8338#endif /* #ifdef MODULE */
8339
8340/**---------------------------------------------------------------------------
8341
Jeff Johnson295189b2012-06-20 16:38:30 -07008342 \brief hdd_get_conparam() -
8343
8344 This is the driver exit point (invoked when module is unloaded using rmmod)
8345
8346 \param - None
8347
8348 \return - tVOS_CON_MODE
8349
8350 --------------------------------------------------------------------------*/
8351tVOS_CON_MODE hdd_get_conparam ( void )
8352{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008353#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008354 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008355#else
8356 return (tVOS_CON_MODE)curr_con_mode;
8357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008358}
8359void hdd_set_conparam ( v_UINT_t newParam )
8360{
8361 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008362#ifndef MODULE
8363 curr_con_mode = con_mode;
8364#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008365}
8366/**---------------------------------------------------------------------------
8367
8368 \brief hdd_softap_sta_deauth() - function
8369
8370 This to take counter measure to handle deauth req from HDD
8371
8372 \param - pAdapter - Pointer to the HDD
8373
8374 \param - enable - boolean value
8375
8376 \return - None
8377
8378 --------------------------------------------------------------------------*/
8379
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008380VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008381{
Jeff Johnson295189b2012-06-20 16:38:30 -07008382 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008383 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008384
8385 ENTER();
8386
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008387 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8388 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008389
8390 //Ignore request to deauth bcmc station
8391 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008392 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008393
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008394 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008395
8396 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008397 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008398}
8399
8400/**---------------------------------------------------------------------------
8401
8402 \brief hdd_softap_sta_disassoc() - function
8403
8404 This to take counter measure to handle deauth req from HDD
8405
8406 \param - pAdapter - Pointer to the HDD
8407
8408 \param - enable - boolean value
8409
8410 \return - None
8411
8412 --------------------------------------------------------------------------*/
8413
8414void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8415{
8416 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8417
8418 ENTER();
8419
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308420 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008421
8422 //Ignore request to disassoc bcmc station
8423 if( pDestMacAddress[0] & 0x1 )
8424 return;
8425
8426 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8427}
8428
8429void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8430{
8431 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8432
8433 ENTER();
8434
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308435 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008436
8437 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8438}
8439
Jeff Johnson295189b2012-06-20 16:38:30 -07008440/**---------------------------------------------------------------------------
8441 *
8442 * \brief hdd_get__concurrency_mode() -
8443 *
8444 *
8445 * \param - None
8446 *
8447 * \return - CONCURRENCY MODE
8448 *
8449 * --------------------------------------------------------------------------*/
8450tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8451{
8452 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8453 hdd_context_t *pHddCtx;
8454
8455 if (NULL != pVosContext)
8456 {
8457 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8458 if (NULL != pHddCtx)
8459 {
8460 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8461 }
8462 }
8463
8464 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008465 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 return VOS_STA;
8467}
8468
8469/* Decide whether to allow/not the apps power collapse.
8470 * Allow apps power collapse if we are in connected state.
8471 * if not, allow only if we are in IMPS */
8472v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8473{
8474 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008475 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008476 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008477 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8478 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8479 hdd_adapter_t *pAdapter = NULL;
8480 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008481 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008482
Jeff Johnson295189b2012-06-20 16:38:30 -07008483 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8484 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008485
Yathish9f22e662012-12-10 14:21:35 -08008486 concurrent_state = hdd_get_concurrency_mode();
8487
8488#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8489 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8490 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8491 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8492 return TRUE;
8493#endif
8494
Jeff Johnson295189b2012-06-20 16:38:30 -07008495 /*loop through all adapters. TBD fix for Concurrency */
8496 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8497 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8498 {
8499 pAdapter = pAdapterNode->pAdapter;
8500 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8501 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8502 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008503 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008504 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008505 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008506 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8507 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008508 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008509 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008510 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8511 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008512 return FALSE;
8513 }
8514 }
8515 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8516 pAdapterNode = pNext;
8517 }
8518 return TRUE;
8519}
8520
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008521/* Decides whether to send suspend notification to Riva
8522 * if any adapter is in BMPS; then it is required */
8523v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8524{
8525 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8526 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8527
8528 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8529 {
8530 return TRUE;
8531 }
8532 return FALSE;
8533}
8534
Jeff Johnson295189b2012-06-20 16:38:30 -07008535void wlan_hdd_set_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 Johnsone7245742012-09-05 17:12:55 -07008543 pHddCtx->concurrency_mode |= (1 << mode);
8544 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008545 break;
8546 default:
8547 break;
8548
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
8554
8555void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8556{
8557 switch(mode)
8558 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008559 case VOS_STA_MODE:
8560 case VOS_P2P_CLIENT_MODE:
8561 case VOS_P2P_GO_MODE:
8562 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008563 pHddCtx->no_of_sessions[mode]--;
8564 if (!(pHddCtx->no_of_sessions[mode]))
8565 pHddCtx->concurrency_mode &= (~(1 << mode));
8566 break;
8567 default:
8568 break;
8569 }
8570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8571 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8572}
8573
Jeff Johnsone7245742012-09-05 17:12:55 -07008574/**---------------------------------------------------------------------------
8575 *
8576 * \brief wlan_hdd_restart_init
8577 *
8578 * This function initalizes restart timer/flag. An internal function.
8579 *
8580 * \param - pHddCtx
8581 *
8582 * \return - None
8583 *
8584 * --------------------------------------------------------------------------*/
8585
8586static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8587{
8588 /* Initialize */
8589 pHddCtx->hdd_restart_retries = 0;
8590 atomic_set(&pHddCtx->isRestartInProgress, 0);
8591 vos_timer_init(&pHddCtx->hdd_restart_timer,
8592 VOS_TIMER_TYPE_SW,
8593 wlan_hdd_restart_timer_cb,
8594 pHddCtx);
8595}
8596/**---------------------------------------------------------------------------
8597 *
8598 * \brief wlan_hdd_restart_deinit
8599 *
8600 * This function cleans up the resources used. An internal function.
8601 *
8602 * \param - pHddCtx
8603 *
8604 * \return - None
8605 *
8606 * --------------------------------------------------------------------------*/
8607
8608static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8609{
8610
8611 VOS_STATUS vos_status;
8612 /* Block any further calls */
8613 atomic_set(&pHddCtx->isRestartInProgress, 1);
8614 /* Cleanup */
8615 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8616 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008617 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008618 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8619 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008620 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008621
8622}
8623
8624/**---------------------------------------------------------------------------
8625 *
8626 * \brief wlan_hdd_framework_restart
8627 *
8628 * This function uses a cfg80211 API to start a framework initiated WLAN
8629 * driver module unload/load.
8630 *
8631 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8632 *
8633 *
8634 * \param - pHddCtx
8635 *
8636 * \return - VOS_STATUS_SUCCESS: Success
8637 * VOS_STATUS_E_EMPTY: Adapter is Empty
8638 * VOS_STATUS_E_NOMEM: No memory
8639
8640 * --------------------------------------------------------------------------*/
8641
8642static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8643{
8644 VOS_STATUS status = VOS_STATUS_SUCCESS;
8645 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008646 int len = (sizeof (struct ieee80211_mgmt));
8647 struct ieee80211_mgmt *mgmt = NULL;
8648
8649 /* Prepare the DEAUTH managment frame with reason code */
8650 mgmt = kzalloc(len, GFP_KERNEL);
8651 if(mgmt == NULL)
8652 {
8653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8654 "%s: memory allocation failed (%d bytes)", __func__, len);
8655 return VOS_STATUS_E_NOMEM;
8656 }
8657 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008658
8659 /* Iterate over all adapters/devices */
8660 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8661 do
8662 {
8663 if( (status == VOS_STATUS_SUCCESS) &&
8664 pAdapterNode &&
8665 pAdapterNode->pAdapter)
8666 {
8667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8668 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8669 pAdapterNode->pAdapter->dev->name,
8670 pAdapterNode->pAdapter->device_mode,
8671 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008672 /*
8673 * CFG80211 event to restart the driver
8674 *
8675 * 'cfg80211_send_unprot_deauth' sends a
8676 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8677 * of SME(Linux Kernel) state machine.
8678 *
8679 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8680 * the driver.
8681 *
8682 */
8683
8684 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008685 }
8686 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8687 pAdapterNode = pNext;
8688 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8689
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008690
8691 /* Free the allocated management frame */
8692 kfree(mgmt);
8693
Jeff Johnsone7245742012-09-05 17:12:55 -07008694 /* Retry until we unload or reach max count */
8695 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8696 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8697
8698 return status;
8699
8700}
8701/**---------------------------------------------------------------------------
8702 *
8703 * \brief wlan_hdd_restart_timer_cb
8704 *
8705 * Restart timer callback. An internal function.
8706 *
8707 * \param - User data:
8708 *
8709 * \return - None
8710 *
8711 * --------------------------------------------------------------------------*/
8712
8713void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8714{
8715 hdd_context_t *pHddCtx = usrDataForCallback;
8716 wlan_hdd_framework_restart(pHddCtx);
8717 return;
8718
8719}
8720
8721
8722/**---------------------------------------------------------------------------
8723 *
8724 * \brief wlan_hdd_restart_driver
8725 *
8726 * This function sends an event to supplicant to restart the WLAN driver.
8727 *
8728 * This function is called from vos_wlanRestart.
8729 *
8730 * \param - pHddCtx
8731 *
8732 * \return - VOS_STATUS_SUCCESS: Success
8733 * VOS_STATUS_E_EMPTY: Adapter is Empty
8734 * VOS_STATUS_E_ALREADY: Request already in progress
8735
8736 * --------------------------------------------------------------------------*/
8737VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8738{
8739 VOS_STATUS status = VOS_STATUS_SUCCESS;
8740
8741 /* A tight check to make sure reentrancy */
8742 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8743 {
8744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8745 "%s: WLAN restart is already in progress", __func__);
8746
8747 return VOS_STATUS_E_ALREADY;
8748 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008749 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008750#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008751 wcnss_reset_intr();
8752#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008753
Jeff Johnsone7245742012-09-05 17:12:55 -07008754 return status;
8755}
8756
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008757/*
8758 * API to find if there is any STA or P2P-Client is connected
8759 */
8760VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8761{
8762 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8763}
Jeff Johnsone7245742012-09-05 17:12:55 -07008764
Jeff Johnson295189b2012-06-20 16:38:30 -07008765//Register the module init/exit functions
8766module_init(hdd_module_init);
8767module_exit(hdd_module_exit);
8768
8769MODULE_LICENSE("Dual BSD/GPL");
8770MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8771MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8772
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008773module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8774 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008775
Jeff Johnson76052702013-04-16 13:55:05 -07008776module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008777 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);