blob: aa51cce03d622fcfa8a0427c38f1176c77688289 [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*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001413 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301414 {
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,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001451 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301452 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 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301476 count = 0;
1477 len = (len - pPrivData->used_len);
1478 pDest = (command + pPrivData->used_len);
1479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001480 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301481 while(count < len)
1482 {
1483 printk("%c", *(pDest + count));
1484 count++;
1485 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1487 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301488 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 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301494 }
1495
1496 return 0;
1497} /*End of hdd_return_batch_scan_rsp_to_user*/
1498
1499#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1500
Jeff Johnson295189b2012-06-20 16:38:30 -07001501int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1502{
1503 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1504 hdd_priv_data_t priv_data;
1505 tANI_U8 *command = NULL;
1506 int ret = 0;
1507
1508 if (NULL == pAdapter)
1509 {
1510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001511 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001512 ret = -ENODEV;
1513 goto exit;
1514 }
1515
Jeff Johnsone7245742012-09-05 17:12:55 -07001516 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 {
1518 ret = -EINVAL;
1519 goto exit;
1520 }
1521
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001522 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1523 {
1524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1525 "%s:LOGP in Progress. Ignore!!!", __func__);
1526 ret = -EBUSY;
1527 goto exit;
1528 }
1529
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1531 {
1532 ret = -EFAULT;
1533 goto exit;
1534 }
1535
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001536 if (priv_data.total_len <= 0)
1537 {
1538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1539 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1540 priv_data.total_len);
1541 ret = -EINVAL;
1542 goto exit;
1543 }
1544
1545 /* Allocate +1 for '\0' */
1546 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001547 if (!command)
1548 {
1549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001550 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 ret = -ENOMEM;
1552 goto exit;
1553 }
1554
1555 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1556 {
1557 ret = -EFAULT;
1558 goto exit;
1559 }
1560
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001561 /* Making sure the command is NUL-terminated */
1562 command[priv_data.total_len] = '\0';
1563
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 if ((SIOCDEVPRIVATE + 1) == cmd)
1565 {
1566 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1567
1568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001569 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001570
1571 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1572 {
1573 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1574 sizeof(tSirMacAddr)))
1575 {
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001577 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 ret = -EFAULT;
1579 }
1580 }
Amar Singhal0974e402013-02-12 14:27:46 -08001581 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001582 {
Amar Singhal0974e402013-02-12 14:27:46 -08001583 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001584 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001585
Jeff Johnson295189b2012-06-20 16:38:30 -07001586 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001587
1588 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001590 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001591 "%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 -07001592 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001593 ret = hdd_setBand_helper(dev, ptr);
1594 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001595 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1596 {
1597 char *country_code;
1598
1599 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001600
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001601 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001602 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301603 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001604 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1605 (void *)(tSmeChangeCountryCallback)
1606 wlan_hdd_change_country_code_callback,
1607 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1608 if (eHAL_STATUS_SUCCESS == ret)
1609 {
1610 ret = wait_for_completion_interruptible_timeout(
1611 &pAdapter->change_country_code,
1612 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1613 if (0 >= ret)
1614 {
1615 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1616 __func__);
1617 }
1618 }
1619 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001620 {
1621 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001622 "%s: SME Change Country code fail ret=%d", __func__, ret);
1623 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001624 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001625
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001626 }
1627 /*
1628 command should be a string having format
1629 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1630 */
Amar Singhal0974e402013-02-12 14:27:46 -08001631 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001632 {
Amar Singhal0974e402013-02-12 14:27:46 -08001633 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001634
1635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001636 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001637
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001638 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001639 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001640 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1641 {
1642 int suspend = 0;
1643 tANI_U8 *ptr = (tANI_U8*)command + 15;
1644
1645 suspend = *ptr - '0';
1646 hdd_set_wlan_suspend_mode(suspend);
1647 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001648#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1649 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1650 {
1651 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001652 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001653 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1654 eHalStatus status = eHAL_STATUS_SUCCESS;
1655
1656 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1657 value = value + 15;
1658
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001659 /* Convert the value from ascii to integer */
1660 ret = kstrtos8(value, 10, &rssi);
1661 if (ret < 0)
1662 {
1663 /* If the input value is greater than max value of datatype, then also
1664 kstrtou8 fails */
1665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1666 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001667 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001668 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1669 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1670 ret = -EINVAL;
1671 goto exit;
1672 }
1673
Srinivas Girigowdade697412013-02-14 16:31:48 -08001674 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001675
Srinivas Girigowdade697412013-02-14 16:31:48 -08001676 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1677 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1678 {
1679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1680 "Neighbor lookup threshold value %d is out of range"
1681 " (Min: %d Max: %d)", lookUpThreshold,
1682 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1683 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1684 ret = -EINVAL;
1685 goto exit;
1686 }
1687
1688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1689 "%s: Received Command to Set Roam trigger"
1690 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1691
1692 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1693 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1694 if (eHAL_STATUS_SUCCESS != status)
1695 {
1696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1697 "%s: Failed to set roam trigger, try again", __func__);
1698 ret = -EPERM;
1699 goto exit;
1700 }
1701
1702 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1703 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1704 }
1705 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1706 {
1707 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1708 int rssi = (-1) * lookUpThreshold;
1709 char extra[32];
1710 tANI_U8 len = 0;
1711
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001712 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001713 if (copy_to_user(priv_data.buf, &extra, len + 1))
1714 {
1715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1716 "%s: failed to copy data to user buffer", __func__);
1717 ret = -EFAULT;
1718 goto exit;
1719 }
1720 }
1721 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1722 {
1723 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001724 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001725 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001726
Srinivas Girigowdade697412013-02-14 16:31:48 -08001727 /* input refresh period is in terms of seconds */
1728 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1729 value = value + 18;
1730 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001731 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001732 if (ret < 0)
1733 {
1734 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001737 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001738 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001739 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1740 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001741 ret = -EINVAL;
1742 goto exit;
1743 }
1744
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001745 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1746 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001747 {
1748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001749 "Roam scan period value %d is out of range"
1750 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001751 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1752 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001753 ret = -EINVAL;
1754 goto exit;
1755 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001756 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001757
1758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1759 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001760 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001761
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001762 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1763 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001764 }
1765 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1766 {
1767 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1768 char extra[32];
1769 tANI_U8 len = 0;
1770
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001771 len = scnprintf(extra, sizeof(extra), "%s %d",
1772 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001773 /* Returned value is in units of seconds */
1774 if (copy_to_user(priv_data.buf, &extra, len + 1))
1775 {
1776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1777 "%s: failed to copy data to user buffer", __func__);
1778 ret = -EFAULT;
1779 goto exit;
1780 }
1781 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001782 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1783 {
1784 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001786 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001787
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001788 /* input refresh period is in terms of seconds */
1789 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1790 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001791
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001792 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001793 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001794 if (ret < 0)
1795 {
1796 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001799 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001800 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001801 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1802 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001807 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1808 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1809 {
1810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1811 "Neighbor scan results refresh period value %d is out of range"
1812 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1813 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1814 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1815 ret = -EINVAL;
1816 goto exit;
1817 }
1818 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1819
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1821 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001822 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001823
1824 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1825 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1826 }
1827 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1828 {
1829 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1830 char extra[32];
1831 tANI_U8 len = 0;
1832
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001833 len = scnprintf(extra, sizeof(extra), "%s %d",
1834 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001835 /* Returned value is in units of seconds */
1836 if (copy_to_user(priv_data.buf, &extra, len + 1))
1837 {
1838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1839 "%s: failed to copy data to user buffer", __func__);
1840 ret = -EFAULT;
1841 goto exit;
1842 }
1843 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001844#ifdef FEATURE_WLAN_LFR
1845 /* SETROAMMODE */
1846 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1847 {
1848 tANI_U8 *value = command;
1849 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1850
1851 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1852 value = value + SIZE_OF_SETROAMMODE + 1;
1853
1854 /* Convert the value from ascii to integer */
1855 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1856 if (ret < 0)
1857 {
1858 /* If the input value is greater than max value of datatype, then also
1859 kstrtou8 fails */
1860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1861 "%s: kstrtou8 failed range [%d - %d]", __func__,
1862 CFG_LFR_FEATURE_ENABLED_MIN,
1863 CFG_LFR_FEATURE_ENABLED_MAX);
1864 ret = -EINVAL;
1865 goto exit;
1866 }
1867 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1868 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1869 {
1870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1871 "Roam Mode value %d is out of range"
1872 " (Min: %d Max: %d)", roamMode,
1873 CFG_LFR_FEATURE_ENABLED_MIN,
1874 CFG_LFR_FEATURE_ENABLED_MAX);
1875 ret = -EINVAL;
1876 goto exit;
1877 }
1878
1879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1880 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1881 /*
1882 * Note that
1883 * SETROAMMODE 0 is to enable LFR while
1884 * SETROAMMODE 1 is to disable LFR, but
1885 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1886 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1887 */
1888 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1889 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1890 else
1891 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1892
1893 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1894 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1895 }
1896 /* GETROAMMODE */
1897 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1898 {
1899 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1900 char extra[32];
1901 tANI_U8 len = 0;
1902
1903 /*
1904 * roamMode value shall be inverted because the sementics is different.
1905 */
1906 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1907 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1908 else
1909 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1910
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001911 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001912 if (copy_to_user(priv_data.buf, &extra, len + 1))
1913 {
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1915 "%s: failed to copy data to user buffer", __func__);
1916 ret = -EFAULT;
1917 goto exit;
1918 }
1919 }
1920#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001921#endif
1922#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1923 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1924 {
1925 tANI_U8 *value = command;
1926 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1927
1928 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1929 value = value + 13;
1930 /* Convert the value from ascii to integer */
1931 ret = kstrtou8(value, 10, &roamRssiDiff);
1932 if (ret < 0)
1933 {
1934 /* If the input value is greater than max value of datatype, then also
1935 kstrtou8 fails */
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "%s: kstrtou8 failed range [%d - %d]", __func__,
1938 CFG_ROAM_RSSI_DIFF_MIN,
1939 CFG_ROAM_RSSI_DIFF_MAX);
1940 ret = -EINVAL;
1941 goto exit;
1942 }
1943
1944 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1945 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1946 {
1947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1948 "Roam rssi diff value %d is out of range"
1949 " (Min: %d Max: %d)", roamRssiDiff,
1950 CFG_ROAM_RSSI_DIFF_MIN,
1951 CFG_ROAM_RSSI_DIFF_MAX);
1952 ret = -EINVAL;
1953 goto exit;
1954 }
1955
1956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1957 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1958
1959 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1960 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1961 }
1962 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1963 {
1964 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1965 char extra[32];
1966 tANI_U8 len = 0;
1967
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001968 len = scnprintf(extra, sizeof(extra), "%s %d",
1969 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001970 if (copy_to_user(priv_data.buf, &extra, len + 1))
1971 {
1972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1973 "%s: failed to copy data to user buffer", __func__);
1974 ret = -EFAULT;
1975 goto exit;
1976 }
1977 }
1978#endif
1979#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1980 else if (strncmp(command, "GETBAND", 7) == 0)
1981 {
1982 int band = -1;
1983 char extra[32];
1984 tANI_U8 len = 0;
1985 hdd_getBand_helper(pHddCtx, &band);
1986
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001987 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001988 if (copy_to_user(priv_data.buf, &extra, len + 1))
1989 {
1990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1991 "%s: failed to copy data to user buffer", __func__);
1992 ret = -EFAULT;
1993 goto exit;
1994 }
1995 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001996 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1997 {
1998 tANI_U8 *value = command;
1999 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2000 tANI_U8 numChannels = 0;
2001 eHalStatus status = eHAL_STATUS_SUCCESS;
2002
2003 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2004 if (eHAL_STATUS_SUCCESS != status)
2005 {
2006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2007 "%s: Failed to parse channel list information", __func__);
2008 ret = -EINVAL;
2009 goto exit;
2010 }
2011
2012 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2013 {
2014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2015 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2016 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2017 ret = -EINVAL;
2018 goto exit;
2019 }
2020 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2021 numChannels);
2022 if (eHAL_STATUS_SUCCESS != status)
2023 {
2024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2025 "%s: Failed to update channel list information", __func__);
2026 ret = -EINVAL;
2027 goto exit;
2028 }
2029 }
2030 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2031 {
2032 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2033 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002034 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002035 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002036 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002037
2038 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2039 ChannelList, &numChannels ))
2040 {
2041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2042 "%s: failed to get roam scan channel list", __func__);
2043 ret = -EFAULT;
2044 goto exit;
2045 }
2046 /* output channel list is of the format
2047 [Number of roam scan channels][Channel1][Channel2]... */
2048 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002049 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002050 for (j = 0; (j < numChannels); j++)
2051 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002052 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2053 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002054 }
2055
2056 if (copy_to_user(priv_data.buf, &extra, len + 1))
2057 {
2058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: failed to copy data to user buffer", __func__);
2060 ret = -EFAULT;
2061 goto exit;
2062 }
2063 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002064 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2065 {
2066 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2067 char extra[32];
2068 tANI_U8 len = 0;
2069
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002070 /* Check if the features OKC/CCX/11R are supported simultaneously,
2071 then this operation is not permitted (return FAILURE) */
2072 if (ccxMode &&
2073 hdd_is_okc_mode_enabled(pHddCtx) &&
2074 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2075 {
2076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2077 "%s: OKC/CCX/11R are supported simultaneously"
2078 " hence this operation is not permitted!", __func__);
2079 ret = -EPERM;
2080 goto exit;
2081 }
2082
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002083 len = scnprintf(extra, sizeof(extra), "%s %d",
2084 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002085 if (copy_to_user(priv_data.buf, &extra, len + 1))
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2088 "%s: failed to copy data to user buffer", __func__);
2089 ret = -EFAULT;
2090 goto exit;
2091 }
2092 }
2093 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2094 {
2095 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2096 char extra[32];
2097 tANI_U8 len = 0;
2098
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002099 /* Check if the features OKC/CCX/11R are supported simultaneously,
2100 then this operation is not permitted (return FAILURE) */
2101 if (okcMode &&
2102 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2103 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2104 {
2105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2106 "%s: OKC/CCX/11R are supported simultaneously"
2107 " hence this operation is not permitted!", __func__);
2108 ret = -EPERM;
2109 goto exit;
2110 }
2111
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002112 len = scnprintf(extra, sizeof(extra), "%s %d",
2113 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002114 if (copy_to_user(priv_data.buf, &extra, len + 1))
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2117 "%s: failed to copy data to user buffer", __func__);
2118 ret = -EFAULT;
2119 goto exit;
2120 }
2121 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002122 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002123 {
2124 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2125 char extra[32];
2126 tANI_U8 len = 0;
2127
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002128 len = scnprintf(extra, sizeof(extra), "%s %d",
2129 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002130 if (copy_to_user(priv_data.buf, &extra, len + 1))
2131 {
2132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2133 "%s: failed to copy data to user buffer", __func__);
2134 ret = -EFAULT;
2135 goto exit;
2136 }
2137 }
2138 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2139 {
2140 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2141 char extra[32];
2142 tANI_U8 len = 0;
2143
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002144 len = scnprintf(extra, sizeof(extra), "%s %d",
2145 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002146 if (copy_to_user(priv_data.buf, &extra, len + 1))
2147 {
2148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2149 "%s: failed to copy data to user buffer", __func__);
2150 ret = -EFAULT;
2151 goto exit;
2152 }
2153 }
2154 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2155 {
2156 tANI_U8 *value = command;
2157 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2158
2159 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2160 value = value + 26;
2161 /* Convert the value from ascii to integer */
2162 ret = kstrtou8(value, 10, &minTime);
2163 if (ret < 0)
2164 {
2165 /* If the input value is greater than max value of datatype, then also
2166 kstrtou8 fails */
2167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2168 "%s: kstrtou8 failed range [%d - %d]", __func__,
2169 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2170 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2171 ret = -EINVAL;
2172 goto exit;
2173 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002174 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2175 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2176 {
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2178 "scan min channel time value %d is out of range"
2179 " (Min: %d Max: %d)", minTime,
2180 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2181 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2182 ret = -EINVAL;
2183 goto exit;
2184 }
2185
2186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2187 "%s: Received Command to change channel min time = %d", __func__, minTime);
2188
2189 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2190 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2191 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002192 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2193 {
2194 tANI_U8 *value = command;
2195 tANI_U8 channel = 0;
2196 tANI_U8 dwellTime = 0;
2197 tANI_U8 bufLen = 0;
2198 tANI_U8 *buf = NULL;
2199 tSirMacAddr targetApBssid;
2200 eHalStatus status = eHAL_STATUS_SUCCESS;
2201 struct ieee80211_channel chan;
2202 tANI_U8 finalLen = 0;
2203 tANI_U8 *finalBuf = NULL;
2204 tANI_U8 temp = 0;
2205 u64 cookie;
2206 hdd_station_ctx_t *pHddStaCtx = NULL;
2207 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2208
2209 /* if not associated, no need to send action frame */
2210 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2211 {
2212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2213 ret = -EINVAL;
2214 goto exit;
2215 }
2216
2217 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2218 &dwellTime, &buf, &bufLen);
2219 if (eHAL_STATUS_SUCCESS != status)
2220 {
2221 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2222 "%s: Failed to parse send action frame data", __func__);
2223 ret = -EINVAL;
2224 goto exit;
2225 }
2226
2227 /* if the target bssid is different from currently associated AP,
2228 then no need to send action frame */
2229 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2230 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2231 {
2232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2233 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002234 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002235 goto exit;
2236 }
2237
2238 /* if the channel number is different from operating channel then
2239 no need to send action frame */
2240 if (channel != pHddStaCtx->conn_info.operationChannel)
2241 {
2242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2243 "%s: channel(%d) is different from operating channel(%d)",
2244 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2245 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002246 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002247 goto exit;
2248 }
2249 chan.center_freq = sme_ChnToFreq(channel);
2250
2251 finalLen = bufLen + 24;
2252 finalBuf = vos_mem_malloc(finalLen);
2253 if (NULL == finalBuf)
2254 {
2255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2256 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002257 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002258 goto exit;
2259 }
2260 vos_mem_zero(finalBuf, finalLen);
2261
2262 /* Fill subtype */
2263 temp = SIR_MAC_MGMT_ACTION << 4;
2264 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2265
2266 /* Fill type */
2267 temp = SIR_MAC_MGMT_FRAME;
2268 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2269
2270 /* Fill destination address (bssid of the AP) */
2271 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2272
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002273 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002274 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2275
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002276 /* Fill BSSID (AP mac address) */
2277 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002278
2279 /* Fill received buffer from 24th address */
2280 vos_mem_copy(finalBuf + 24, buf, bufLen);
2281
Jeff Johnson11c33152013-04-16 17:52:40 -07002282 /* done with the parsed buffer */
2283 vos_mem_free(buf);
2284
Yue Maf49ba872013-08-19 12:04:25 -07002285 wlan_hdd_action( NULL,
2286#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2287 &(pAdapter->wdev),
2288#else
2289 dev,
2290#endif
2291 &chan, 0,
2292#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2293 NL80211_CHAN_HT20, 1,
2294#endif
2295 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002296 1, &cookie );
2297 vos_mem_free(finalBuf);
2298 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002299 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2300 {
2301 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2302 char extra[32];
2303 tANI_U8 len = 0;
2304
2305 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002306 len = scnprintf(extra, sizeof(extra), "%s %d",
2307 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002308 if (copy_to_user(priv_data.buf, &extra, len + 1))
2309 {
2310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2311 "%s: failed to copy data to user buffer", __func__);
2312 ret = -EFAULT;
2313 goto exit;
2314 }
2315 }
2316 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2317 {
2318 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002319 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002320 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002321
2322 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2323 value = value + 19;
2324 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002325 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002326 if (ret < 0)
2327 {
2328 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002329 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002331 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002332 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2333 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2334 ret = -EINVAL;
2335 goto exit;
2336 }
2337
2338 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2339 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2340 {
2341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2342 "lfr mode value %d is out of range"
2343 " (Min: %d Max: %d)", maxTime,
2344 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2345 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2346 ret = -EINVAL;
2347 goto exit;
2348 }
2349
2350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2351 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2352
2353 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002354
2355 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2356 * where RFS is the RF Switching time. It is twice RFS to consider the
2357 * time to go off channel and return to the home channel. */
2358 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2359 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2360 {
2361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002362 "%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 -07002363 " Hence enforcing home away time to disable (0)",
2364 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2365 homeAwayTime = 0;
2366 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2367 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2368 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002369 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2370 }
2371 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2372 {
2373 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2374 char extra[32];
2375 tANI_U8 len = 0;
2376
2377 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002378 len = scnprintf(extra, sizeof(extra), "%s %d",
2379 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002380 if (copy_to_user(priv_data.buf, &extra, len + 1))
2381 {
2382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2383 "%s: failed to copy data to user buffer", __func__);
2384 ret = -EFAULT;
2385 goto exit;
2386 }
2387 }
2388 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2389 {
2390 tANI_U8 *value = command;
2391 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2392
2393 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2394 value = value + 16;
2395 /* Convert the value from ascii to integer */
2396 ret = kstrtou16(value, 10, &val);
2397 if (ret < 0)
2398 {
2399 /* If the input value is greater than max value of datatype, then also
2400 kstrtou16 fails */
2401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2402 "%s: kstrtou16 failed range [%d - %d]", __func__,
2403 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2404 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2405 ret = -EINVAL;
2406 goto exit;
2407 }
2408
2409 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2410 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2411 {
2412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2413 "scan home time value %d is out of range"
2414 " (Min: %d Max: %d)", val,
2415 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2416 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2417 ret = -EINVAL;
2418 goto exit;
2419 }
2420
2421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2422 "%s: Received Command to change scan home time = %d", __func__, val);
2423
2424 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2425 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2426 }
2427 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2428 {
2429 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2430 char extra[32];
2431 tANI_U8 len = 0;
2432
2433 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002434 len = scnprintf(extra, sizeof(extra), "%s %d",
2435 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 if (copy_to_user(priv_data.buf, &extra, len + 1))
2437 {
2438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2439 "%s: failed to copy data to user buffer", __func__);
2440 ret = -EFAULT;
2441 goto exit;
2442 }
2443 }
2444 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2445 {
2446 tANI_U8 *value = command;
2447 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2448
2449 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2450 value = value + 17;
2451 /* Convert the value from ascii to integer */
2452 ret = kstrtou8(value, 10, &val);
2453 if (ret < 0)
2454 {
2455 /* If the input value is greater than max value of datatype, then also
2456 kstrtou8 fails */
2457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2458 "%s: kstrtou8 failed range [%d - %d]", __func__,
2459 CFG_ROAM_INTRA_BAND_MIN,
2460 CFG_ROAM_INTRA_BAND_MAX);
2461 ret = -EINVAL;
2462 goto exit;
2463 }
2464
2465 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2466 (val > CFG_ROAM_INTRA_BAND_MAX))
2467 {
2468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2469 "intra band mode value %d is out of range"
2470 " (Min: %d Max: %d)", val,
2471 CFG_ROAM_INTRA_BAND_MIN,
2472 CFG_ROAM_INTRA_BAND_MAX);
2473 ret = -EINVAL;
2474 goto exit;
2475 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2477 "%s: Received Command to change intra band = %d", __func__, val);
2478
2479 pHddCtx->cfg_ini->nRoamIntraBand = val;
2480 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2481 }
2482 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2483 {
2484 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2485 char extra[32];
2486 tANI_U8 len = 0;
2487
2488 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002489 len = scnprintf(extra, sizeof(extra), "%s %d",
2490 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002491 if (copy_to_user(priv_data.buf, &extra, len + 1))
2492 {
2493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2494 "%s: failed to copy data to user buffer", __func__);
2495 ret = -EFAULT;
2496 goto exit;
2497 }
2498 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002499 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2500 {
2501 tANI_U8 *value = command;
2502 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2503
2504 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2505 value = value + 15;
2506 /* Convert the value from ascii to integer */
2507 ret = kstrtou8(value, 10, &nProbes);
2508 if (ret < 0)
2509 {
2510 /* If the input value is greater than max value of datatype, then also
2511 kstrtou8 fails */
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "%s: kstrtou8 failed range [%d - %d]", __func__,
2514 CFG_ROAM_SCAN_N_PROBES_MIN,
2515 CFG_ROAM_SCAN_N_PROBES_MAX);
2516 ret = -EINVAL;
2517 goto exit;
2518 }
2519
2520 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2521 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2522 {
2523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2524 "NProbes value %d is out of range"
2525 " (Min: %d Max: %d)", nProbes,
2526 CFG_ROAM_SCAN_N_PROBES_MIN,
2527 CFG_ROAM_SCAN_N_PROBES_MAX);
2528 ret = -EINVAL;
2529 goto exit;
2530 }
2531
2532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2533 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2534
2535 pHddCtx->cfg_ini->nProbes = nProbes;
2536 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2537 }
2538 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2539 {
2540 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2541 char extra[32];
2542 tANI_U8 len = 0;
2543
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002544 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002545 if (copy_to_user(priv_data.buf, &extra, len + 1))
2546 {
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2548 "%s: failed to copy data to user buffer", __func__);
2549 ret = -EFAULT;
2550 goto exit;
2551 }
2552 }
2553 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2554 {
2555 tANI_U8 *value = command;
2556 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002557 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002558
2559 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2560 /* input value is in units of msec */
2561 value = value + 20;
2562 /* Convert the value from ascii to integer */
2563 ret = kstrtou16(value, 10, &homeAwayTime);
2564 if (ret < 0)
2565 {
2566 /* If the input value is greater than max value of datatype, then also
2567 kstrtou8 fails */
2568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2569 "%s: kstrtou8 failed range [%d - %d]", __func__,
2570 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2571 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2572 ret = -EINVAL;
2573 goto exit;
2574 }
2575
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002576 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2577 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2578 {
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "homeAwayTime value %d is out of range"
2581 " (Min: %d Max: %d)", homeAwayTime,
2582 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2583 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2584 ret = -EINVAL;
2585 goto exit;
2586 }
2587
2588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2589 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2590
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002591 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2592 * where RFS is the RF Switching time. It is twice RFS to consider the
2593 * time to go off channel and return to the home channel. */
2594 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2595 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2596 {
2597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002598 "%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 -07002599 " Hence enforcing home away time to disable (0)",
2600 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2601 homeAwayTime = 0;
2602 }
2603
2604 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2605 {
2606 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2607 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2608 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002609 }
2610 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2611 {
2612 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2613 char extra[32];
2614 tANI_U8 len = 0;
2615
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002616 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002617 if (copy_to_user(priv_data.buf, &extra, len + 1))
2618 {
2619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2620 "%s: failed to copy data to user buffer", __func__);
2621 ret = -EFAULT;
2622 goto exit;
2623 }
2624 }
2625 else if (strncmp(command, "REASSOC", 7) == 0)
2626 {
2627 tANI_U8 *value = command;
2628 tANI_U8 channel = 0;
2629 tSirMacAddr targetApBssid;
2630 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002631#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2632 tCsrHandoffRequest handoffInfo;
2633#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002634 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002635 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2636
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002637 /* if not associated, no need to proceed with reassoc */
2638 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2639 {
2640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2641 ret = -EINVAL;
2642 goto exit;
2643 }
2644
2645 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2646 if (eHAL_STATUS_SUCCESS != status)
2647 {
2648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2649 "%s: Failed to parse reassoc command data", __func__);
2650 ret = -EINVAL;
2651 goto exit;
2652 }
2653
2654 /* if the target bssid is same as currently associated AP,
2655 then no need to proceed with reassoc */
2656 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2657 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2658 {
2659 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2660 ret = -EINVAL;
2661 goto exit;
2662 }
2663
2664 /* Check channel number is a valid channel number */
2665 if(VOS_STATUS_SUCCESS !=
2666 wlan_hdd_validate_operation_channel(pAdapter, channel))
2667 {
2668 hddLog(VOS_TRACE_LEVEL_ERROR,
2669 "%s: Invalid Channel [%d] \n", __func__, channel);
2670 return -EINVAL;
2671 }
2672
2673 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002674#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2675 handoffInfo.channel = channel;
2676 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2677 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2678#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002679 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002680 else if (strncmp(command, "SETWESMODE", 10) == 0)
2681 {
2682 tANI_U8 *value = command;
2683 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2684
2685 /* Move pointer to ahead of SETWESMODE<delimiter> */
2686 value = value + 11;
2687 /* Convert the value from ascii to integer */
2688 ret = kstrtou8(value, 10, &wesMode);
2689 if (ret < 0)
2690 {
2691 /* If the input value is greater than max value of datatype, then also
2692 kstrtou8 fails */
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2694 "%s: kstrtou8 failed range [%d - %d]", __func__,
2695 CFG_ENABLE_WES_MODE_NAME_MIN,
2696 CFG_ENABLE_WES_MODE_NAME_MAX);
2697 ret = -EINVAL;
2698 goto exit;
2699 }
2700
2701 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2702 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2703 {
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "WES Mode value %d is out of range"
2706 " (Min: %d Max: %d)", wesMode,
2707 CFG_ENABLE_WES_MODE_NAME_MIN,
2708 CFG_ENABLE_WES_MODE_NAME_MAX);
2709 ret = -EINVAL;
2710 goto exit;
2711 }
2712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2713 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2714
2715 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2716 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2717 }
2718 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2719 {
2720 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2721 char extra[32];
2722 tANI_U8 len = 0;
2723
Arif Hussain826d9412013-11-12 16:44:54 -08002724 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002725 if (copy_to_user(priv_data.buf, &extra, len + 1))
2726 {
2727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2728 "%s: failed to copy data to user buffer", __func__);
2729 ret = -EFAULT;
2730 goto exit;
2731 }
2732 }
2733#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002734#ifdef FEATURE_WLAN_LFR
2735 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2736 {
2737 tANI_U8 *value = command;
2738 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2739
2740 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2741 value = value + 12;
2742 /* Convert the value from ascii to integer */
2743 ret = kstrtou8(value, 10, &lfrMode);
2744 if (ret < 0)
2745 {
2746 /* If the input value is greater than max value of datatype, then also
2747 kstrtou8 fails */
2748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2749 "%s: kstrtou8 failed range [%d - %d]", __func__,
2750 CFG_LFR_FEATURE_ENABLED_MIN,
2751 CFG_LFR_FEATURE_ENABLED_MAX);
2752 ret = -EINVAL;
2753 goto exit;
2754 }
2755
2756 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2757 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2758 {
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2760 "lfr mode value %d is out of range"
2761 " (Min: %d Max: %d)", lfrMode,
2762 CFG_LFR_FEATURE_ENABLED_MIN,
2763 CFG_LFR_FEATURE_ENABLED_MAX);
2764 ret = -EINVAL;
2765 goto exit;
2766 }
2767
2768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2769 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2770
2771 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2772 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2773 }
2774#endif
2775#ifdef WLAN_FEATURE_VOWIFI_11R
2776 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2777 {
2778 tANI_U8 *value = command;
2779 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2780
2781 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2782 value = value + 18;
2783 /* Convert the value from ascii to integer */
2784 ret = kstrtou8(value, 10, &ft);
2785 if (ret < 0)
2786 {
2787 /* If the input value is greater than max value of datatype, then also
2788 kstrtou8 fails */
2789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2790 "%s: kstrtou8 failed range [%d - %d]", __func__,
2791 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2792 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2793 ret = -EINVAL;
2794 goto exit;
2795 }
2796
2797 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2798 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2799 {
2800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2801 "ft mode value %d is out of range"
2802 " (Min: %d Max: %d)", ft,
2803 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2804 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2805 ret = -EINVAL;
2806 goto exit;
2807 }
2808
2809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2810 "%s: Received Command to change ft mode = %d", __func__, ft);
2811
2812 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2813 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2814 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302815
2816 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2817 {
2818 tANI_U8 *value = command;
2819 tSirMacAddr targetApBssid;
2820 tANI_U8 trigger = 0;
2821 eHalStatus status = eHAL_STATUS_SUCCESS;
2822 hdd_station_ctx_t *pHddStaCtx = NULL;
2823 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2824
2825 /* if not associated, no need to proceed with reassoc */
2826 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2827 {
2828 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2829 ret = -EINVAL;
2830 goto exit;
2831 }
2832
2833 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2834 if (eHAL_STATUS_SUCCESS != status)
2835 {
2836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2837 "%s: Failed to parse reassoc command data", __func__);
2838 ret = -EINVAL;
2839 goto exit;
2840 }
2841
2842 /* if the target bssid is same as currently associated AP,
2843 then no need to proceed with reassoc */
2844 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2845 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2846 {
2847 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2848 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2849 __func__);
2850 ret = -EINVAL;
2851 goto exit;
2852 }
2853
2854 /* Proceed with scan/roam */
2855 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2856 &targetApBssid[0],
2857 (tSmeFastRoamTrigger)(trigger));
2858 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002859#endif
2860#ifdef FEATURE_WLAN_CCX
2861 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2862 {
2863 tANI_U8 *value = command;
2864 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2865
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002866 /* Check if the features OKC/CCX/11R are supported simultaneously,
2867 then this operation is not permitted (return FAILURE) */
2868 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2869 hdd_is_okc_mode_enabled(pHddCtx) &&
2870 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2871 {
2872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2873 "%s: OKC/CCX/11R are supported simultaneously"
2874 " hence this operation is not permitted!", __func__);
2875 ret = -EPERM;
2876 goto exit;
2877 }
2878
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002879 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2880 value = value + 11;
2881 /* Convert the value from ascii to integer */
2882 ret = kstrtou8(value, 10, &ccxMode);
2883 if (ret < 0)
2884 {
2885 /* If the input value is greater than max value of datatype, then also
2886 kstrtou8 fails */
2887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2888 "%s: kstrtou8 failed range [%d - %d]", __func__,
2889 CFG_CCX_FEATURE_ENABLED_MIN,
2890 CFG_CCX_FEATURE_ENABLED_MAX);
2891 ret = -EINVAL;
2892 goto exit;
2893 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002894 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2895 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2896 {
2897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2898 "Ccx mode value %d is out of range"
2899 " (Min: %d Max: %d)", ccxMode,
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 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2906 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2907
2908 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2909 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2910 }
2911#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002912 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2913 {
2914 tANI_U8 *value = command;
2915 tANI_BOOLEAN roamScanControl = 0;
2916
2917 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2918 value = value + 19;
2919 /* Convert the value from ascii to integer */
2920 ret = kstrtou8(value, 10, &roamScanControl);
2921 if (ret < 0)
2922 {
2923 /* If the input value is greater than max value of datatype, then also
2924 kstrtou8 fails */
2925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2926 "%s: kstrtou8 failed ", __func__);
2927 ret = -EINVAL;
2928 goto exit;
2929 }
2930
2931 if (0 != roamScanControl)
2932 {
2933 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2934 "roam scan control invalid value = %d",
2935 roamScanControl);
2936 ret = -EINVAL;
2937 goto exit;
2938 }
2939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2940 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2941
2942 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2943 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002944#ifdef FEATURE_WLAN_OKC
2945 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2946 {
2947 tANI_U8 *value = command;
2948 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2949
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002950 /* Check if the features OKC/CCX/11R are supported simultaneously,
2951 then this operation is not permitted (return FAILURE) */
2952 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2953 hdd_is_okc_mode_enabled(pHddCtx) &&
2954 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2955 {
2956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2957 "%s: OKC/CCX/11R are supported simultaneously"
2958 " hence this operation is not permitted!", __func__);
2959 ret = -EPERM;
2960 goto exit;
2961 }
2962
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002963 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2964 value = value + 11;
2965 /* Convert the value from ascii to integer */
2966 ret = kstrtou8(value, 10, &okcMode);
2967 if (ret < 0)
2968 {
2969 /* If the input value is greater than max value of datatype, then also
2970 kstrtou8 fails */
2971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2972 "%s: kstrtou8 failed range [%d - %d]", __func__,
2973 CFG_OKC_FEATURE_ENABLED_MIN,
2974 CFG_OKC_FEATURE_ENABLED_MAX);
2975 ret = -EINVAL;
2976 goto exit;
2977 }
2978
2979 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2980 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2981 {
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2983 "Okc mode value %d is out of range"
2984 " (Min: %d Max: %d)", okcMode,
2985 CFG_OKC_FEATURE_ENABLED_MIN,
2986 CFG_OKC_FEATURE_ENABLED_MAX);
2987 ret = -EINVAL;
2988 goto exit;
2989 }
2990
2991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2992 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2993
2994 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2995 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002996#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002997 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2998 {
2999 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3000 char extra[32];
3001 tANI_U8 len = 0;
3002
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003003 len = scnprintf(extra, sizeof(extra), "%s %d",
3004 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003005 if (copy_to_user(priv_data.buf, &extra, len + 1))
3006 {
3007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3008 "%s: failed to copy data to user buffer", __func__);
3009 ret = -EFAULT;
3010 goto exit;
3011 }
3012 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303013#ifdef WLAN_FEATURE_PACKET_FILTERING
3014 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3015 {
3016 tANI_U8 filterType = 0;
3017 tANI_U8 *value = command;
3018
3019 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3020 value = value + 22;
3021
3022 /* Convert the value from ascii to integer */
3023 ret = kstrtou8(value, 10, &filterType);
3024 if (ret < 0)
3025 {
3026 /* If the input value is greater than max value of datatype,
3027 * then also kstrtou8 fails
3028 */
3029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3030 "%s: kstrtou8 failed range ", __func__);
3031 ret = -EINVAL;
3032 goto exit;
3033 }
3034
3035 if (filterType != 0 && filterType != 1)
3036 {
3037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3038 "%s: Accepted Values are 0 and 1 ", __func__);
3039 ret = -EINVAL;
3040 goto exit;
3041 }
3042 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3043 pAdapter->sessionId);
3044 }
3045#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303046 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3047 {
3048 char *dhcpPhase;
3049 dhcpPhase = command + 12;
3050 if ('1' == *dhcpPhase)
3051 {
3052 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3053 pAdapter->macAddressCurrent.bytes);
3054 }
3055 else if ('2' == *dhcpPhase)
3056 {
3057 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3058 pAdapter->macAddressCurrent.bytes);
3059 }
3060 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003061 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3062 {
3063 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3064 }
3065 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3066 {
3067 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3068 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303069 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3070 {
3071 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3072 char extra[32];
3073 tANI_U8 len = 0;
3074
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003075 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303076 (int)pCfg->nActiveMaxChnTime);
3077 if (copy_to_user(priv_data.buf, &extra, len + 1))
3078 {
3079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3080 "%s: failed to copy data to user buffer", __func__);
3081 ret = -EFAULT;
3082 goto exit;
3083 }
3084 ret = len;
3085 }
3086 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3087 {
3088 tANI_U8 *value = command;
3089 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3090 int val = 0, temp;
3091
3092 value = value + 13;
3093 temp = kstrtou32(value, 10, &val);
3094 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3095 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3096 {
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3098 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3099 ret = -EFAULT;
3100 goto exit;
3101 }
3102 pCfg->nActiveMaxChnTime = val;
3103 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003104 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3105 {
3106 tANI_U8 filterType = 0;
3107 tANI_U8 *value;
3108 value = command + 9;
3109
3110 /* Convert the value from ascii to integer */
3111 ret = kstrtou8(value, 10, &filterType);
3112 if (ret < 0)
3113 {
3114 /* If the input value is greater than max value of datatype,
3115 * then also kstrtou8 fails
3116 */
3117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3118 "%s: kstrtou8 failed range ", __func__);
3119 ret = -EINVAL;
3120 goto exit;
3121 }
3122 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3123 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3124 {
3125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3126 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3127 " 2-Sink ", __func__);
3128 ret = -EINVAL;
3129 goto exit;
3130 }
3131 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3132 pHddCtx->drvr_miracast = filterType;
3133 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3134 }
Leo Chang614d2072013-08-22 14:59:44 -07003135 else if (strncmp(command, "SETMCRATE", 9) == 0)
3136 {
Leo Chang614d2072013-08-22 14:59:44 -07003137 tANI_U8 *value = command;
3138 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003139 tSirRateUpdateInd *rateUpdate;
3140 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003141
3142 /* Only valid for SAP mode */
3143 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3144 {
3145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3146 "%s: SAP mode is not running", __func__);
3147 ret = -EFAULT;
3148 goto exit;
3149 }
3150
3151 /* Move pointer to ahead of SETMCRATE<delimiter> */
3152 /* input value is in units of hundred kbps */
3153 value = value + 10;
3154 /* Convert the value from ascii to integer, decimal base */
3155 ret = kstrtouint(value, 10, &targetRate);
3156
Leo Chang1f98cbd2013-10-17 15:03:52 -07003157 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3158 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003159 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003160 hddLog(VOS_TRACE_LEVEL_ERROR,
3161 "%s: SETMCRATE indication alloc fail", __func__);
3162 ret = -EFAULT;
3163 goto exit;
3164 }
3165 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3166
3167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3168 "MC Target rate %d", targetRate);
3169 /* Ignore unicast */
3170 rateUpdate->ucastDataRate = -1;
3171 rateUpdate->mcastDataRate24GHz = targetRate;
3172 rateUpdate->mcastDataRate5GHz = targetRate;
3173 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3174 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3175 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3176 if (eHAL_STATUS_SUCCESS != status)
3177 {
3178 hddLog(VOS_TRACE_LEVEL_ERROR,
3179 "%s: SET_MC_RATE failed", __func__);
3180 vos_mem_free(rateUpdate);
3181 ret = -EFAULT;
3182 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003183 }
3184 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303185#ifdef FEATURE_WLAN_BATCH_SCAN
3186 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3187 {
3188 char extra[32];
3189 tANI_U8 len = 0;
3190 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3191
3192 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3193 {
3194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3195 "%s: Batch scan feature is not supported by FW", __func__);
3196 ret = -EINVAL;
3197 goto exit;
3198 }
3199
3200 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3201 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3202 {
3203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3204 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3205 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3206 " mode",
3207 pAdapter->device_mode);
3208 ret = -EINVAL;
3209 goto exit;
3210 }
3211
Arif Hussain826d9412013-11-12 16:44:54 -08003212 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303213 version);
3214 if (copy_to_user(priv_data.buf, &extra, len + 1))
3215 {
3216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3217 "%s: failed to copy data to user buffer", __func__);
3218 ret = -EFAULT;
3219 goto exit;
3220 }
3221 ret = HDD_BATCH_SCAN_VERSION;
3222 }
3223 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3224 {
3225 int status;
3226 tANI_U8 *value = (command + 16);
3227 eHalStatus halStatus;
3228 unsigned long rc;
3229 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3230 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3231
3232 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3233 {
3234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3235 "%s: Batch scan feature is not supported by FW", __func__);
3236 ret = -EINVAL;
3237 goto exit;
3238 }
3239
Rajeev Kumar20140c12013-10-21 19:39:02 -07003240
Rajeev79dbe4c2013-10-05 11:03:42 +05303241 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3242 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003245 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303246 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3247 pAdapter->device_mode);
3248 ret = -EINVAL;
3249 goto exit;
3250 }
3251
Rajeev Kumar20140c12013-10-21 19:39:02 -07003252
Rajeev79dbe4c2013-10-05 11:03:42 +05303253 status = hdd_parse_set_batchscan_command(value, pReq);
3254 if (status)
3255 {
3256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003257 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303258 ret = -EINVAL;
3259 goto exit;
3260 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003261
3262
Rajeev79dbe4c2013-10-05 11:03:42 +05303263 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3264 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3265 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3266 pAdapter);
3267
3268 if ( eHAL_STATUS_SUCCESS == halStatus )
3269 {
3270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3271 "sme_SetBatchScanReq returned success halStatus %d",
3272 halStatus);
3273 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3274 {
3275 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3276 rc = wait_for_completion_timeout(
3277 &pAdapter->hdd_set_batch_scan_req_var,
3278 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3279 if (0 == rc)
3280 {
3281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "%s: Timeout waiting for set batch scan to complete",
3283 __func__);
3284 ret = -EINVAL;
3285 goto exit;
3286 }
3287 }
3288 if ( !pRsp->nScansToBatch )
3289 {
3290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3291 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003292 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303293 ret = -EINVAL;
3294 goto exit;
3295 }
3296 /*As per the Batch Scan Framework API we should return the MIN of
3297 either MSCAN or the max # of scans firmware can cache*/
3298 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3299
Rajeev Kumar20140c12013-10-21 19:39:02 -07003300 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3301
Rajeev79dbe4c2013-10-05 11:03:42 +05303302 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3303 "%s: request MSCAN %d response MSCAN %d ret %d",
3304 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3305 }
3306 else
3307 {
3308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3309 "sme_SetBatchScanReq returned failure halStatus %d",
3310 halStatus);
3311 ret = -EINVAL;
3312 goto exit;
3313 }
3314 }
3315 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3316 {
3317 eHalStatus halStatus;
3318 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3319 pInd->param = 0;
3320
3321 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3322 {
3323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3324 "%s: Batch scan feature is not supported by FW", __func__);
3325 ret = -EINVAL;
3326 goto exit;
3327 }
3328
Rajeev Kumar20140c12013-10-21 19:39:02 -07003329 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303330 {
3331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003332 "Batch scan is not yet enabled batch scan state %d",
3333 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303334 ret = -EINVAL;
3335 goto exit;
3336 }
3337
Rajeev Kumar20140c12013-10-21 19:39:02 -07003338 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3339
Rajeev79dbe4c2013-10-05 11:03:42 +05303340 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3341 pAdapter->sessionId);
3342 if ( eHAL_STATUS_SUCCESS == halStatus )
3343 {
3344 ret = 0;
3345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3346 "sme_StopBatchScanInd returned success halStatus %d",
3347 halStatus);
3348 }
3349 else
3350 {
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3352 "sme_StopBatchScanInd returned failure halStatus %d",
3353 halStatus);
3354 ret = -EINVAL;
3355 goto exit;
3356 }
3357 }
3358 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3359 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003360 tANI_U32 remain_len;
3361
Rajeev79dbe4c2013-10-05 11:03:42 +05303362 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3363 {
3364 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3365 "%s: Batch scan feature is not supported by FW", __func__);
3366 ret = -EINVAL;
3367 goto exit;
3368 }
3369
Rajeev Kumar20140c12013-10-21 19:39:02 -07003370 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303371 {
3372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003373 "Batch scan is not yet enabled could not return results"
3374 "Batch Scan state %d",
3375 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303376 ret = -EINVAL;
3377 goto exit;
3378 }
3379
3380 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003381 remain_len = priv_data.total_len - priv_data.used_len;
3382 if (remain_len < priv_data.total_len)
3383 {
3384 /*Clear previous batch scan response data if any*/
3385 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3386 }
3387 else
3388 {
3389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3390 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003391 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003392 priv_data.total_len, priv_data.used_len, remain_len);
3393 ret = -EINVAL;
3394 goto exit;
3395 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303396 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3397 }
3398#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003399#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3400 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3401 {
3402 tANI_U8 *value = command;
3403 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3404 tANI_U8 numChannels = 0;
3405 eHalStatus status = eHAL_STATUS_SUCCESS;
3406
3407 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3408 if (eHAL_STATUS_SUCCESS != status)
3409 {
3410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3411 "%s: Failed to parse channel list information", __func__);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415
3416 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3417 {
3418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3419 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3420 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3421 ret = -EINVAL;
3422 goto exit;
3423 }
3424 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3425 ChannelList,
3426 numChannels);
3427 if (eHAL_STATUS_SUCCESS != status)
3428 {
3429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3430 "%s: Failed to update channel list information", __func__);
3431 ret = -EINVAL;
3432 goto exit;
3433 }
3434 }
3435 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3436 {
3437 tANI_U8 *value = command;
3438 char extra[128] = {0};
3439 int len = 0;
3440 tANI_U8 tid = 0;
3441 hdd_station_ctx_t *pHddStaCtx = NULL;
3442 tAniTrafStrmMetrics tsmMetrics;
3443 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3444
3445 /* if not associated, return error */
3446 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3447 {
3448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3449 ret = -EINVAL;
3450 goto exit;
3451 }
3452
3453 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3454 value = value + 12;
3455 /* Convert the value from ascii to integer */
3456 ret = kstrtou8(value, 10, &tid);
3457 if (ret < 0)
3458 {
3459 /* If the input value is greater than max value of datatype, then also
3460 kstrtou8 fails */
3461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3462 "%s: kstrtou8 failed range [%d - %d]", __func__,
3463 TID_MIN_VALUE,
3464 TID_MAX_VALUE);
3465 ret = -EINVAL;
3466 goto exit;
3467 }
3468
3469 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3470 {
3471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3472 "tid value %d is out of range"
3473 " (Min: %d Max: %d)", tid,
3474 TID_MIN_VALUE,
3475 TID_MAX_VALUE);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3481 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3482
3483 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3484 {
3485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3486 "%s: failed to get tsm stats", __func__);
3487 ret = -EFAULT;
3488 goto exit;
3489 }
3490
3491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3492 "UplinkPktQueueDly(%d)\n"
3493 "UplinkPktQueueDlyHist[0](%d)\n"
3494 "UplinkPktQueueDlyHist[1](%d)\n"
3495 "UplinkPktQueueDlyHist[2](%d)\n"
3496 "UplinkPktQueueDlyHist[3](%d)\n"
3497 "UplinkPktTxDly(%lu)\n"
3498 "UplinkPktLoss(%d)\n"
3499 "UplinkPktCount(%d)\n"
3500 "RoamingCount(%d)\n"
3501 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3502 tsmMetrics.UplinkPktQueueDlyHist[0],
3503 tsmMetrics.UplinkPktQueueDlyHist[1],
3504 tsmMetrics.UplinkPktQueueDlyHist[2],
3505 tsmMetrics.UplinkPktQueueDlyHist[3],
3506 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3507 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3508
3509 /* Output TSM stats is of the format
3510 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3511 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3512 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3513 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3514 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3515 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3516 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3517 tsmMetrics.RoamingDly);
3518
3519 if (copy_to_user(priv_data.buf, &extra, len + 1))
3520 {
3521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3522 "%s: failed to copy data to user buffer", __func__);
3523 ret = -EFAULT;
3524 goto exit;
3525 }
3526 }
3527 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3528 {
3529 tANI_U8 *value = command;
3530 tANI_U8 *cckmIe = NULL;
3531 tANI_U8 cckmIeLen = 0;
3532 eHalStatus status = eHAL_STATUS_SUCCESS;
3533
3534 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3535 if (eHAL_STATUS_SUCCESS != status)
3536 {
3537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3538 "%s: Failed to parse cckm ie data", __func__);
3539 ret = -EINVAL;
3540 goto exit;
3541 }
3542
3543 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3544 {
3545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3546 "%s: CCKM Ie input length is more than max[%d]", __func__,
3547 DOT11F_IE_RSN_MAX_LEN);
3548 if (NULL != cckmIe)
3549 {
3550 vos_mem_free(cckmIe);
3551 }
3552 ret = -EINVAL;
3553 goto exit;
3554 }
3555 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3556 if (NULL != cckmIe)
3557 {
3558 vos_mem_free(cckmIe);
3559 }
3560 }
3561#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003562 else {
3563 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3564 __func__, command);
3565 }
3566
Jeff Johnson295189b2012-06-20 16:38:30 -07003567 }
3568exit:
3569 if (command)
3570 {
3571 kfree(command);
3572 }
3573 return ret;
3574}
3575
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003576
3577
3578#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3579static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3580{
3581 struct statsContext *pStatsContext = NULL;
3582 hdd_adapter_t *pAdapter = NULL;
3583
3584 if (NULL == pContext)
3585 {
3586 hddLog(VOS_TRACE_LEVEL_ERROR,
3587 "%s: Bad param, pContext [%p]",
3588 __func__, pContext);
3589 return;
3590 }
3591
3592 /* there is a race condition that exists between this callback function
3593 and the caller since the caller could time out either before or
3594 while this code is executing. we'll assume the timeout hasn't
3595 occurred, but we'll verify that right before we save our work */
3596
3597 pStatsContext = pContext;
3598 pAdapter = pStatsContext->pAdapter;
3599 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3600 {
3601 /* the caller presumably timed out so there is nothing we can do */
3602 hddLog(VOS_TRACE_LEVEL_WARN,
3603 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3604 __func__, pAdapter, pStatsContext->magic);
3605 return;
3606 }
3607
3608 /* the race is on. caller could have timed out immediately after
3609 we verified the magic, but if so, caller will wait a short time
3610 for us to copy over the tsm stats */
3611 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3612 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3613 tsmMetrics.UplinkPktQueueDlyHist,
3614 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3615 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3616 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3617 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3618 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3619 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3620 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3621
3622 /* and notify the caller */
3623 complete(&pStatsContext->completion);
3624}
3625
3626
3627
3628static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3629 tAniTrafStrmMetrics* pTsmMetrics)
3630{
3631 hdd_station_ctx_t *pHddStaCtx = NULL;
3632 eHalStatus hstatus;
3633 long lrc;
3634 struct statsContext context;
3635 hdd_context_t *pHddCtx = NULL;
3636
3637 if (NULL == pAdapter)
3638 {
3639 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3640 return VOS_STATUS_E_FAULT;
3641 }
3642
3643 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3644 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3645
3646 /* we are connected prepare our callback context */
3647 init_completion(&context.completion);
3648 context.pAdapter = pAdapter;
3649 context.magic = STATS_CONTEXT_MAGIC;
3650
3651 /* query tsm stats */
3652 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3653 pHddStaCtx->conn_info.staId[ 0 ],
3654 pHddStaCtx->conn_info.bssId,
3655 &context, pHddCtx->pvosContext, tid);
3656
3657 if (eHAL_STATUS_SUCCESS != hstatus)
3658 {
3659 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3660 return hstatus;
3661 }
3662 else
3663 {
3664 /* request was sent -- wait for the response */
3665 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3666 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3667 /* either we have a response or we timed out
3668 either way, first invalidate our magic */
3669 context.magic = 0;
3670 if (lrc <= 0)
3671 {
3672 hddLog(VOS_TRACE_LEVEL_ERROR,
3673 "%s: SME %s while retrieving statistics",
3674 __func__, (0 == lrc) ? "timeout" : "interrupt");
3675 /* there is a race condition such that the callback
3676 function could be executing at the same time we are. of
3677 primary concern is if the callback function had already
3678 verified the "magic" but hasn't yet set the completion
3679 variable. Since the completion variable is on our
3680 stack, we'll delay just a bit to make sure the data is
3681 still valid if that is the case */
3682 msleep(50);
3683 return (VOS_STATUS_E_TIMEOUT);
3684 }
3685 }
3686 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3687 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3688 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3689 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3690 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3691 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3692 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3693 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3694 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3695 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3696
3697 return VOS_STATUS_SUCCESS;
3698}
3699#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3700
Srinivas Girigowdade697412013-02-14 16:31:48 -08003701#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3702void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3703{
3704 eCsrBand band = -1;
3705 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3706 switch (band)
3707 {
3708 case eCSR_BAND_ALL:
3709 *pBand = WLAN_HDD_UI_BAND_AUTO;
3710 break;
3711
3712 case eCSR_BAND_24:
3713 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3714 break;
3715
3716 case eCSR_BAND_5G:
3717 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3718 break;
3719
3720 default:
3721 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3722 *pBand = -1;
3723 break;
3724 }
3725}
3726
3727/**---------------------------------------------------------------------------
3728
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003729 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3730
3731 This function parses the send action frame data passed in the format
3732 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3733
Srinivas Girigowda56076852013-08-20 14:00:50 -07003734 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003735 \param - pTargetApBssid Pointer to target Ap bssid
3736 \param - pChannel Pointer to the Target AP channel
3737 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3738 \param - pBuf Pointer to data
3739 \param - pBufLen Pointer to data length
3740
3741 \return - 0 for success non-zero for failure
3742
3743 --------------------------------------------------------------------------*/
3744VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3745 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3746{
3747 tANI_U8 *inPtr = pValue;
3748 tANI_U8 *dataEnd;
3749 int tempInt;
3750 int j = 0;
3751 int i = 0;
3752 int v = 0;
3753 tANI_U8 tempBuf[32];
3754 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003755 /* 12 hexa decimal digits and 5 ':' */
3756 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003757
3758 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3759 /*no argument after the command*/
3760 if (NULL == inPtr)
3761 {
3762 return -EINVAL;
3763 }
3764
3765 /*no space after the command*/
3766 else if (SPACE_ASCII_VALUE != *inPtr)
3767 {
3768 return -EINVAL;
3769 }
3770
3771 /*removing empty spaces*/
3772 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3773
3774 /*no argument followed by spaces*/
3775 if ('\0' == *inPtr)
3776 {
3777 return -EINVAL;
3778 }
3779
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003780 v = sscanf(inPtr, "%17s", macAddress);
3781 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003782 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3784 "Invalid MAC address or All hex inputs are not read (%d)", v);
3785 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003786 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003787
3788 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3789 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3790 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3791 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3792 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3793 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003794
3795 /* point to the next argument */
3796 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3797 /*no argument after the command*/
3798 if (NULL == inPtr) return -EINVAL;
3799
3800 /*removing empty spaces*/
3801 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3802
3803 /*no argument followed by spaces*/
3804 if ('\0' == *inPtr)
3805 {
3806 return -EINVAL;
3807 }
3808
3809 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003810 v = sscanf(inPtr, "%32s ", tempBuf);
3811 if (1 != v) return -EINVAL;
3812
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003813 v = kstrtos32(tempBuf, 10, &tempInt);
3814 if ( v < 0) return -EINVAL;
3815
3816 *pChannel = tempInt;
3817
3818 /* point to the next argument */
3819 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3820 /*no argument after the command*/
3821 if (NULL == inPtr) return -EINVAL;
3822 /*removing empty spaces*/
3823 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3824
3825 /*no argument followed by spaces*/
3826 if ('\0' == *inPtr)
3827 {
3828 return -EINVAL;
3829 }
3830
3831 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003832 v = sscanf(inPtr, "%32s ", tempBuf);
3833 if (1 != v) return -EINVAL;
3834
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003835 v = kstrtos32(tempBuf, 10, &tempInt);
3836 if ( v < 0) return -EINVAL;
3837
3838 *pDwellTime = tempInt;
3839
3840 /* point to the next argument */
3841 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3842 /*no argument after the command*/
3843 if (NULL == inPtr) return -EINVAL;
3844 /*removing empty spaces*/
3845 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3846
3847 /*no argument followed by spaces*/
3848 if ('\0' == *inPtr)
3849 {
3850 return -EINVAL;
3851 }
3852
3853 /* find the length of data */
3854 dataEnd = inPtr;
3855 while(('\0' != *dataEnd) )
3856 {
3857 dataEnd++;
3858 ++(*pBufLen);
3859 }
3860 if ( *pBufLen <= 0) return -EINVAL;
3861
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003862 /* Allocate the number of bytes based on the number of input characters
3863 whether it is even or odd.
3864 if the number of input characters are even, then we need N/2 byte.
3865 if the number of input characters are odd, then we need do (N+1)/2 to
3866 compensate rounding off.
3867 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3868 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3869 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003870 if (NULL == *pBuf)
3871 {
3872 hddLog(VOS_TRACE_LEVEL_FATAL,
3873 "%s: vos_mem_alloc failed ", __func__);
3874 return -EINVAL;
3875 }
3876
3877 /* the buffer received from the upper layer is character buffer,
3878 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3879 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3880 and f0 in 3rd location */
3881 for (i = 0, j = 0; j < *pBufLen; j += 2)
3882 {
3883 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3884 (*pBuf)[i++] = tempByte;
3885 }
3886 *pBufLen = i;
3887 return VOS_STATUS_SUCCESS;
3888}
3889
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003890/**---------------------------------------------------------------------------
3891
Srinivas Girigowdade697412013-02-14 16:31:48 -08003892 \brief hdd_parse_channellist() - HDD Parse channel list
3893
3894 This function parses the channel list passed in the format
3895 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003896 if the Number of channels (N) does not match with the actual number of channels passed
3897 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3898 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3899 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3900 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003901
3902 \param - pValue Pointer to input channel list
3903 \param - ChannelList Pointer to local output array to record channel list
3904 \param - pNumChannels Pointer to number of roam scan channels
3905
3906 \return - 0 for success non-zero for failure
3907
3908 --------------------------------------------------------------------------*/
3909VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3910{
3911 tANI_U8 *inPtr = pValue;
3912 int tempInt;
3913 int j = 0;
3914 int v = 0;
3915 char buf[32];
3916
3917 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3918 /*no argument after the command*/
3919 if (NULL == inPtr)
3920 {
3921 return -EINVAL;
3922 }
3923
3924 /*no space after the command*/
3925 else if (SPACE_ASCII_VALUE != *inPtr)
3926 {
3927 return -EINVAL;
3928 }
3929
3930 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003931 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003932
3933 /*no argument followed by spaces*/
3934 if ('\0' == *inPtr)
3935 {
3936 return -EINVAL;
3937 }
3938
3939 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003940 v = sscanf(inPtr, "%32s ", buf);
3941 if (1 != v) return -EINVAL;
3942
Srinivas Girigowdade697412013-02-14 16:31:48 -08003943 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003944 if ((v < 0) ||
3945 (tempInt <= 0) ||
3946 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3947 {
3948 return -EINVAL;
3949 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003950
3951 *pNumChannels = tempInt;
3952
3953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3954 "Number of channels are: %d", *pNumChannels);
3955
3956 for (j = 0; j < (*pNumChannels); j++)
3957 {
3958 /*inPtr pointing to the beginning of first space after number of channels*/
3959 inPtr = strpbrk( inPtr, " " );
3960 /*no channel list after the number of channels argument*/
3961 if (NULL == inPtr)
3962 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003963 if (0 != j)
3964 {
3965 *pNumChannels = j;
3966 return VOS_STATUS_SUCCESS;
3967 }
3968 else
3969 {
3970 return -EINVAL;
3971 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003972 }
3973
3974 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003975 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003976
3977 /*no channel list after the number of channels argument and spaces*/
3978 if ( '\0' == *inPtr )
3979 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003980 if (0 != j)
3981 {
3982 *pNumChannels = j;
3983 return VOS_STATUS_SUCCESS;
3984 }
3985 else
3986 {
3987 return -EINVAL;
3988 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003989 }
3990
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003991 v = sscanf(inPtr, "%32s ", buf);
3992 if (1 != v) return -EINVAL;
3993
Srinivas Girigowdade697412013-02-14 16:31:48 -08003994 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003995 if ((v < 0) ||
3996 (tempInt <= 0) ||
3997 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3998 {
3999 return -EINVAL;
4000 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004001 pChannelList[j] = tempInt;
4002
4003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4004 "Channel %d added to preferred channel list",
4005 pChannelList[j] );
4006 }
4007
Srinivas Girigowdade697412013-02-14 16:31:48 -08004008 return VOS_STATUS_SUCCESS;
4009}
4010
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004011
4012/**---------------------------------------------------------------------------
4013
4014 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4015
4016 This function parses the reasoc command data passed in the format
4017 REASSOC<space><bssid><space><channel>
4018
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004019 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004020 \param - pTargetApBssid Pointer to target Ap bssid
4021 \param - pChannel Pointer to the Target AP channel
4022
4023 \return - 0 for success non-zero for failure
4024
4025 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004026VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4027 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004028{
4029 tANI_U8 *inPtr = pValue;
4030 int tempInt;
4031 int v = 0;
4032 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004033 /* 12 hexa decimal digits and 5 ':' */
4034 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004035
4036 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4037 /*no argument after the command*/
4038 if (NULL == inPtr)
4039 {
4040 return -EINVAL;
4041 }
4042
4043 /*no space after the command*/
4044 else if (SPACE_ASCII_VALUE != *inPtr)
4045 {
4046 return -EINVAL;
4047 }
4048
4049 /*removing empty spaces*/
4050 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4051
4052 /*no argument followed by spaces*/
4053 if ('\0' == *inPtr)
4054 {
4055 return -EINVAL;
4056 }
4057
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004058 v = sscanf(inPtr, "%17s", macAddress);
4059 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004060 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4062 "Invalid MAC address or All hex inputs are not read (%d)", v);
4063 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004064 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004065
4066 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4067 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4068 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4069 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4070 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4071 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004072
4073 /* point to the next argument */
4074 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4075 /*no argument after the command*/
4076 if (NULL == inPtr) return -EINVAL;
4077
4078 /*removing empty spaces*/
4079 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4080
4081 /*no argument followed by spaces*/
4082 if ('\0' == *inPtr)
4083 {
4084 return -EINVAL;
4085 }
4086
4087 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004088 v = sscanf(inPtr, "%32s ", tempBuf);
4089 if (1 != v) return -EINVAL;
4090
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004091 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004092 if ((v < 0) ||
4093 (tempInt <= 0) ||
4094 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4095 {
4096 return -EINVAL;
4097 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004098
4099 *pChannel = tempInt;
4100 return VOS_STATUS_SUCCESS;
4101}
4102
4103#endif
4104
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004105#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4106/**---------------------------------------------------------------------------
4107
4108 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4109
4110 This function parses the SETCCKM IE command
4111 SETCCKMIE<space><ie data>
4112
4113 \param - pValue Pointer to input data
4114 \param - pCckmIe Pointer to output cckm Ie
4115 \param - pCckmIeLen Pointer to output cckm ie length
4116
4117 \return - 0 for success non-zero for failure
4118
4119 --------------------------------------------------------------------------*/
4120VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4121 tANI_U8 *pCckmIeLen)
4122{
4123 tANI_U8 *inPtr = pValue;
4124 tANI_U8 *dataEnd;
4125 int j = 0;
4126 int i = 0;
4127 tANI_U8 tempByte = 0;
4128
4129 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4130 /*no argument after the command*/
4131 if (NULL == inPtr)
4132 {
4133 return -EINVAL;
4134 }
4135
4136 /*no space after the command*/
4137 else if (SPACE_ASCII_VALUE != *inPtr)
4138 {
4139 return -EINVAL;
4140 }
4141
4142 /*removing empty spaces*/
4143 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4144
4145 /*no argument followed by spaces*/
4146 if ('\0' == *inPtr)
4147 {
4148 return -EINVAL;
4149 }
4150
4151 /* find the length of data */
4152 dataEnd = inPtr;
4153 while(('\0' != *dataEnd) )
4154 {
4155 dataEnd++;
4156 ++(*pCckmIeLen);
4157 }
4158 if ( *pCckmIeLen <= 0) return -EINVAL;
4159
4160 /* Allocate the number of bytes based on the number of input characters
4161 whether it is even or odd.
4162 if the number of input characters are even, then we need N/2 byte.
4163 if the number of input characters are odd, then we need do (N+1)/2 to
4164 compensate rounding off.
4165 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4166 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4167 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4168 if (NULL == *pCckmIe)
4169 {
4170 hddLog(VOS_TRACE_LEVEL_FATAL,
4171 "%s: vos_mem_alloc failed ", __func__);
4172 return -EINVAL;
4173 }
4174 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4175 /* the buffer received from the upper layer is character buffer,
4176 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4177 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4178 and f0 in 3rd location */
4179 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4180 {
4181 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4182 (*pCckmIe)[i++] = tempByte;
4183 }
4184 *pCckmIeLen = i;
4185
4186 return VOS_STATUS_SUCCESS;
4187}
4188#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4189
Jeff Johnson295189b2012-06-20 16:38:30 -07004190/**---------------------------------------------------------------------------
4191
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004192 \brief hdd_is_valid_mac_address() - Validate MAC address
4193
4194 This function validates whether the given MAC address is valid or not
4195 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4196 where X is the hexa decimal digit character and separated by ':'
4197 This algorithm works even if MAC address is not separated by ':'
4198
4199 This code checks given input string mac contains exactly 12 hexadecimal digits.
4200 and a separator colon : appears in the input string only after
4201 an even number of hex digits.
4202
4203 \param - pMacAddr pointer to the input MAC address
4204 \return - 1 for valid and 0 for invalid
4205
4206 --------------------------------------------------------------------------*/
4207
4208v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4209{
4210 int xdigit = 0;
4211 int separator = 0;
4212 while (*pMacAddr)
4213 {
4214 if (isxdigit(*pMacAddr))
4215 {
4216 xdigit++;
4217 }
4218 else if (':' == *pMacAddr)
4219 {
4220 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4221 break;
4222
4223 ++separator;
4224 }
4225 else
4226 {
4227 separator = -1;
4228 /* Invalid MAC found */
4229 return 0;
4230 }
4231 ++pMacAddr;
4232 }
4233 return (xdigit == 12 && (separator == 5 || separator == 0));
4234}
4235
4236/**---------------------------------------------------------------------------
4237
Jeff Johnson295189b2012-06-20 16:38:30 -07004238 \brief hdd_open() - HDD Open function
4239
4240 This is called in response to ifconfig up
4241
4242 \param - dev Pointer to net_device structure
4243
4244 \return - 0 for success non-zero for failure
4245
4246 --------------------------------------------------------------------------*/
4247int hdd_open (struct net_device *dev)
4248{
4249 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4250 hdd_context_t *pHddCtx;
4251 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4252 VOS_STATUS status;
4253 v_BOOL_t in_standby = TRUE;
4254
4255 if (NULL == pAdapter)
4256 {
4257 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004258 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 return -ENODEV;
4260 }
4261
4262 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4263 if (NULL == pHddCtx)
4264 {
4265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004266 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004267 return -ENODEV;
4268 }
4269
4270 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4271 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4272 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004273 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4274 {
4275 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304276 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004277 in_standby = FALSE;
4278 break;
4279 }
4280 else
4281 {
4282 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4283 pAdapterNode = pNext;
4284 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004285 }
4286
4287 if (TRUE == in_standby)
4288 {
4289 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4290 {
4291 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4292 "wlan out of power save", __func__);
4293 return -EINVAL;
4294 }
4295 }
4296
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004297 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004298 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4299 {
4300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004301 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004302 /* Enable TX queues only when we are connected */
4303 netif_tx_start_all_queues(dev);
4304 }
4305
4306 return 0;
4307}
4308
4309int hdd_mon_open (struct net_device *dev)
4310{
4311 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4312
4313 if(pAdapter == NULL) {
4314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004315 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004316 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 }
4318
4319 netif_start_queue(dev);
4320
4321 return 0;
4322}
4323/**---------------------------------------------------------------------------
4324
4325 \brief hdd_stop() - HDD stop function
4326
4327 This is called in response to ifconfig down
4328
4329 \param - dev Pointer to net_device structure
4330
4331 \return - 0 for success non-zero for failure
4332
4333 --------------------------------------------------------------------------*/
4334
4335int hdd_stop (struct net_device *dev)
4336{
4337 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4338 hdd_context_t *pHddCtx;
4339 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4340 VOS_STATUS status;
4341 v_BOOL_t enter_standby = TRUE;
4342
4343 ENTER();
4344
4345 if (NULL == pAdapter)
4346 {
4347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004348 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004349 return -ENODEV;
4350 }
4351
4352 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4353 if (NULL == pHddCtx)
4354 {
4355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004356 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004357 return -ENODEV;
4358 }
4359
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004360 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4362 netif_tx_disable(pAdapter->dev);
4363 netif_carrier_off(pAdapter->dev);
4364
4365
4366 /* SoftAP ifaces should never go in power save mode
4367 making sure same here. */
4368 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4369 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004371 )
4372 {
4373 /* SoftAP mode, so return from here */
4374 EXIT();
4375 return 0;
4376 }
4377
4378 /* Find if any iface is up then
4379 if any iface is up then can't put device to sleep/ power save mode. */
4380 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4381 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4382 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004383 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4384 {
4385 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304386 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004387 enter_standby = FALSE;
4388 break;
4389 }
4390 else
4391 {
4392 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4393 pAdapterNode = pNext;
4394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 }
4396
4397 if (TRUE == enter_standby)
4398 {
4399 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4400 "entering standby", __func__);
4401 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4402 {
4403 /*log and return success*/
4404 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4405 "wlan in power save", __func__);
4406 }
4407 }
4408
4409 EXIT();
4410 return 0;
4411}
4412
4413/**---------------------------------------------------------------------------
4414
4415 \brief hdd_uninit() - HDD uninit function
4416
4417 This is called during the netdev unregister to uninitialize all data
4418associated with the device
4419
4420 \param - dev Pointer to net_device structure
4421
4422 \return - void
4423
4424 --------------------------------------------------------------------------*/
4425static void hdd_uninit (struct net_device *dev)
4426{
4427 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4428
4429 ENTER();
4430
4431 do
4432 {
4433 if (NULL == pAdapter)
4434 {
4435 hddLog(VOS_TRACE_LEVEL_FATAL,
4436 "%s: NULL pAdapter", __func__);
4437 break;
4438 }
4439
4440 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4441 {
4442 hddLog(VOS_TRACE_LEVEL_FATAL,
4443 "%s: Invalid magic", __func__);
4444 break;
4445 }
4446
4447 if (NULL == pAdapter->pHddCtx)
4448 {
4449 hddLog(VOS_TRACE_LEVEL_FATAL,
4450 "%s: NULL pHddCtx", __func__);
4451 break;
4452 }
4453
4454 if (dev != pAdapter->dev)
4455 {
4456 hddLog(VOS_TRACE_LEVEL_FATAL,
4457 "%s: Invalid device reference", __func__);
4458 /* we haven't validated all cases so let this go for now */
4459 }
4460
4461 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4462
4463 /* after uninit our adapter structure will no longer be valid */
4464 pAdapter->dev = NULL;
4465 pAdapter->magic = 0;
4466 } while (0);
4467
4468 EXIT();
4469}
4470
4471/**---------------------------------------------------------------------------
4472
4473 \brief hdd_release_firmware() -
4474
4475 This function calls the release firmware API to free the firmware buffer.
4476
4477 \param - pFileName Pointer to the File Name.
4478 pCtx - Pointer to the adapter .
4479
4480
4481 \return - 0 for success, non zero for failure
4482
4483 --------------------------------------------------------------------------*/
4484
4485VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4486{
4487 VOS_STATUS status = VOS_STATUS_SUCCESS;
4488 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4489 ENTER();
4490
4491
4492 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4493
4494 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4495
4496 if(pHddCtx->fw) {
4497 release_firmware(pHddCtx->fw);
4498 pHddCtx->fw = NULL;
4499 }
4500 else
4501 status = VOS_STATUS_E_FAILURE;
4502 }
4503 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4504 if(pHddCtx->nv) {
4505 release_firmware(pHddCtx->nv);
4506 pHddCtx->nv = NULL;
4507 }
4508 else
4509 status = VOS_STATUS_E_FAILURE;
4510
4511 }
4512
4513 EXIT();
4514 return status;
4515}
4516
4517/**---------------------------------------------------------------------------
4518
4519 \brief hdd_request_firmware() -
4520
4521 This function reads the firmware file using the request firmware
4522 API and returns the the firmware data and the firmware file size.
4523
4524 \param - pfileName - Pointer to the file name.
4525 - pCtx - Pointer to the adapter .
4526 - ppfw_data - Pointer to the pointer of the firmware data.
4527 - pSize - Pointer to the file size.
4528
4529 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4530
4531 --------------------------------------------------------------------------*/
4532
4533
4534VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4535{
4536 int status;
4537 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4538 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4539 ENTER();
4540
4541 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4542
4543 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4544
4545 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4546 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4547 __func__, pfileName);
4548 retval = VOS_STATUS_E_FAILURE;
4549 }
4550
4551 else {
4552 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4553 *pSize = pHddCtx->fw->size;
4554 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4555 __func__, *pSize);
4556 }
4557 }
4558 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4559
4560 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4561
4562 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4563 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4564 __func__, pfileName);
4565 retval = VOS_STATUS_E_FAILURE;
4566 }
4567
4568 else {
4569 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4570 *pSize = pHddCtx->nv->size;
4571 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4572 __func__, *pSize);
4573 }
4574 }
4575
4576 EXIT();
4577 return retval;
4578}
4579/**---------------------------------------------------------------------------
4580 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4581
4582 This is the function invoked by SME to inform the result of a full power
4583 request issued by HDD
4584
4585 \param - callbackcontext - Pointer to cookie
4586 status - result of request
4587
4588 \return - None
4589
4590--------------------------------------------------------------------------*/
4591void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4592{
4593 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4594
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004595 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004596 if(&pHddCtx->full_pwr_comp_var)
4597 {
4598 complete(&pHddCtx->full_pwr_comp_var);
4599 }
4600}
4601
4602/**---------------------------------------------------------------------------
4603
4604 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4605
4606 This is the function invoked by SME to inform the result of BMPS
4607 request issued by HDD
4608
4609 \param - callbackcontext - Pointer to cookie
4610 status - result of request
4611
4612 \return - None
4613
4614--------------------------------------------------------------------------*/
4615void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4616{
4617
4618 struct completion *completion_var = (struct completion*) callbackContext;
4619
4620 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4621 if(completion_var != NULL)
4622 {
4623 complete(completion_var);
4624 }
4625}
4626
4627/**---------------------------------------------------------------------------
4628
4629 \brief hdd_get_cfg_file_size() -
4630
4631 This function reads the configuration file using the request firmware
4632 API and returns the configuration file size.
4633
4634 \param - pCtx - Pointer to the adapter .
4635 - pFileName - Pointer to the file name.
4636 - pBufSize - Pointer to the buffer size.
4637
4638 \return - 0 for success, non zero for failure
4639
4640 --------------------------------------------------------------------------*/
4641
4642VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4643{
4644 int status;
4645 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4646
4647 ENTER();
4648
4649 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4650
4651 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4652 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4653 status = VOS_STATUS_E_FAILURE;
4654 }
4655 else {
4656 *pBufSize = pHddCtx->fw->size;
4657 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4658 release_firmware(pHddCtx->fw);
4659 pHddCtx->fw = NULL;
4660 }
4661
4662 EXIT();
4663 return VOS_STATUS_SUCCESS;
4664}
4665
4666/**---------------------------------------------------------------------------
4667
4668 \brief hdd_read_cfg_file() -
4669
4670 This function reads the configuration file using the request firmware
4671 API and returns the cfg data and the buffer size of the configuration file.
4672
4673 \param - pCtx - Pointer to the adapter .
4674 - pFileName - Pointer to the file name.
4675 - pBuffer - Pointer to the data buffer.
4676 - pBufSize - Pointer to the buffer size.
4677
4678 \return - 0 for success, non zero for failure
4679
4680 --------------------------------------------------------------------------*/
4681
4682VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4683 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4684{
4685 int status;
4686 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4687
4688 ENTER();
4689
4690 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4691
4692 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4693 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4694 return VOS_STATUS_E_FAILURE;
4695 }
4696 else {
4697 if(*pBufSize != pHddCtx->fw->size) {
4698 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4699 "file size", __func__);
4700 release_firmware(pHddCtx->fw);
4701 pHddCtx->fw = NULL;
4702 return VOS_STATUS_E_FAILURE;
4703 }
4704 else {
4705 if(pBuffer) {
4706 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4707 }
4708 release_firmware(pHddCtx->fw);
4709 pHddCtx->fw = NULL;
4710 }
4711 }
4712
4713 EXIT();
4714
4715 return VOS_STATUS_SUCCESS;
4716}
4717
4718/**---------------------------------------------------------------------------
4719
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 \brief hdd_set_mac_address() -
4721
4722 This function sets the user specified mac address using
4723 the command ifconfig wlanX hw ether <mac adress>.
4724
4725 \param - dev - Pointer to the net device.
4726 - addr - Pointer to the sockaddr.
4727 \return - 0 for success, non zero for failure
4728
4729 --------------------------------------------------------------------------*/
4730
4731static int hdd_set_mac_address(struct net_device *dev, void *addr)
4732{
4733 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4734 struct sockaddr *psta_mac_addr = addr;
4735 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4736
4737 ENTER();
4738
4739 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4740
4741#ifdef HDD_SESSIONIZE
4742 // set the MAC address though the STA ID CFG.
4743 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4744 (v_U8_t *)&pAdapter->macAddressCurrent,
4745 sizeof( pAdapter->macAddressCurrent ),
4746 hdd_set_mac_addr_cb, VOS_FALSE );
4747#endif
4748
4749 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4750
4751 EXIT();
4752 return halStatus;
4753}
4754
4755tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4756{
4757 int i;
4758 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4759 {
4760 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4761 break;
4762 }
4763
4764 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4765 return NULL;
4766
4767 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4768 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4769}
4770
4771void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4772{
4773 int i;
4774 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4775 {
4776 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4777 {
4778 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4779 break;
4780 }
4781 }
4782 return;
4783}
4784
4785#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4786 static struct net_device_ops wlan_drv_ops = {
4787 .ndo_open = hdd_open,
4788 .ndo_stop = hdd_stop,
4789 .ndo_uninit = hdd_uninit,
4790 .ndo_start_xmit = hdd_hard_start_xmit,
4791 .ndo_tx_timeout = hdd_tx_timeout,
4792 .ndo_get_stats = hdd_stats,
4793 .ndo_do_ioctl = hdd_ioctl,
4794 .ndo_set_mac_address = hdd_set_mac_address,
4795 .ndo_select_queue = hdd_select_queue,
4796#ifdef WLAN_FEATURE_PACKET_FILTERING
4797#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4798 .ndo_set_rx_mode = hdd_set_multicast_list,
4799#else
4800 .ndo_set_multicast_list = hdd_set_multicast_list,
4801#endif //LINUX_VERSION_CODE
4802#endif
4803 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004804 static struct net_device_ops wlan_mon_drv_ops = {
4805 .ndo_open = hdd_mon_open,
4806 .ndo_stop = hdd_stop,
4807 .ndo_uninit = hdd_uninit,
4808 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4809 .ndo_tx_timeout = hdd_tx_timeout,
4810 .ndo_get_stats = hdd_stats,
4811 .ndo_do_ioctl = hdd_ioctl,
4812 .ndo_set_mac_address = hdd_set_mac_address,
4813 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004814
4815#endif
4816
4817void hdd_set_station_ops( struct net_device *pWlanDev )
4818{
4819#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4820 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4821 pWlanDev->netdev_ops = &wlan_drv_ops;
4822#else
4823 pWlanDev->open = hdd_open;
4824 pWlanDev->stop = hdd_stop;
4825 pWlanDev->uninit = hdd_uninit;
4826 pWlanDev->hard_start_xmit = NULL;
4827 pWlanDev->tx_timeout = hdd_tx_timeout;
4828 pWlanDev->get_stats = hdd_stats;
4829 pWlanDev->do_ioctl = hdd_ioctl;
4830 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4831 pWlanDev->set_mac_address = hdd_set_mac_address;
4832#endif
4833}
4834
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004835static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004836{
4837 struct net_device *pWlanDev = NULL;
4838 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 /*
4840 * cfg80211 initialization and registration....
4841 */
4842 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4843
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 if(pWlanDev != NULL)
4845 {
4846
4847 //Save the pointer to the net_device in the HDD adapter
4848 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4849
Jeff Johnson295189b2012-06-20 16:38:30 -07004850 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4851
4852 pAdapter->dev = pWlanDev;
4853 pAdapter->pHddCtx = pHddCtx;
4854 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4855
4856 init_completion(&pAdapter->session_open_comp_var);
4857 init_completion(&pAdapter->session_close_comp_var);
4858 init_completion(&pAdapter->disconnect_comp_var);
4859 init_completion(&pAdapter->linkup_event_var);
4860 init_completion(&pAdapter->cancel_rem_on_chan_var);
4861 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004862#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4863 init_completion(&pAdapter->offchannel_tx_event);
4864#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004865 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004866#ifdef FEATURE_WLAN_TDLS
4867 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004868 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004869 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304870 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004871#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004872 init_completion(&pHddCtx->mc_sus_event_var);
4873 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304874 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004875 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004876 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004877
Rajeev79dbe4c2013-10-05 11:03:42 +05304878#ifdef FEATURE_WLAN_BATCH_SCAN
4879 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4880 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4881 pAdapter->pBatchScanRsp = NULL;
4882 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004883 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304884 mutex_init(&pAdapter->hdd_batch_scan_lock);
4885#endif
4886
Jeff Johnson295189b2012-06-20 16:38:30 -07004887 pAdapter->isLinkUpSvcNeeded = FALSE;
4888 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4889 //Init the net_device structure
4890 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4891
4892 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4893 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4894 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4895 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4896
4897 hdd_set_station_ops( pAdapter->dev );
4898
4899 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4901 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4902 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004903 /* set pWlanDev's parent to underlying device */
4904 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4905 }
4906
4907 return pAdapter;
4908}
4909
4910VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4911{
4912 struct net_device *pWlanDev = pAdapter->dev;
4913 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4914 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4915 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4916
4917 if( rtnl_lock_held )
4918 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004919 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004920 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4921 {
4922 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4923 return VOS_STATUS_E_FAILURE;
4924 }
4925 }
4926 if (register_netdevice(pWlanDev))
4927 {
4928 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4929 return VOS_STATUS_E_FAILURE;
4930 }
4931 }
4932 else
4933 {
4934 if(register_netdev(pWlanDev))
4935 {
4936 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4937 return VOS_STATUS_E_FAILURE;
4938 }
4939 }
4940 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4941
4942 return VOS_STATUS_SUCCESS;
4943}
4944
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004945static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004946{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004947 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004948
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004949 if (NULL == pAdapter)
4950 {
4951 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4952 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004953 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004954
4955 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4956 {
4957 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4958 return eHAL_STATUS_NOT_INITIALIZED;
4959 }
4960
4961 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4962
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004963#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004964 /* need to make sure all of our scheduled work has completed.
4965 * This callback is called from MC thread context, so it is safe to
4966 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004967 *
4968 * Even though this is called from MC thread context, if there is a faulty
4969 * work item in the system, that can hang this call forever. So flushing
4970 * this global work queue is not safe; and now we make sure that
4971 * individual work queues are stopped correctly. But the cancel work queue
4972 * is a GPL only API, so the proprietary version of the driver would still
4973 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004974 */
4975 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004976#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004977
4978 /* We can be blocked while waiting for scheduled work to be
4979 * flushed, and the adapter structure can potentially be freed, in
4980 * which case the magic will have been reset. So make sure the
4981 * magic is still good, and hence the adapter structure is still
4982 * valid, before signaling completion */
4983 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4984 {
4985 complete(&pAdapter->session_close_comp_var);
4986 }
4987
Jeff Johnson295189b2012-06-20 16:38:30 -07004988 return eHAL_STATUS_SUCCESS;
4989}
4990
4991VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4992{
4993 struct net_device *pWlanDev = pAdapter->dev;
4994 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4995 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4996 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4997 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4998 int rc = 0;
4999
5000 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005001 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 //Open a SME session for future operation
5003 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005004 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005005 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5006 {
5007 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005008 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 halStatus, halStatus );
5010 status = VOS_STATUS_E_FAILURE;
5011 goto error_sme_open;
5012 }
5013
5014 //Block on a completion variable. Can't wait forever though.
5015 rc = wait_for_completion_interruptible_timeout(
5016 &pAdapter->session_open_comp_var,
5017 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5018 if (!rc)
5019 {
5020 hddLog(VOS_TRACE_LEVEL_FATAL,
5021 "Session is not opened within timeout period code %08d", rc );
5022 status = VOS_STATUS_E_FAILURE;
5023 goto error_sme_open;
5024 }
5025
5026 // Register wireless extensions
5027 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5028 {
5029 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005030 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 halStatus, halStatus );
5032 status = VOS_STATUS_E_FAILURE;
5033 goto error_register_wext;
5034 }
5035 //Safe to register the hard_start_xmit function again
5036#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5037 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5038#else
5039 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5040#endif
5041
5042 //Set the Connection State to Not Connected
5043 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5044
5045 //Set the default operation channel
5046 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5047
5048 /* Make the default Auth Type as OPEN*/
5049 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5050
5051 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5052 {
5053 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005054 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 status, status );
5056 goto error_init_txrx;
5057 }
5058
5059 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5060
5061 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5062 {
5063 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005064 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 status, status );
5066 goto error_wmm_init;
5067 }
5068
5069 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5070
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005071#ifdef FEATURE_WLAN_TDLS
5072 if(0 != wlan_hdd_tdls_init(pAdapter))
5073 {
5074 status = VOS_STATUS_E_FAILURE;
5075 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5076 goto error_tdls_init;
5077 }
5078 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5079#endif
5080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 return VOS_STATUS_SUCCESS;
5082
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005083#ifdef FEATURE_WLAN_TDLS
5084error_tdls_init:
5085 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5086 hdd_wmm_adapter_close(pAdapter);
5087#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005088error_wmm_init:
5089 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5090 hdd_deinit_tx_rx(pAdapter);
5091error_init_txrx:
5092 hdd_UnregisterWext(pWlanDev);
5093error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005094 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 {
5096 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005097 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005099 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005100 {
5101 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005102 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005104 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 }
5106}
5107error_sme_open:
5108 return status;
5109}
5110
Jeff Johnson295189b2012-06-20 16:38:30 -07005111void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5112{
5113 hdd_cfg80211_state_t *cfgState;
5114
5115 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5116
5117 if( NULL != cfgState->buf )
5118 {
5119 int rc;
5120 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5121 rc = wait_for_completion_interruptible_timeout(
5122 &pAdapter->tx_action_cnf_event,
5123 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5124 if(!rc)
5125 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005126 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005127 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5128 }
5129 }
5130 return;
5131}
Jeff Johnson295189b2012-06-20 16:38:30 -07005132
5133void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5134{
5135 ENTER();
5136 switch ( pAdapter->device_mode )
5137 {
5138 case WLAN_HDD_INFRA_STATION:
5139 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005140 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005141 {
5142 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5143 {
5144 hdd_deinit_tx_rx( pAdapter );
5145 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5146 }
5147
5148 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5149 {
5150 hdd_wmm_adapter_close( pAdapter );
5151 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5152 }
5153
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005155#ifdef FEATURE_WLAN_TDLS
5156 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5157 {
5158 wlan_hdd_tdls_exit(pAdapter);
5159 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5160 }
5161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005162
5163 break;
5164 }
5165
5166 case WLAN_HDD_SOFTAP:
5167 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005168 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305169
5170 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5171 {
5172 hdd_wmm_adapter_close( pAdapter );
5173 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5174 }
5175
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005177
5178 hdd_unregister_hostapd(pAdapter);
5179 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 break;
5182 }
5183
5184 case WLAN_HDD_MONITOR:
5185 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5188 {
5189 hdd_deinit_tx_rx( pAdapter );
5190 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5191 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 if(NULL != pAdapterforTx)
5193 {
5194 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 break;
5197 }
5198
5199
5200 default:
5201 break;
5202 }
5203
5204 EXIT();
5205}
5206
5207void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5208{
5209 struct net_device *pWlanDev = pAdapter->dev;
5210
Rajeev79dbe4c2013-10-05 11:03:42 +05305211#ifdef FEATURE_WLAN_BATCH_SCAN
5212 tHddBatchScanRsp *pNode;
5213 tHddBatchScanRsp *pPrev;
5214 if (pAdapter)
5215 {
5216 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5217 pNode = pAdapter->pBatchScanRsp;
5218 while (pNode)
5219 {
5220 pPrev = pNode;
5221 pNode = pNode->pNext;
5222 vos_mem_free((v_VOID_t * )pPrev);
5223 }
5224 pAdapter->pBatchScanRsp = NULL;
5225 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5226 }
5227#endif
5228
Jeff Johnson295189b2012-06-20 16:38:30 -07005229 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5230 if( rtnl_held )
5231 {
5232 unregister_netdevice(pWlanDev);
5233 }
5234 else
5235 {
5236 unregister_netdev(pWlanDev);
5237 }
5238 // note that the pAdapter is no longer valid at this point
5239 // since the memory has been reclaimed
5240 }
5241
5242}
5243
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005244void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5245{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305246 VOS_STATUS status;
5247 hdd_adapter_t *pAdapter = NULL;
5248 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005249
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305250 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005251
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305252 /*loop through all adapters.*/
5253 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005254 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305255 pAdapter = pAdapterNode->pAdapter;
5256 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5257 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005258
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305259 { // we skip this registration for modes other than STA and P2P client modes.
5260 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5261 pAdapterNode = pNext;
5262 continue;
5263 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005264
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305265 //Apply Dynamic DTIM For P2P
5266 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5267 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5268 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5269 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5270 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5271 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5272 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5273 (eConnectionState_Associated ==
5274 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5275 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5276 {
5277 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005278
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305279 powerRequest.uIgnoreDTIM = 1;
5280 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5281
5282 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5283 {
5284 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5285 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5286 }
5287 else
5288 {
5289 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5290 }
5291
5292 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5293 * specified during Enter/Exit BMPS when LCD off*/
5294 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5295 NULL, eANI_BOOLEAN_FALSE);
5296 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5297 NULL, eANI_BOOLEAN_FALSE);
5298
5299 /* switch to the DTIM specified in cfg.ini */
5300 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5301 "Switch to DTIM %d", powerRequest.uListenInterval);
5302 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5303 break;
5304
5305 }
5306
5307 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5308 pAdapterNode = pNext;
5309 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005310}
5311
5312void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5313{
5314 /*Switch back to DTIM 1*/
5315 tSirSetPowerParamsReq powerRequest = { 0 };
5316
5317 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5318 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005319 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005320
5321 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5322 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5323 NULL, eANI_BOOLEAN_FALSE);
5324 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5325 NULL, eANI_BOOLEAN_FALSE);
5326
5327 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5328 "Switch to DTIM%d",powerRequest.uListenInterval);
5329 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5330
5331}
5332
Jeff Johnson295189b2012-06-20 16:38:30 -07005333VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5334{
5335 VOS_STATUS status = VOS_STATUS_SUCCESS;
5336
5337 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5338 {
5339 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5340 }
5341
5342 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5343 {
5344 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5345 }
5346
5347 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5348 {
5349 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5350 }
5351
5352 return status;
5353}
5354
5355VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5356{
5357 hdd_adapter_t *pAdapter = NULL;
5358 eHalStatus halStatus;
5359 VOS_STATUS status = VOS_STATUS_E_INVAL;
5360 v_BOOL_t disableBmps = FALSE;
5361 v_BOOL_t disableImps = FALSE;
5362
5363 switch(session_type)
5364 {
5365 case WLAN_HDD_INFRA_STATION:
5366 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005367 case WLAN_HDD_P2P_CLIENT:
5368 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005369 //Exit BMPS -> Is Sta/P2P Client is already connected
5370 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5371 if((NULL != pAdapter)&&
5372 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5373 {
5374 disableBmps = TRUE;
5375 }
5376
5377 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5378 if((NULL != pAdapter)&&
5379 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5380 {
5381 disableBmps = TRUE;
5382 }
5383
5384 //Exit both Bmps and Imps incase of Go/SAP Mode
5385 if((WLAN_HDD_SOFTAP == session_type) ||
5386 (WLAN_HDD_P2P_GO == session_type))
5387 {
5388 disableBmps = TRUE;
5389 disableImps = TRUE;
5390 }
5391
5392 if(TRUE == disableImps)
5393 {
5394 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5395 {
5396 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5397 }
5398 }
5399
5400 if(TRUE == disableBmps)
5401 {
5402 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5403 {
5404 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5405
5406 if(eHAL_STATUS_SUCCESS != halStatus)
5407 {
5408 status = VOS_STATUS_E_FAILURE;
5409 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5410 VOS_ASSERT(0);
5411 return status;
5412 }
5413 }
5414
5415 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5416 {
5417 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5418
5419 if(eHAL_STATUS_SUCCESS != halStatus)
5420 {
5421 status = VOS_STATUS_E_FAILURE;
5422 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5423 VOS_ASSERT(0);
5424 return status;
5425 }
5426 }
5427 }
5428
5429 if((TRUE == disableBmps) ||
5430 (TRUE == disableImps))
5431 {
5432 /* Now, get the chip into Full Power now */
5433 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5434 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5435 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5436
5437 if(halStatus != eHAL_STATUS_SUCCESS)
5438 {
5439 if(halStatus == eHAL_STATUS_PMC_PENDING)
5440 {
5441 //Block on a completion variable. Can't wait forever though
5442 wait_for_completion_interruptible_timeout(
5443 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5444 }
5445 else
5446 {
5447 status = VOS_STATUS_E_FAILURE;
5448 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5449 VOS_ASSERT(0);
5450 return status;
5451 }
5452 }
5453
5454 status = VOS_STATUS_SUCCESS;
5455 }
5456
5457 break;
5458 }
5459 return status;
5460}
5461
5462hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005463 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 tANI_U8 rtnl_held )
5465{
5466 hdd_adapter_t *pAdapter = NULL;
5467 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5468 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5469 VOS_STATUS exitbmpsStatus;
5470
5471 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5472
5473 //Disable BMPS incase of Concurrency
5474 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5475
5476 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5477 {
5478 //Fail to Exit BMPS
5479 VOS_ASSERT(0);
5480 return NULL;
5481 }
5482
5483 switch(session_type)
5484 {
5485 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005487 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 {
5489 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5490
5491 if( NULL == pAdapter )
5492 return NULL;
5493
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305494#ifdef FEATURE_WLAN_TDLS
5495 /* A Mutex Lock is introduced while changing/initializing the mode to
5496 * protect the concurrent access for the Adapters by TDLS module.
5497 */
5498 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5499 {
5500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5501 "%s: unable to lock list", __func__);
5502 return NULL;
5503 }
5504#endif
5505
Jeff Johnsone7245742012-09-05 17:12:55 -07005506 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5507 NL80211_IFTYPE_P2P_CLIENT:
5508 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005509
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 pAdapter->device_mode = session_type;
5511
5512 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305513#ifdef FEATURE_WLAN_TDLS
5514 mutex_unlock(&pHddCtx->tdls_lock);
5515#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005516 if( VOS_STATUS_SUCCESS != status )
5517 goto err_free_netdev;
5518
5519 status = hdd_register_interface( pAdapter, rtnl_held );
5520 if( VOS_STATUS_SUCCESS != status )
5521 {
5522 hdd_deinit_adapter(pHddCtx, pAdapter);
5523 goto err_free_netdev;
5524 }
5525 //Stop the Interface TX queue.
5526 netif_tx_disable(pAdapter->dev);
5527 //netif_tx_disable(pWlanDev);
5528 netif_carrier_off(pAdapter->dev);
5529
5530 break;
5531 }
5532
Jeff Johnson295189b2012-06-20 16:38:30 -07005533 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 case WLAN_HDD_SOFTAP:
5535 {
5536 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5537 if( NULL == pAdapter )
5538 return NULL;
5539
Jeff Johnson295189b2012-06-20 16:38:30 -07005540 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5541 NL80211_IFTYPE_AP:
5542 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 pAdapter->device_mode = session_type;
5544
5545 status = hdd_init_ap_mode(pAdapter);
5546 if( VOS_STATUS_SUCCESS != status )
5547 goto err_free_netdev;
5548
5549 status = hdd_register_hostapd( pAdapter, rtnl_held );
5550 if( VOS_STATUS_SUCCESS != status )
5551 {
5552 hdd_deinit_adapter(pHddCtx, pAdapter);
5553 goto err_free_netdev;
5554 }
5555
5556 netif_tx_disable(pAdapter->dev);
5557 netif_carrier_off(pAdapter->dev);
5558
5559 hdd_set_conparam( 1 );
5560 break;
5561 }
5562 case WLAN_HDD_MONITOR:
5563 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5565 if( NULL == pAdapter )
5566 return NULL;
5567
5568 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5569 pAdapter->device_mode = session_type;
5570 status = hdd_register_interface( pAdapter, rtnl_held );
5571#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5572 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5573#else
5574 pAdapter->dev->open = hdd_mon_open;
5575 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5576#endif
5577 hdd_init_tx_rx( pAdapter );
5578 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5579 //Set adapter to be used for data tx. It will use either GO or softap.
5580 pAdapter->sessionCtx.monitor.pAdapterForTx =
5581 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005582 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5583 {
5584 pAdapter->sessionCtx.monitor.pAdapterForTx =
5585 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5586 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 /* This workqueue will be used to transmit management packet over
5588 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005589 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5590 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5591 return NULL;
5592 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005593
Jeff Johnson295189b2012-06-20 16:38:30 -07005594 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5595 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 }
5597 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 case WLAN_HDD_FTM:
5599 {
5600 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5601
5602 if( NULL == pAdapter )
5603 return NULL;
5604 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5605 * message while loading driver in FTM mode. */
5606 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5607 pAdapter->device_mode = session_type;
5608 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305609
5610 hdd_init_tx_rx( pAdapter );
5611
5612 //Stop the Interface TX queue.
5613 netif_tx_disable(pAdapter->dev);
5614 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 }
5616 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005617 default:
5618 {
5619 VOS_ASSERT(0);
5620 return NULL;
5621 }
5622 }
5623
5624
5625 if( VOS_STATUS_SUCCESS == status )
5626 {
5627 //Add it to the hdd's session list.
5628 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5629 if( NULL == pHddAdapterNode )
5630 {
5631 status = VOS_STATUS_E_NOMEM;
5632 }
5633 else
5634 {
5635 pHddAdapterNode->pAdapter = pAdapter;
5636 status = hdd_add_adapter_back ( pHddCtx,
5637 pHddAdapterNode );
5638 }
5639 }
5640
5641 if( VOS_STATUS_SUCCESS != status )
5642 {
5643 if( NULL != pAdapter )
5644 {
5645 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5646 pAdapter = NULL;
5647 }
5648 if( NULL != pHddAdapterNode )
5649 {
5650 vos_mem_free( pHddAdapterNode );
5651 }
5652
5653 goto resume_bmps;
5654 }
5655
5656 if(VOS_STATUS_SUCCESS == status)
5657 {
5658 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5659
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005660 //Initialize the WoWL service
5661 if(!hdd_init_wowl(pAdapter))
5662 {
5663 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5664 goto err_free_netdev;
5665 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005666 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005667 return pAdapter;
5668
5669err_free_netdev:
5670 free_netdev(pAdapter->dev);
5671 wlan_hdd_release_intf_addr( pHddCtx,
5672 pAdapter->macAddressCurrent.bytes );
5673
5674resume_bmps:
5675 //If bmps disabled enable it
5676 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5677 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305678 if (pHddCtx->hdd_wlan_suspended)
5679 {
5680 hdd_set_pwrparams(pHddCtx);
5681 }
5682 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 }
5684 return NULL;
5685}
5686
5687VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5688 tANI_U8 rtnl_held )
5689{
5690 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5691 VOS_STATUS status;
5692
5693 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5694 if( VOS_STATUS_SUCCESS != status )
5695 return status;
5696
5697 while ( pCurrent->pAdapter != pAdapter )
5698 {
5699 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5700 if( VOS_STATUS_SUCCESS != status )
5701 break;
5702
5703 pCurrent = pNext;
5704 }
5705 pAdapterNode = pCurrent;
5706 if( VOS_STATUS_SUCCESS == status )
5707 {
5708 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5709 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305710
5711#ifdef FEATURE_WLAN_TDLS
5712
5713 /* A Mutex Lock is introduced while changing/initializing the mode to
5714 * protect the concurrent access for the Adapters by TDLS module.
5715 */
5716 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5717 {
5718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5719 "%s: unable to lock list", __func__);
5720 return VOS_STATUS_E_FAILURE;
5721 }
5722#endif
5723
Jeff Johnson295189b2012-06-20 16:38:30 -07005724 hdd_remove_adapter( pHddCtx, pAdapterNode );
5725 vos_mem_free( pAdapterNode );
5726
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305727#ifdef FEATURE_WLAN_TDLS
5728 mutex_unlock(&pHddCtx->tdls_lock);
5729#endif
5730
Jeff Johnson295189b2012-06-20 16:38:30 -07005731
5732 /* If there is a single session of STA/P2P client, re-enable BMPS */
5733 if ((!vos_concurrent_sessions_running()) &&
5734 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5735 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5736 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305737 if (pHddCtx->hdd_wlan_suspended)
5738 {
5739 hdd_set_pwrparams(pHddCtx);
5740 }
5741 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 }
5743
5744 return VOS_STATUS_SUCCESS;
5745 }
5746
5747 return VOS_STATUS_E_FAILURE;
5748}
5749
5750VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5751{
5752 hdd_adapter_list_node_t *pHddAdapterNode;
5753 VOS_STATUS status;
5754
5755 ENTER();
5756
5757 do
5758 {
5759 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5760 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5761 {
5762 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5763 vos_mem_free( pHddAdapterNode );
5764 }
5765 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5766
5767 EXIT();
5768
5769 return VOS_STATUS_SUCCESS;
5770}
5771
5772void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5773{
5774 v_U8_t addIE[1] = {0};
5775
5776 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5777 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5778 eANI_BOOLEAN_FALSE) )
5779 {
5780 hddLog(LOGE,
5781 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5782 }
5783
5784 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5785 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5786 eANI_BOOLEAN_FALSE) )
5787 {
5788 hddLog(LOGE,
5789 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5790 }
5791
5792 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5793 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5794 eANI_BOOLEAN_FALSE) )
5795 {
5796 hddLog(LOGE,
5797 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5798 }
5799}
5800
5801VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5802{
5803 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5804 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5805 union iwreq_data wrqu;
5806
5807 ENTER();
5808
5809 switch(pAdapter->device_mode)
5810 {
5811 case WLAN_HDD_INFRA_STATION:
5812 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005813 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5815 {
5816 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5817 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5818 pAdapter->sessionId,
5819 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5820 else
5821 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5822 pAdapter->sessionId,
5823 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5824 //success implies disconnect command got queued up successfully
5825 if(halStatus == eHAL_STATUS_SUCCESS)
5826 {
5827 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5828 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5829 }
5830 memset(&wrqu, '\0', sizeof(wrqu));
5831 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5832 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5833 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5834 }
5835 else
5836 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305837 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 }
5839
5840 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5841 {
5842 INIT_COMPLETION(pAdapter->session_close_comp_var);
5843 if (eHAL_STATUS_SUCCESS ==
5844 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5845 hdd_smeCloseSessionCallback, pAdapter))
5846 {
5847 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005848 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 &pAdapter->session_close_comp_var,
5850 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5851 }
5852 }
5853
5854 break;
5855
5856 case WLAN_HDD_SOFTAP:
5857 case WLAN_HDD_P2P_GO:
5858 //Any softap specific cleanup here...
5859 mutex_lock(&pHddCtx->sap_lock);
5860 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5861 {
5862 VOS_STATUS status;
5863 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5864
5865 //Stop Bss.
5866 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5867 if (VOS_IS_STATUS_SUCCESS(status))
5868 {
5869 hdd_hostapd_state_t *pHostapdState =
5870 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5871
5872 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5873
5874 if (!VOS_IS_STATUS_SUCCESS(status))
5875 {
5876 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005877 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 }
5879 }
5880 else
5881 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005882 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 }
5884 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5885
5886 if (eHAL_STATUS_FAILURE ==
5887 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5888 0, NULL, eANI_BOOLEAN_FALSE))
5889 {
5890 hddLog(LOGE,
5891 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005892 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005893 }
5894
5895 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5896 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5897 eANI_BOOLEAN_FALSE) )
5898 {
5899 hddLog(LOGE,
5900 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5901 }
5902
5903 // Reset WNI_CFG_PROBE_RSP Flags
5904 wlan_hdd_reset_prob_rspies(pAdapter);
5905 kfree(pAdapter->sessionCtx.ap.beacon);
5906 pAdapter->sessionCtx.ap.beacon = NULL;
5907 }
5908 mutex_unlock(&pHddCtx->sap_lock);
5909 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005910
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005912#ifdef WLAN_OPEN_SOURCE
5913 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
5914#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005916
Jeff Johnson295189b2012-06-20 16:38:30 -07005917 default:
5918 break;
5919 }
5920
5921 EXIT();
5922 return VOS_STATUS_SUCCESS;
5923}
5924
5925VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5926{
5927 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5928 VOS_STATUS status;
5929 hdd_adapter_t *pAdapter;
5930
5931 ENTER();
5932
5933 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5934
5935 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5936 {
5937 pAdapter = pAdapterNode->pAdapter;
5938 netif_tx_disable(pAdapter->dev);
5939 netif_carrier_off(pAdapter->dev);
5940
5941 hdd_stop_adapter( pHddCtx, pAdapter );
5942
5943 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5944 pAdapterNode = pNext;
5945 }
5946
5947 EXIT();
5948
5949 return VOS_STATUS_SUCCESS;
5950}
5951
5952VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5953{
5954 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5955 VOS_STATUS status;
5956 hdd_adapter_t *pAdapter;
5957
5958 ENTER();
5959
5960 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5961
5962 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5963 {
5964 pAdapter = pAdapterNode->pAdapter;
5965 netif_tx_disable(pAdapter->dev);
5966 netif_carrier_off(pAdapter->dev);
5967
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005968 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5969
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305971 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5972 {
5973 hdd_wmm_adapter_close( pAdapter );
5974 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005976
5977 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5978 pAdapterNode = pNext;
5979 }
5980
5981 EXIT();
5982
5983 return VOS_STATUS_SUCCESS;
5984}
5985
5986VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5987{
5988 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5989 VOS_STATUS status;
5990 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305991 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005992
5993 ENTER();
5994
5995 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5996
5997 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5998 {
5999 pAdapter = pAdapterNode->pAdapter;
6000
6001 switch(pAdapter->device_mode)
6002 {
6003 case WLAN_HDD_INFRA_STATION:
6004 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006005 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306006
6007 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6008
Jeff Johnson295189b2012-06-20 16:38:30 -07006009 hdd_init_station_mode(pAdapter);
6010 /* Open the gates for HDD to receive Wext commands */
6011 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006012 pHddCtx->scan_info.mScanPending = FALSE;
6013 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006014
6015 //Trigger the initial scan
6016 hdd_wlan_initial_scan(pAdapter);
6017
6018 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306019 if (eConnectionState_Associated == connState ||
6020 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006021 {
6022 union iwreq_data wrqu;
6023 memset(&wrqu, '\0', sizeof(wrqu));
6024 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6025 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6026 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006027 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 /* indicate disconnected event to nl80211 */
6030 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6031 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306033 else if (eConnectionState_Connecting == connState)
6034 {
6035 /*
6036 * Indicate connect failure to supplicant if we were in the
6037 * process of connecting
6038 */
6039 cfg80211_connect_result(pAdapter->dev, NULL,
6040 NULL, 0, NULL, 0,
6041 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6042 GFP_KERNEL);
6043 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 break;
6045
6046 case WLAN_HDD_SOFTAP:
6047 /* softAP can handle SSR */
6048 break;
6049
6050 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006052 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006053 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 break;
6055
6056 case WLAN_HDD_MONITOR:
6057 /* monitor interface start */
6058 break;
6059 default:
6060 break;
6061 }
6062
6063 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6064 pAdapterNode = pNext;
6065 }
6066
6067 EXIT();
6068
6069 return VOS_STATUS_SUCCESS;
6070}
6071
6072VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6073{
6074 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6075 hdd_adapter_t *pAdapter;
6076 VOS_STATUS status;
6077 v_U32_t roamId;
6078
6079 ENTER();
6080
6081 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6082
6083 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6084 {
6085 pAdapter = pAdapterNode->pAdapter;
6086
6087 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6088 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6089 {
6090 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6091 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6092
6093 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6094 init_completion(&pAdapter->disconnect_comp_var);
6095 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6096 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6097
6098 wait_for_completion_interruptible_timeout(
6099 &pAdapter->disconnect_comp_var,
6100 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6101
6102 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6103 pHddCtx->isAmpAllowed = VOS_FALSE;
6104 sme_RoamConnect(pHddCtx->hHal,
6105 pAdapter->sessionId, &(pWextState->roamProfile),
6106 &roamId);
6107 }
6108
6109 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6110 pAdapterNode = pNext;
6111 }
6112
6113 EXIT();
6114
6115 return VOS_STATUS_SUCCESS;
6116}
6117
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006118void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6119{
6120 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6121 VOS_STATUS status;
6122 hdd_adapter_t *pAdapter;
6123 hdd_station_ctx_t *pHddStaCtx;
6124 hdd_ap_ctx_t *pHddApCtx;
6125 hdd_hostapd_state_t * pHostapdState;
6126 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6127 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6128 const char *p2pMode = "DEV";
6129 const char *ccMode = "Standalone";
6130 int n;
6131
6132 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6133 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6134 {
6135 pAdapter = pAdapterNode->pAdapter;
6136 switch (pAdapter->device_mode) {
6137 case WLAN_HDD_INFRA_STATION:
6138 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6139 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6140 staChannel = pHddStaCtx->conn_info.operationChannel;
6141 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6142 }
6143 break;
6144 case WLAN_HDD_P2P_CLIENT:
6145 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6146 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6147 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6148 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6149 p2pMode = "CLI";
6150 }
6151 break;
6152 case WLAN_HDD_P2P_GO:
6153 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6154 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6155 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6156 p2pChannel = pHddApCtx->operatingChannel;
6157 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6158 }
6159 p2pMode = "GO";
6160 break;
6161 case WLAN_HDD_SOFTAP:
6162 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6163 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6164 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6165 apChannel = pHddApCtx->operatingChannel;
6166 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6167 }
6168 break;
6169 default:
6170 break;
6171 }
6172 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6173 pAdapterNode = pNext;
6174 }
6175 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6176 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6177 }
6178 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6179 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6180 if (p2pChannel > 0) {
6181 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6182 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6183 }
6184 if (apChannel > 0) {
6185 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6186 apChannel, MAC_ADDR_ARRAY(apBssid));
6187 }
6188
6189 if (p2pChannel > 0 && apChannel > 0) {
6190 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6191 }
6192}
6193
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006194bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006195{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006196 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006197}
6198
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006199/* Once SSR is disabled then it cannot be set. */
6200void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006201{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006202 if (HDD_SSR_DISABLED == isSsrRequired)
6203 return;
6204
Jeff Johnson295189b2012-06-20 16:38:30 -07006205 isSsrRequired = value;
6206}
6207
6208VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6209 hdd_adapter_list_node_t** ppAdapterNode)
6210{
6211 VOS_STATUS status;
6212 spin_lock(&pHddCtx->hddAdapters.lock);
6213 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6214 (hdd_list_node_t**) ppAdapterNode );
6215 spin_unlock(&pHddCtx->hddAdapters.lock);
6216 return status;
6217}
6218
6219VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6220 hdd_adapter_list_node_t* pAdapterNode,
6221 hdd_adapter_list_node_t** pNextAdapterNode)
6222{
6223 VOS_STATUS status;
6224 spin_lock(&pHddCtx->hddAdapters.lock);
6225 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6226 (hdd_list_node_t*) pAdapterNode,
6227 (hdd_list_node_t**)pNextAdapterNode );
6228
6229 spin_unlock(&pHddCtx->hddAdapters.lock);
6230 return status;
6231}
6232
6233VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6234 hdd_adapter_list_node_t* pAdapterNode)
6235{
6236 VOS_STATUS status;
6237 spin_lock(&pHddCtx->hddAdapters.lock);
6238 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6239 &pAdapterNode->node );
6240 spin_unlock(&pHddCtx->hddAdapters.lock);
6241 return status;
6242}
6243
6244VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6245 hdd_adapter_list_node_t** ppAdapterNode)
6246{
6247 VOS_STATUS status;
6248 spin_lock(&pHddCtx->hddAdapters.lock);
6249 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6250 (hdd_list_node_t**) ppAdapterNode );
6251 spin_unlock(&pHddCtx->hddAdapters.lock);
6252 return status;
6253}
6254
6255VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6256 hdd_adapter_list_node_t* pAdapterNode)
6257{
6258 VOS_STATUS status;
6259 spin_lock(&pHddCtx->hddAdapters.lock);
6260 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6261 (hdd_list_node_t*) pAdapterNode );
6262 spin_unlock(&pHddCtx->hddAdapters.lock);
6263 return status;
6264}
6265
6266VOS_STATUS hdd_add_adapter_front( 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_front ( &pHddCtx->hddAdapters,
6272 (hdd_list_node_t*) pAdapterNode );
6273 spin_unlock(&pHddCtx->hddAdapters.lock);
6274 return status;
6275}
6276
6277hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6278 tSirMacAddr macAddr )
6279{
6280 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6281 hdd_adapter_t *pAdapter;
6282 VOS_STATUS status;
6283
6284 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6285
6286 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6287 {
6288 pAdapter = pAdapterNode->pAdapter;
6289
6290 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6291 macAddr, sizeof(tSirMacAddr) ) )
6292 {
6293 return pAdapter;
6294 }
6295 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6296 pAdapterNode = pNext;
6297 }
6298
6299 return NULL;
6300
6301}
6302
6303hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6304{
6305 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6306 hdd_adapter_t *pAdapter;
6307 VOS_STATUS status;
6308
6309 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6310
6311 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6312 {
6313 pAdapter = pAdapterNode->pAdapter;
6314
6315 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6316 IFNAMSIZ ) )
6317 {
6318 return pAdapter;
6319 }
6320 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6321 pAdapterNode = pNext;
6322 }
6323
6324 return NULL;
6325
6326}
6327
6328hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6329{
6330 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6331 hdd_adapter_t *pAdapter;
6332 VOS_STATUS status;
6333
6334 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6335
6336 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6337 {
6338 pAdapter = pAdapterNode->pAdapter;
6339
6340 if( pAdapter && (mode == pAdapter->device_mode) )
6341 {
6342 return pAdapter;
6343 }
6344 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6345 pAdapterNode = pNext;
6346 }
6347
6348 return NULL;
6349
6350}
6351
6352//Remove this function later
6353hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6354{
6355 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6356 hdd_adapter_t *pAdapter;
6357 VOS_STATUS status;
6358
6359 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6360
6361 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6362 {
6363 pAdapter = pAdapterNode->pAdapter;
6364
6365 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6366 {
6367 return pAdapter;
6368 }
6369
6370 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6371 pAdapterNode = pNext;
6372 }
6373
6374 return NULL;
6375
6376}
6377
Jeff Johnson295189b2012-06-20 16:38:30 -07006378/**---------------------------------------------------------------------------
6379
6380 \brief hdd_set_monitor_tx_adapter() -
6381
6382 This API initializes the adapter to be used while transmitting on monitor
6383 adapter.
6384
6385 \param - pHddCtx - Pointer to the HDD context.
6386 pAdapter - Adapter that will used for TX. This can be NULL.
6387 \return - None.
6388 --------------------------------------------------------------------------*/
6389void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6390{
6391 hdd_adapter_t *pMonAdapter;
6392
6393 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6394
6395 if( NULL != pMonAdapter )
6396 {
6397 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6398 }
6399}
Jeff Johnson295189b2012-06-20 16:38:30 -07006400/**---------------------------------------------------------------------------
6401
6402 \brief hdd_select_queue() -
6403
6404 This API returns the operating channel of the requested device mode
6405
6406 \param - pHddCtx - Pointer to the HDD context.
6407 - mode - Device mode for which operating channel is required
6408 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6409 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6410 \return - channel number. "0" id the requested device is not found OR it is not connected.
6411 --------------------------------------------------------------------------*/
6412v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6413{
6414 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6415 VOS_STATUS status;
6416 hdd_adapter_t *pAdapter;
6417 v_U8_t operatingChannel = 0;
6418
6419 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6420
6421 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6422 {
6423 pAdapter = pAdapterNode->pAdapter;
6424
6425 if( mode == pAdapter->device_mode )
6426 {
6427 switch(pAdapter->device_mode)
6428 {
6429 case WLAN_HDD_INFRA_STATION:
6430 case WLAN_HDD_P2P_CLIENT:
6431 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6432 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6433 break;
6434 case WLAN_HDD_SOFTAP:
6435 case WLAN_HDD_P2P_GO:
6436 /*softap connection info */
6437 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6438 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6439 break;
6440 default:
6441 break;
6442 }
6443
6444 break; //Found the device of interest. break the loop
6445 }
6446
6447 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6448 pAdapterNode = pNext;
6449 }
6450 return operatingChannel;
6451}
6452
6453#ifdef WLAN_FEATURE_PACKET_FILTERING
6454/**---------------------------------------------------------------------------
6455
6456 \brief hdd_set_multicast_list() -
6457
6458 This used to set the multicast address list.
6459
6460 \param - dev - Pointer to the WLAN device.
6461 - skb - Pointer to OS packet (sk_buff).
6462 \return - success/fail
6463
6464 --------------------------------------------------------------------------*/
6465static void hdd_set_multicast_list(struct net_device *dev)
6466{
6467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006468 int mc_count;
6469 int i = 0;
6470 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306471
6472 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006473 {
6474 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306475 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 return;
6477 }
6478
6479 if (dev->flags & IFF_ALLMULTI)
6480 {
6481 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006482 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306483 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 }
6485 else
6486 {
6487 mc_count = netdev_mc_count(dev);
6488 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006489 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006490 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6491 {
6492 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006493 "%s: No free filter available; 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 return;
6496 }
6497
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306498 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006499
6500 netdev_for_each_mc_addr(ha, dev) {
6501 if (i == mc_count)
6502 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306503 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6504 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6505 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006506 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306507 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006508 i++;
6509 }
6510 }
6511 return;
6512}
6513#endif
6514
6515/**---------------------------------------------------------------------------
6516
6517 \brief hdd_select_queue() -
6518
6519 This function is registered with the Linux OS for network
6520 core to decide which queue to use first.
6521
6522 \param - dev - Pointer to the WLAN device.
6523 - skb - Pointer to OS packet (sk_buff).
6524 \return - ac, Queue Index/access category corresponding to UP in IP header
6525
6526 --------------------------------------------------------------------------*/
6527v_U16_t hdd_select_queue(struct net_device *dev,
6528 struct sk_buff *skb)
6529{
6530 return hdd_wmm_select_queue(dev, skb);
6531}
6532
6533
6534/**---------------------------------------------------------------------------
6535
6536 \brief hdd_wlan_initial_scan() -
6537
6538 This function triggers the initial scan
6539
6540 \param - pAdapter - Pointer to the HDD adapter.
6541
6542 --------------------------------------------------------------------------*/
6543void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6544{
6545 tCsrScanRequest scanReq;
6546 tCsrChannelInfo channelInfo;
6547 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006548 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6550
6551 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6552 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6553 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6554
6555 if(sme_Is11dSupported(pHddCtx->hHal))
6556 {
6557 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6558 if ( HAL_STATUS_SUCCESS( halStatus ) )
6559 {
6560 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6561 if( !scanReq.ChannelInfo.ChannelList )
6562 {
6563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6564 vos_mem_free(channelInfo.ChannelList);
6565 return;
6566 }
6567 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6568 channelInfo.numOfChannels);
6569 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6570 vos_mem_free(channelInfo.ChannelList);
6571 }
6572
6573 scanReq.scanType = eSIR_PASSIVE_SCAN;
6574 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6575 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6576 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6577 }
6578 else
6579 {
6580 scanReq.scanType = eSIR_ACTIVE_SCAN;
6581 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6582 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6583 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6584 }
6585
6586 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6587 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6588 {
6589 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6590 __func__, halStatus );
6591 }
6592
6593 if(sme_Is11dSupported(pHddCtx->hHal))
6594 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6595}
6596
6597struct fullPowerContext
6598{
6599 struct completion completion;
6600 unsigned int magic;
6601};
6602#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6603
6604/**---------------------------------------------------------------------------
6605
6606 \brief hdd_full_power_callback() - HDD full power callback function
6607
6608 This is the function invoked by SME to inform the result of a full power
6609 request issued by HDD
6610
6611 \param - callbackcontext - Pointer to cookie
6612 \param - status - result of request
6613
6614 \return - None
6615
6616 --------------------------------------------------------------------------*/
6617static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6618{
6619 struct fullPowerContext *pContext = callbackContext;
6620
6621 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306622 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006623
6624 if (NULL == callbackContext)
6625 {
6626 hddLog(VOS_TRACE_LEVEL_ERROR,
6627 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006628 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006629 return;
6630 }
6631
6632 /* there is a race condition that exists between this callback function
6633 and the caller since the caller could time out either before or
6634 while this code is executing. we'll assume the timeout hasn't
6635 occurred, but we'll verify that right before we save our work */
6636
6637 if (POWER_CONTEXT_MAGIC != pContext->magic)
6638 {
6639 /* the caller presumably timed out so there is nothing we can do */
6640 hddLog(VOS_TRACE_LEVEL_WARN,
6641 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006642 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006643 return;
6644 }
6645
6646 /* the race is on. caller could have timed out immediately after
6647 we verified the magic, but if so, caller will wait a short time
6648 for us to notify the caller, so the context will stay valid */
6649 complete(&pContext->completion);
6650}
6651
6652/**---------------------------------------------------------------------------
6653
6654 \brief hdd_wlan_exit() - HDD WLAN exit function
6655
6656 This is the driver exit point (invoked during rmmod)
6657
6658 \param - pHddCtx - Pointer to the HDD Context
6659
6660 \return - None
6661
6662 --------------------------------------------------------------------------*/
6663void hdd_wlan_exit(hdd_context_t *pHddCtx)
6664{
6665 eHalStatus halStatus;
6666 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6667 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306668 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006669 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006670 struct fullPowerContext powerContext;
6671 long lrc;
6672
6673 ENTER();
6674
Jeff Johnson88ba7742013-02-27 14:36:02 -08006675 if (VOS_FTM_MODE != hdd_get_conparam())
6676 {
6677 // Unloading, restart logic is no more required.
6678 wlan_hdd_restart_deinit(pHddCtx);
6679 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006680
Jeff Johnson295189b2012-06-20 16:38:30 -07006681 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006682 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006683 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006684 {
6685 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6686 WLAN_HDD_INFRA_STATION);
6687 if (pAdapter == NULL)
6688 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6689
6690 if (pAdapter != NULL)
6691 {
6692 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6693 hdd_UnregisterWext(pAdapter->dev);
6694 }
6695 }
6696 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006697
Jeff Johnson295189b2012-06-20 16:38:30 -07006698 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006699 {
6700 wlan_hdd_ftm_close(pHddCtx);
6701 goto free_hdd_ctx;
6702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006703 //Stop the Interface TX queue.
6704 //netif_tx_disable(pWlanDev);
6705 //netif_carrier_off(pWlanDev);
6706
Jeff Johnson295189b2012-06-20 16:38:30 -07006707 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6708 {
6709 pAdapter = hdd_get_adapter(pHddCtx,
6710 WLAN_HDD_SOFTAP);
6711 }
6712 else
6713 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006714 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006715 {
6716 pAdapter = hdd_get_adapter(pHddCtx,
6717 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006718 if (pAdapter == NULL)
6719 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006720 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006721 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006722 /* DeRegister with platform driver as client for Suspend/Resume */
6723 vosStatus = hddDeregisterPmOps(pHddCtx);
6724 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6725 {
6726 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6727 VOS_ASSERT(0);
6728 }
6729
6730 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6731 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6732 {
6733 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006735
6736 // Cancel any outstanding scan requests. We are about to close all
6737 // of our adapters, but an adapter structure is what SME passes back
6738 // to our callback function. Hence if there are any outstanding scan
6739 // requests then there is a race condition between when the adapter
6740 // is closed and when the callback is invoked. We try to resolve that
6741 // race condition here by canceling any outstanding scans before we
6742 // close the adapters.
6743 // Note that the scans may be cancelled in an asynchronous manner, so
6744 // ideally there needs to be some kind of synchronization. Rather than
6745 // introduce a new synchronization here, we will utilize the fact that
6746 // we are about to Request Full Power, and since that is synchronized,
6747 // the expectation is that by the time Request Full Power has completed,
6748 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006749 if (NULL != pAdapter)
6750 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6751 else
6752 hddLog(VOS_TRACE_LEVEL_ERROR,
6753 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006754
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006755 //Stop the traffic monitor timer
6756 if ( VOS_TIMER_STATE_RUNNING ==
6757 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6758 {
6759 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6760 }
6761
6762 // Destroy the traffic monitor timer
6763 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6764 &pHddCtx->tx_rx_trafficTmr)))
6765 {
6766 hddLog(VOS_TRACE_LEVEL_ERROR,
6767 "%s: Cannot deallocate Traffic monitor timer", __func__);
6768 }
6769
Jeff Johnson295189b2012-06-20 16:38:30 -07006770 //Disable IMPS/BMPS as we do not want the device to enter any power
6771 //save mode during shutdown
6772 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6773 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6774 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6775
6776 //Ensure that device is in full power as we will touch H/W during vos_Stop
6777 init_completion(&powerContext.completion);
6778 powerContext.magic = POWER_CONTEXT_MAGIC;
6779
6780 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6781 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6782
6783 if (eHAL_STATUS_SUCCESS != halStatus)
6784 {
6785 if (eHAL_STATUS_PMC_PENDING == halStatus)
6786 {
6787 /* request was sent -- wait for the response */
6788 lrc = wait_for_completion_interruptible_timeout(
6789 &powerContext.completion,
6790 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6791 /* either we have a response or we timed out
6792 either way, first invalidate our magic */
6793 powerContext.magic = 0;
6794 if (lrc <= 0)
6795 {
6796 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006797 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006798 /* there is a race condition such that the callback
6799 function could be executing at the same time we are. of
6800 primary concern is if the callback function had already
6801 verified the "magic" but hasn't yet set the completion
6802 variable. Since the completion variable is on our
6803 stack, we'll delay just a bit to make sure the data is
6804 still valid if that is the case */
6805 msleep(50);
6806 }
6807 }
6808 else
6809 {
6810 hddLog(VOS_TRACE_LEVEL_ERROR,
6811 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006812 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006813 VOS_ASSERT(0);
6814 /* continue -- need to clean up as much as possible */
6815 }
6816 }
6817
Yue Ma0d4891e2013-08-06 17:01:45 -07006818 hdd_debugfs_exit(pHddCtx);
6819
Jeff Johnson295189b2012-06-20 16:38:30 -07006820 // Unregister the Net Device Notifier
6821 unregister_netdevice_notifier(&hdd_netdev_notifier);
6822
Jeff Johnson295189b2012-06-20 16:38:30 -07006823 hdd_stop_all_adapters( pHddCtx );
6824
Jeff Johnson295189b2012-06-20 16:38:30 -07006825#ifdef WLAN_BTAMP_FEATURE
6826 vosStatus = WLANBAP_Stop(pVosContext);
6827 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6828 {
6829 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6830 "%s: Failed to stop BAP",__func__);
6831 }
6832#endif //WLAN_BTAMP_FEATURE
6833
6834 //Stop all the modules
6835 vosStatus = vos_stop( pVosContext );
6836 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6837 {
6838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6839 "%s: Failed to stop VOSS",__func__);
6840 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6841 }
6842
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 //Assert Deep sleep signal now to put Libra HW in lowest power state
6844 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6845 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6846
6847 //Vote off any PMIC voltage supplies
6848 vos_chipPowerDown(NULL, NULL, NULL);
6849
6850 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6851
Leo Chang59cdc7e2013-07-10 10:08:21 -07006852
Jeff Johnson295189b2012-06-20 16:38:30 -07006853 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006854 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006855
6856 //Close the scheduler before calling vos_close to make sure no thread is
6857 // scheduled after the each module close is called i.e after all the data
6858 // structures are freed.
6859 vosStatus = vos_sched_close( pVosContext );
6860 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6861 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6862 "%s: Failed to close VOSS Scheduler",__func__);
6863 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6864 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006865#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006866#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6867 /* Destroy the wake lock */
6868 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6869#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006870 /* Destroy the wake lock */
6871 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006872#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006873
6874 //Close VOSS
6875 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6876 vos_close(pVosContext);
6877
Jeff Johnson295189b2012-06-20 16:38:30 -07006878 //Close Watchdog
6879 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6880 vos_watchdog_close(pVosContext);
6881
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306882 //Clean up HDD Nlink Service
6883 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006884#ifdef WLAN_KD_READY_NOTIFIER
6885 nl_srv_exit(pHddCtx->ptt_pid);
6886#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306887 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006888#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306889
Jeff Johnson295189b2012-06-20 16:38:30 -07006890 /* Cancel the vote for XO Core ON.
6891 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6892 * exited at this point
6893 */
6894 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6895 " when WLAN is turned OFF\n");
6896 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6897 {
6898 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6899 " Not returning failure."
6900 " Power consumed will be high\n");
6901 }
6902
6903 hdd_close_all_adapters( pHddCtx );
6904
6905
6906 //Free up dynamically allocated members inside HDD Adapter
6907 kfree(pHddCtx->cfg_ini);
6908 pHddCtx->cfg_ini= NULL;
6909
6910 /* free the power on lock from platform driver */
6911 if (free_riva_power_on_lock("wlan"))
6912 {
6913 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6914 __func__);
6915 }
6916
Jeff Johnson88ba7742013-02-27 14:36:02 -08006917free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006918 /* FTM mode, WIPHY did not registered
6919 If un-register here, system crash will happen */
6920 if (VOS_FTM_MODE != hdd_get_conparam())
6921 {
6922 wiphy_unregister(wiphy) ;
6923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006925 if (hdd_is_ssr_required())
6926 {
6927 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006928 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006929 msleep(5000);
6930 }
6931 hdd_set_ssr_required (VOS_FALSE);
6932}
6933
6934
6935/**---------------------------------------------------------------------------
6936
6937 \brief hdd_update_config_from_nv() - Function to update the contents of
6938 the running configuration with parameters taken from NV storage
6939
6940 \param - pHddCtx - Pointer to the HDD global context
6941
6942 \return - VOS_STATUS_SUCCESS if successful
6943
6944 --------------------------------------------------------------------------*/
6945static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6946{
Jeff Johnson295189b2012-06-20 16:38:30 -07006947 v_BOOL_t itemIsValid = VOS_FALSE;
6948 VOS_STATUS status;
6949 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6950 v_U8_t macLoop;
6951
6952 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6953 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6954 if(status != VOS_STATUS_SUCCESS)
6955 {
6956 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6957 return VOS_STATUS_E_FAILURE;
6958 }
6959
6960 if (itemIsValid == VOS_TRUE)
6961 {
6962 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6963 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6964 VOS_MAX_CONCURRENCY_PERSONA);
6965 if(status != VOS_STATUS_SUCCESS)
6966 {
6967 /* Get MAC from NV fail, not update CFG info
6968 * INI MAC value will be used for MAC setting */
6969 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6970 return VOS_STATUS_E_FAILURE;
6971 }
6972
6973 /* If first MAC is not valid, treat all others are not valid
6974 * Then all MACs will be got from ini file */
6975 if(vos_is_macaddr_zero(&macFromNV[0]))
6976 {
6977 /* MAC address in NV file is not configured yet */
6978 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6979 return VOS_STATUS_E_INVAL;
6980 }
6981
6982 /* Get MAC address from NV, update CFG info */
6983 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6984 {
6985 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6986 {
6987 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6988 /* This MAC is not valid, skip it
6989 * This MAC will be got from ini file */
6990 }
6991 else
6992 {
6993 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6994 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6995 VOS_MAC_ADDR_SIZE);
6996 }
6997 }
6998 }
6999 else
7000 {
7001 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7002 return VOS_STATUS_E_FAILURE;
7003 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007004
Jeff Johnson295189b2012-06-20 16:38:30 -07007005
7006 return VOS_STATUS_SUCCESS;
7007}
7008
7009/**---------------------------------------------------------------------------
7010
7011 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7012
7013 \param - pAdapter - Pointer to the HDD
7014
7015 \return - None
7016
7017 --------------------------------------------------------------------------*/
7018VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7019{
7020 eHalStatus halStatus;
7021 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307022 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007023
Jeff Johnson295189b2012-06-20 16:38:30 -07007024
7025 // Send ready indication to the HDD. This will kick off the MAC
7026 // into a 'running' state and should kick off an initial scan.
7027 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7028 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7029 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307030 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007031 "code %08d [x%08x]",__func__, halStatus, halStatus );
7032 return VOS_STATUS_E_FAILURE;
7033 }
7034
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307035 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007036 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7037 // And RIVA will crash
7038 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7039 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307040 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7041 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7042
7043
Jeff Johnson295189b2012-06-20 16:38:30 -07007044 return VOS_STATUS_SUCCESS;
7045}
7046
Jeff Johnson295189b2012-06-20 16:38:30 -07007047/* wake lock APIs for HDD */
7048void hdd_prevent_suspend(void)
7049{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007050#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007052#else
7053 wcnss_prevent_suspend();
7054#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007055}
7056
7057void hdd_allow_suspend(void)
7058{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007059#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007060 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007061#else
7062 wcnss_allow_suspend();
7063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007064}
7065
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007066void hdd_allow_suspend_timeout(v_U32_t timeout)
7067{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007068#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007069 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007070#else
7071 /* Do nothing as there is no API in wcnss for timeout*/
7072#endif
7073}
7074
Jeff Johnson295189b2012-06-20 16:38:30 -07007075/**---------------------------------------------------------------------------
7076
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007077 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7078 information between Host and Riva
7079
7080 This function gets reported version of FW
7081 It also finds the version of Riva headers used to compile the host
7082 It compares the above two and prints a warning if they are different
7083 It gets the SW and HW version string
7084 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7085 indicating the features they support through a bitmap
7086
7087 \param - pHddCtx - Pointer to HDD context
7088
7089 \return - void
7090
7091 --------------------------------------------------------------------------*/
7092
7093void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7094{
7095
7096 tSirVersionType versionCompiled;
7097 tSirVersionType versionReported;
7098 tSirVersionString versionString;
7099 tANI_U8 fwFeatCapsMsgSupported = 0;
7100 VOS_STATUS vstatus;
7101
7102 /* retrieve and display WCNSS version information */
7103 do {
7104
7105 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7106 &versionCompiled);
7107 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7108 {
7109 hddLog(VOS_TRACE_LEVEL_FATAL,
7110 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007111 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007112 break;
7113 }
7114
7115 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7116 &versionReported);
7117 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7118 {
7119 hddLog(VOS_TRACE_LEVEL_FATAL,
7120 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007121 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007122 break;
7123 }
7124
7125 if ((versionCompiled.major != versionReported.major) ||
7126 (versionCompiled.minor != versionReported.minor) ||
7127 (versionCompiled.version != versionReported.version) ||
7128 (versionCompiled.revision != versionReported.revision))
7129 {
7130 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7131 "Host expected %u.%u.%u.%u\n",
7132 WLAN_MODULE_NAME,
7133 (int)versionReported.major,
7134 (int)versionReported.minor,
7135 (int)versionReported.version,
7136 (int)versionReported.revision,
7137 (int)versionCompiled.major,
7138 (int)versionCompiled.minor,
7139 (int)versionCompiled.version,
7140 (int)versionCompiled.revision);
7141 }
7142 else
7143 {
7144 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7145 WLAN_MODULE_NAME,
7146 (int)versionReported.major,
7147 (int)versionReported.minor,
7148 (int)versionReported.version,
7149 (int)versionReported.revision);
7150 }
7151
7152 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7153 versionString,
7154 sizeof(versionString));
7155 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7156 {
7157 hddLog(VOS_TRACE_LEVEL_FATAL,
7158 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007159 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007160 break;
7161 }
7162
7163 pr_info("%s: WCNSS software version %s\n",
7164 WLAN_MODULE_NAME, versionString);
7165
7166 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7167 versionString,
7168 sizeof(versionString));
7169 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7170 {
7171 hddLog(VOS_TRACE_LEVEL_FATAL,
7172 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007173 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007174 break;
7175 }
7176
7177 pr_info("%s: WCNSS hardware version %s\n",
7178 WLAN_MODULE_NAME, versionString);
7179
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007180 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7181 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007182 send the message only if it the riva is 1.1
7183 minor numbers for different riva branches:
7184 0 -> (1.0)Mainline Build
7185 1 -> (1.1)Mainline Build
7186 2->(1.04) Stability Build
7187 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007188 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007189 ((versionReported.minor>=1) && (versionReported.version>=1)))
7190 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7191 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007192
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007193 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007194 {
7195#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7196 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7197 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7198#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007199 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7200 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7201 {
7202 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7203 }
7204
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007205 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007206 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007207
7208 } while (0);
7209
7210}
7211
7212/**---------------------------------------------------------------------------
7213
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307214 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7215
7216 \param - pHddCtx - Pointer to the hdd context
7217
7218 \return - true if hardware supports 5GHz
7219
7220 --------------------------------------------------------------------------*/
7221static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7222{
7223 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7224 * then hardware support 5Ghz.
7225 */
7226 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7227 {
7228 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7229 return true;
7230 }
7231 else
7232 {
7233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7234 __func__);
7235 return false;
7236 }
7237}
7238
7239
7240/**---------------------------------------------------------------------------
7241
Jeff Johnson295189b2012-06-20 16:38:30 -07007242 \brief hdd_wlan_startup() - HDD init function
7243
7244 This is the driver startup code executed once a WLAN device has been detected
7245
7246 \param - dev - Pointer to the underlying device
7247
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007248 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007249
7250 --------------------------------------------------------------------------*/
7251
7252int hdd_wlan_startup(struct device *dev )
7253{
7254 VOS_STATUS status;
7255 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007256 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007257 hdd_context_t *pHddCtx = NULL;
7258 v_CONTEXT_t pVosContext= NULL;
7259#ifdef WLAN_BTAMP_FEATURE
7260 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7261 WLANBAP_ConfigType btAmpConfig;
7262 hdd_config_t *pConfig;
7263#endif
7264 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007265 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007266
7267 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 /*
7269 * cfg80211: wiphy allocation
7270 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307271 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007272
7273 if(wiphy == NULL)
7274 {
7275 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007276 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007277 }
7278
7279 pHddCtx = wiphy_priv(wiphy);
7280
Jeff Johnson295189b2012-06-20 16:38:30 -07007281 //Initialize the adapter context to zeros.
7282 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7283
Jeff Johnson295189b2012-06-20 16:38:30 -07007284 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007285 hdd_prevent_suspend();
7286 pHddCtx->isLoadUnloadInProgress = TRUE;
7287
7288 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7289
7290 /*Get vos context here bcoz vos_open requires it*/
7291 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7292
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007293 if(pVosContext == NULL)
7294 {
7295 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7296 goto err_free_hdd_context;
7297 }
7298
Jeff Johnson295189b2012-06-20 16:38:30 -07007299 //Save the Global VOSS context in adapter context for future.
7300 pHddCtx->pvosContext = pVosContext;
7301
7302 //Save the adapter context in global context for future.
7303 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7304
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 pHddCtx->parent_dev = dev;
7306
7307 init_completion(&pHddCtx->full_pwr_comp_var);
7308 init_completion(&pHddCtx->standby_comp_var);
7309 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007310 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007311 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307312 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007313
7314#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007315 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007316#else
7317 init_completion(&pHddCtx->driver_crda_req);
7318#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007319
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307320 spin_lock_init(&pHddCtx->schedScan_lock);
7321
Jeff Johnson295189b2012-06-20 16:38:30 -07007322 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7323
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307324#ifdef FEATURE_WLAN_TDLS
7325 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7326 * invoked by other instances also) to protect the concurrent
7327 * access for the Adapters by TDLS module.
7328 */
7329 mutex_init(&pHddCtx->tdls_lock);
7330#endif
7331
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307332 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007333 // Load all config first as TL config is needed during vos_open
7334 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7335 if(pHddCtx->cfg_ini == NULL)
7336 {
7337 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7338 goto err_free_hdd_context;
7339 }
7340
7341 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7342
7343 // Read and parse the qcom_cfg.ini file
7344 status = hdd_parse_config_ini( pHddCtx );
7345 if ( VOS_STATUS_SUCCESS != status )
7346 {
7347 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7348 __func__, WLAN_INI_FILE);
7349 goto err_config;
7350 }
7351
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307352 /* INI has been read, initialise the configuredMcastBcastFilter with
7353 * INI value as this will serve as the default value
7354 */
7355 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7356 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7357 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307358
7359 if (false == hdd_is_5g_supported(pHddCtx))
7360 {
7361 //5Ghz is not supported.
7362 if (1 != pHddCtx->cfg_ini->nBandCapability)
7363 {
7364 hddLog(VOS_TRACE_LEVEL_INFO,
7365 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7366 pHddCtx->cfg_ini->nBandCapability = 1;
7367 }
7368 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307369
7370 /* If SNR Monitoring is enabled, FW has to parse all beacons
7371 * for calcaluting and storing the average SNR, so set Nth beacon
7372 * filter to 1 to enable FW to parse all the beaocons
7373 */
7374 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7375 {
7376 /* The log level is deliberately set to WARN as overriding
7377 * nthBeaconFilter to 1 will increase power cosumption and this
7378 * might just prove helpful to detect the power issue.
7379 */
7380 hddLog(VOS_TRACE_LEVEL_WARN,
7381 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7382 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007384 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307385 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007386 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307387 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 {
7389 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307390 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7391 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007392 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007393
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007394 // Update VOS trace levels based upon the cfg.ini
7395 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7396 pHddCtx->cfg_ini->vosTraceEnableBAP);
7397 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7398 pHddCtx->cfg_ini->vosTraceEnableTL);
7399 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7400 pHddCtx->cfg_ini->vosTraceEnableWDI);
7401 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7402 pHddCtx->cfg_ini->vosTraceEnableHDD);
7403 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7404 pHddCtx->cfg_ini->vosTraceEnableSME);
7405 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7406 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307407 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7408 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007409 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7410 pHddCtx->cfg_ini->vosTraceEnableWDA);
7411 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7412 pHddCtx->cfg_ini->vosTraceEnableSYS);
7413 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7414 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007415 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7416 pHddCtx->cfg_ini->vosTraceEnableSAP);
7417 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7418 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007419
Jeff Johnson295189b2012-06-20 16:38:30 -07007420 // Update WDI trace levels based upon the cfg.ini
7421 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7422 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7423 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7424 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7425 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7426 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7427 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7428 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007429
Jeff Johnson88ba7742013-02-27 14:36:02 -08007430 if (VOS_FTM_MODE == hdd_get_conparam())
7431 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007432 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7433 {
7434 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7435 goto err_free_hdd_context;
7436 }
7437 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7438 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007440
Jeff Johnson88ba7742013-02-27 14:36:02 -08007441 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007442 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7443 {
7444 status = vos_watchdog_open(pVosContext,
7445 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7446
7447 if(!VOS_IS_STATUS_SUCCESS( status ))
7448 {
7449 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307450 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 }
7452 }
7453
7454 pHddCtx->isLogpInProgress = FALSE;
7455 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7456
Jeff Johnson295189b2012-06-20 16:38:30 -07007457 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7458 if(!VOS_IS_STATUS_SUCCESS(status))
7459 {
7460 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007461 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 }
7463
Amar Singhala49cbc52013-10-08 18:37:44 -07007464#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007465 /* initialize the NV module. This is required so that
7466 we can initialize the channel information in wiphy
7467 from the NV.bin data. The channel information in
7468 wiphy needs to be initialized before wiphy registration */
7469
7470 status = vos_nv_open();
7471 if (!VOS_IS_STATUS_SUCCESS(status))
7472 {
7473 /* NV module cannot be initialized */
7474 hddLog( VOS_TRACE_LEVEL_FATAL,
7475 "%s: vos_nv_open failed", __func__);
7476 goto err_clkvote;
7477 }
7478
7479 status = vos_init_wiphy_from_nv_bin();
7480 if (!VOS_IS_STATUS_SUCCESS(status))
7481 {
7482 /* NV module cannot be initialized */
7483 hddLog( VOS_TRACE_LEVEL_FATAL,
7484 "%s: vos_init_wiphy failed", __func__);
7485 goto err_vos_nv_close;
7486 }
7487
Amar Singhala49cbc52013-10-08 18:37:44 -07007488 /* registration of wiphy dev with cfg80211 */
7489 if (0 > wlan_hdd_cfg80211_register(wiphy))
7490 {
7491 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007492 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007493 }
7494#endif
7495
Jeff Johnson295189b2012-06-20 16:38:30 -07007496 status = vos_open( &pVosContext, 0);
7497 if ( !VOS_IS_STATUS_SUCCESS( status ))
7498 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007499 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007500 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007501 }
7502
Jeff Johnson295189b2012-06-20 16:38:30 -07007503 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7504
7505 if ( NULL == pHddCtx->hHal )
7506 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007508 goto err_vosclose;
7509 }
7510
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007511 status = vos_preStart( pHddCtx->pvosContext );
7512 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7513 {
7514 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7515 goto err_vosclose;
7516 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007517
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007518 /* Note that the vos_preStart() sequence triggers the cfg download.
7519 The cfg download must occur before we update the SME config
7520 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007521 status = hdd_set_sme_config( pHddCtx );
7522
7523 if ( VOS_STATUS_SUCCESS != status )
7524 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007525 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7526 goto err_vosclose;
7527 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007528
7529 //Initialize the WMM module
7530 status = hdd_wmm_init(pHddCtx);
7531 if (!VOS_IS_STATUS_SUCCESS(status))
7532 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007533 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007534 goto err_vosclose;
7535 }
7536
Jeff Johnson295189b2012-06-20 16:38:30 -07007537 /* In the integrated architecture we update the configuration from
7538 the INI file and from NV before vOSS has been started so that
7539 the final contents are available to send down to the cCPU */
7540
7541 // Apply the cfg.ini to cfg.dat
7542 if (FALSE == hdd_update_config_dat(pHddCtx))
7543 {
7544 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7545 goto err_vosclose;
7546 }
7547
7548 // Apply the NV to cfg.dat
7549 /* Prima Update MAC address only at here */
7550 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7551 {
7552#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7553 /* There was not a valid set of MAC Addresses in NV. See if the
7554 default addresses were modified by the cfg.ini settings. If so,
7555 we'll use them, but if not, we'll autogenerate a set of MAC
7556 addresses based upon the device serial number */
7557
7558 static const v_MACADDR_t default_address =
7559 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7560 unsigned int serialno;
7561 int i;
7562
7563 serialno = wcnss_get_serial_number();
7564 if ((0 != serialno) &&
7565 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7566 sizeof(default_address))))
7567 {
7568 /* cfg.ini has the default address, invoke autogen logic */
7569
7570 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7571 bytes of the serial number that can be used to generate
7572 the other 3 bytes of the MAC address. Mask off all but
7573 the lower 3 bytes (this will also make sure we don't
7574 overflow in the next step) */
7575 serialno &= 0x00FFFFFF;
7576
7577 /* we need a unique address for each session */
7578 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7579
7580 /* autogen all addresses */
7581 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7582 {
7583 /* start with the entire default address */
7584 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7585 /* then replace the lower 3 bytes */
7586 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7587 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7588 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7589
7590 serialno++;
7591 }
7592
7593 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7594 MAC_ADDRESS_STR,
7595 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7596 }
7597 else
7598#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7599 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007600 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007601 "%s: Invalid MAC address in NV, using MAC from ini file "
7602 MAC_ADDRESS_STR, __func__,
7603 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7604 }
7605 }
7606 {
7607 eHalStatus halStatus;
7608 // Set the MAC Address
7609 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7610 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7611 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7612 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7613
7614 if (!HAL_STATUS_SUCCESS( halStatus ))
7615 {
7616 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7617 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007618 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007619 }
7620 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007621
7622 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7623 Note: Firmware image will be read and downloaded inside vos_start API */
7624 status = vos_start( pHddCtx->pvosContext );
7625 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7626 {
7627 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7628 goto err_vosclose;
7629 }
7630
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007631 /* Exchange capability info between Host and FW and also get versioning info from FW */
7632 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007633
7634 status = hdd_post_voss_start_config( pHddCtx );
7635 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7636 {
7637 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7638 __func__);
7639 goto err_vosstop;
7640 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007641
7642#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307643 wlan_hdd_cfg80211_update_reg_info( wiphy );
7644
7645 /* registration of wiphy dev with cfg80211 */
7646 if (0 > wlan_hdd_cfg80211_register(wiphy))
7647 {
7648 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7649 goto err_vosstop;
7650 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007651#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007652
Jeff Johnson295189b2012-06-20 16:38:30 -07007653 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7654 {
7655 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7656 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7657 }
7658 else
7659 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007660 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7661 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7662 if (pAdapter != NULL)
7663 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307664 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307666 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7667 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7668 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007669
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307670 /* Generate the P2P Device Address. This consists of the device's
7671 * primary MAC address with the locally administered bit set.
7672 */
7673 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007674 }
7675 else
7676 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307677 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7678 if (p2p_dev_addr != NULL)
7679 {
7680 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7681 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7682 }
7683 else
7684 {
7685 hddLog(VOS_TRACE_LEVEL_FATAL,
7686 "%s: Failed to allocate mac_address for p2p_device",
7687 __func__);
7688 goto err_close_adapter;
7689 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007690 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007691
7692 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7693 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7694 if ( NULL == pP2pAdapter )
7695 {
7696 hddLog(VOS_TRACE_LEVEL_FATAL,
7697 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007698 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007699 goto err_close_adapter;
7700 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007701 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007703
7704 if( pAdapter == NULL )
7705 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007706 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7707 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007708 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007709
Jeff Johnson295189b2012-06-20 16:38:30 -07007710#ifdef WLAN_BTAMP_FEATURE
7711 vStatus = WLANBAP_Open(pVosContext);
7712 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7713 {
7714 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7715 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007716 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007717 }
7718
7719 vStatus = BSL_Init(pVosContext);
7720 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7721 {
7722 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7723 "%s: Failed to Init BSL",__func__);
7724 goto err_bap_close;
7725 }
7726 vStatus = WLANBAP_Start(pVosContext);
7727 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7728 {
7729 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7730 "%s: Failed to start TL",__func__);
7731 goto err_bap_close;
7732 }
7733
7734 pConfig = pHddCtx->cfg_ini;
7735 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7736 status = WLANBAP_SetConfig(&btAmpConfig);
7737
7738#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007739
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007740#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7741 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7742 {
7743 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7744 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7745 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7746 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7747 }
7748#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007749#ifdef FEATURE_WLAN_SCAN_PNO
7750 /*SME must send channel update configuration to RIVA*/
7751 sme_UpdateChannelConfig(pHddCtx->hHal);
7752#endif
7753
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 /* Register with platform driver as client for Suspend/Resume */
7755 status = hddRegisterPmOps(pHddCtx);
7756 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7757 {
7758 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7759#ifdef WLAN_BTAMP_FEATURE
7760 goto err_bap_stop;
7761#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007762 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007763#endif //WLAN_BTAMP_FEATURE
7764 }
7765
Yue Ma0d4891e2013-08-06 17:01:45 -07007766 /* Open debugfs interface */
7767 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7768 {
7769 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7770 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007771 }
7772
Jeff Johnson295189b2012-06-20 16:38:30 -07007773 /* Register TM level change handler function to the platform */
7774 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7775 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7776 {
7777 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7778 goto err_unregister_pmops;
7779 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007780
7781 /* register for riva power on lock to platform driver */
7782 if (req_riva_power_on_lock("wlan"))
7783 {
7784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7785 __func__);
7786 goto err_unregister_pmops;
7787 }
7788
Jeff Johnson295189b2012-06-20 16:38:30 -07007789 // register net device notifier for device change notification
7790 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7791
7792 if(ret < 0)
7793 {
7794 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7795 goto err_free_power_on_lock;
7796 }
7797
7798 //Initialize the nlink service
7799 if(nl_srv_init() != 0)
7800 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007802 goto err_reg_netdev;
7803 }
7804
Leo Chang4ce1cc52013-10-21 18:27:15 -07007805#ifdef WLAN_KD_READY_NOTIFIER
7806 pHddCtx->kd_nl_init = 1;
7807#endif /* WLAN_KD_READY_NOTIFIER */
7808
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 //Initialize the BTC service
7810 if(btc_activate_service(pHddCtx) != 0)
7811 {
7812 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7813 goto err_nl_srv;
7814 }
7815
7816#ifdef PTT_SOCK_SVC_ENABLE
7817 //Initialize the PTT service
7818 if(ptt_sock_activate_svc(pHddCtx) != 0)
7819 {
7820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7821 goto err_nl_srv;
7822 }
7823#endif
7824
Jeff Johnson295189b2012-06-20 16:38:30 -07007825 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007826 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007827 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007828 /* Action frame registered in one adapter which will
7829 * applicable to all interfaces
7830 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007831 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007833
7834 mutex_init(&pHddCtx->sap_lock);
7835
7836 pHddCtx->isLoadUnloadInProgress = FALSE;
7837
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007838#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007839#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7840 /* Initialize the wake lcok */
7841 wake_lock_init(&pHddCtx->rx_wake_lock,
7842 WAKE_LOCK_SUSPEND,
7843 "qcom_rx_wakelock");
7844#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007845 /* Initialize the wake lcok */
7846 wake_lock_init(&pHddCtx->sap_wake_lock,
7847 WAKE_LOCK_SUSPEND,
7848 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007849#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007850
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007851 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7852 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007853
7854 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7855 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307856
Jeff Johnsone7245742012-09-05 17:12:55 -07007857 // Initialize the restart logic
7858 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307859
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007860 //Register the traffic monitor timer now
7861 if ( pHddCtx->cfg_ini->dynSplitscan)
7862 {
7863 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7864 VOS_TIMER_TYPE_SW,
7865 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7866 (void *)pHddCtx);
7867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007868 goto success;
7869
7870err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007871#ifdef WLAN_KD_READY_NOTIFIER
7872 nl_srv_exit(pHddCtx->ptt_pid);
7873#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007874 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007875#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007876err_reg_netdev:
7877 unregister_netdevice_notifier(&hdd_netdev_notifier);
7878
7879err_free_power_on_lock:
7880 free_riva_power_on_lock("wlan");
7881
7882err_unregister_pmops:
7883 hddDevTmUnregisterNotifyCallback(pHddCtx);
7884 hddDeregisterPmOps(pHddCtx);
7885
Yue Ma0d4891e2013-08-06 17:01:45 -07007886 hdd_debugfs_exit(pHddCtx);
7887
Jeff Johnson295189b2012-06-20 16:38:30 -07007888#ifdef WLAN_BTAMP_FEATURE
7889err_bap_stop:
7890 WLANBAP_Stop(pVosContext);
7891#endif
7892
7893#ifdef WLAN_BTAMP_FEATURE
7894err_bap_close:
7895 WLANBAP_Close(pVosContext);
7896#endif
7897
Jeff Johnson295189b2012-06-20 16:38:30 -07007898err_close_adapter:
7899 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007900
7901#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307902 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007903#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007904
7905err_vosstop:
7906 vos_stop(pVosContext);
7907
Amar Singhala49cbc52013-10-08 18:37:44 -07007908err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007909 status = vos_sched_close( pVosContext );
7910 if (!VOS_IS_STATUS_SUCCESS(status)) {
7911 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7912 "%s: Failed to close VOSS Scheduler", __func__);
7913 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7914 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007915 vos_close(pVosContext );
7916
7917err_wiphy_unregister:
7918
7919#ifdef CONFIG_ENABLE_LINUX_REG
7920 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007921
Amar Singhal0a402232013-10-11 20:57:16 -07007922err_vos_nv_close:
7923
7924 vos_nv_close();
7925
Jeff Johnson295189b2012-06-20 16:38:30 -07007926err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007927#endif
7928
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007929 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007930
7931err_wdclose:
7932 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7933 vos_watchdog_close(pVosContext);
7934
Jeff Johnson295189b2012-06-20 16:38:30 -07007935err_config:
7936 kfree(pHddCtx->cfg_ini);
7937 pHddCtx->cfg_ini= NULL;
7938
7939err_free_hdd_context:
7940 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007941 wiphy_free(wiphy) ;
7942 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007943 VOS_BUG(1);
7944
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007945 if (hdd_is_ssr_required())
7946 {
7947 /* WDI timeout had happened during load, so SSR is needed here */
7948 subsystem_restart("wcnss");
7949 msleep(5000);
7950 }
7951 hdd_set_ssr_required (VOS_FALSE);
7952
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007953 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007954
7955success:
7956 EXIT();
7957 return 0;
7958}
7959
7960/**---------------------------------------------------------------------------
7961
Jeff Johnson32d95a32012-09-10 13:15:23 -07007962 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007963
Jeff Johnson32d95a32012-09-10 13:15:23 -07007964 This is the driver entry point - called in different timeline depending
7965 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007966
7967 \param - None
7968
7969 \return - 0 for success, non zero for failure
7970
7971 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007972static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007973{
7974 VOS_STATUS status;
7975 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007976 struct device *dev = NULL;
7977 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007978#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7979 int max_retries = 0;
7980#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007981
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307982#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7983 vos_wconn_trace_init();
7984#endif
7985
Jeff Johnson295189b2012-06-20 16:38:30 -07007986 ENTER();
7987
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007988#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007989 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007990#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007991
7992 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7993 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7994
7995 //Power Up Libra WLAN card first if not already powered up
7996 status = vos_chipPowerUp(NULL,NULL,NULL);
7997 if (!VOS_IS_STATUS_SUCCESS(status))
7998 {
7999 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8000 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308001#ifdef WLAN_OPEN_SOURCE
8002 wake_lock_destroy(&wlan_wake_lock);
8003#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008004 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 }
8006
Jeff Johnson295189b2012-06-20 16:38:30 -07008007#ifdef ANI_BUS_TYPE_PCI
8008
8009 dev = wcnss_wlan_get_device();
8010
8011#endif // ANI_BUS_TYPE_PCI
8012
8013#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008014
8015#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8016 /* wait until WCNSS driver downloads NV */
8017 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8018 msleep(1000);
8019 }
8020 if (max_retries >= 5) {
8021 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308022#ifdef WLAN_OPEN_SOURCE
8023 wake_lock_destroy(&wlan_wake_lock);
8024#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008025 return -ENODEV;
8026 }
8027#endif
8028
Jeff Johnson295189b2012-06-20 16:38:30 -07008029 dev = wcnss_wlan_get_device();
8030#endif // ANI_BUS_TYPE_PLATFORM
8031
8032
8033 do {
8034 if (NULL == dev) {
8035 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8036 ret_status = -1;
8037 break;
8038 }
8039
8040#ifdef MEMORY_DEBUG
8041 vos_mem_init();
8042#endif
8043
8044#ifdef TIMER_MANAGER
8045 vos_timer_manager_init();
8046#endif
8047
8048 /* Preopen VOSS so that it is ready to start at least SAL */
8049 status = vos_preOpen(&pVosContext);
8050
8051 if (!VOS_IS_STATUS_SUCCESS(status))
8052 {
8053 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8054 ret_status = -1;
8055 break;
8056 }
8057
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008058#ifndef MODULE
8059 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8060 */
8061 hdd_set_conparam((v_UINT_t)con_mode);
8062#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008063
8064 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008065 if (hdd_wlan_startup(dev))
8066 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008068 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008069 vos_preClose( &pVosContext );
8070 ret_status = -1;
8071 break;
8072 }
8073
8074 /* Cancel the vote for XO Core ON
8075 * This is done here for safety purposes in case we re-initialize without turning
8076 * it OFF in any error scenario.
8077 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008078 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008079 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008080 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008081 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8082 {
8083 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8084 " Power consumed will be high\n");
8085 }
8086 } while (0);
8087
8088 if (0 != ret_status)
8089 {
8090 //Assert Deep sleep signal now to put Libra HW in lowest power state
8091 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8092 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8093
8094 //Vote off any PMIC voltage supplies
8095 vos_chipPowerDown(NULL, NULL, NULL);
8096#ifdef TIMER_MANAGER
8097 vos_timer_exit();
8098#endif
8099#ifdef MEMORY_DEBUG
8100 vos_mem_exit();
8101#endif
8102
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008103#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008104 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008105#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008106 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8107 }
8108 else
8109 {
8110 //Send WLAN UP indication to Nlink Service
8111 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8112
8113 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008114 }
8115
8116 EXIT();
8117
8118 return ret_status;
8119}
8120
Jeff Johnson32d95a32012-09-10 13:15:23 -07008121/**---------------------------------------------------------------------------
8122
8123 \brief hdd_module_init() - Init Function
8124
8125 This is the driver entry point (invoked when module is loaded using insmod)
8126
8127 \param - None
8128
8129 \return - 0 for success, non zero for failure
8130
8131 --------------------------------------------------------------------------*/
8132#ifdef MODULE
8133static int __init hdd_module_init ( void)
8134{
8135 return hdd_driver_init();
8136}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008137#else /* #ifdef MODULE */
8138static int __init hdd_module_init ( void)
8139{
8140 /* Driver initialization is delayed to fwpath_changed_handler */
8141 return 0;
8142}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008143#endif /* #ifdef MODULE */
8144
Jeff Johnson295189b2012-06-20 16:38:30 -07008145
8146/**---------------------------------------------------------------------------
8147
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008148 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008149
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008150 This is the driver exit point (invoked when module is unloaded using rmmod
8151 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008152
8153 \param - None
8154
8155 \return - None
8156
8157 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008158static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008159{
8160 hdd_context_t *pHddCtx = NULL;
8161 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008162 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008163
8164 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8165
8166 //Get the global vos context
8167 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8168
8169 if(!pVosContext)
8170 {
8171 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8172 goto done;
8173 }
8174
8175 //Get the HDD context.
8176 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8177
8178 if(!pHddCtx)
8179 {
8180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8181 }
8182 else
8183 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008184 while(isWDresetInProgress()) {
8185 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8186 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008187 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008188
8189 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8190 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8191 "%s:SSR never completed, fatal error", __func__);
8192 VOS_BUG(0);
8193 }
8194 }
8195
Jeff Johnson295189b2012-06-20 16:38:30 -07008196
8197 pHddCtx->isLoadUnloadInProgress = TRUE;
8198 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8199
8200 //Do all the cleanup before deregistering the driver
8201 hdd_wlan_exit(pHddCtx);
8202 }
8203
Jeff Johnson295189b2012-06-20 16:38:30 -07008204 vos_preClose( &pVosContext );
8205
8206#ifdef TIMER_MANAGER
8207 vos_timer_exit();
8208#endif
8209#ifdef MEMORY_DEBUG
8210 vos_mem_exit();
8211#endif
8212
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308213#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8214 vos_wconn_trace_exit();
8215#endif
8216
Jeff Johnson295189b2012-06-20 16:38:30 -07008217done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008218#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008219 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008220#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008221 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8222}
8223
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008224/**---------------------------------------------------------------------------
8225
8226 \brief hdd_module_exit() - Exit function
8227
8228 This is the driver exit point (invoked when module is unloaded using rmmod)
8229
8230 \param - None
8231
8232 \return - None
8233
8234 --------------------------------------------------------------------------*/
8235static void __exit hdd_module_exit(void)
8236{
8237 hdd_driver_exit();
8238}
8239
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008240#ifdef MODULE
8241static int fwpath_changed_handler(const char *kmessage,
8242 struct kernel_param *kp)
8243{
Jeff Johnson76052702013-04-16 13:55:05 -07008244 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008245}
8246
8247static int con_mode_handler(const char *kmessage,
8248 struct kernel_param *kp)
8249{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008250 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008251}
8252#else /* #ifdef MODULE */
8253/**---------------------------------------------------------------------------
8254
Jeff Johnson76052702013-04-16 13:55:05 -07008255 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008256
Jeff Johnson76052702013-04-16 13:55:05 -07008257 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008258 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008259 - invoked when module parameter fwpath is modified from userspace to signal
8260 initializing the WLAN driver or when con_mode is modified from userspace
8261 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008262
8263 \return - 0 for success, non zero for failure
8264
8265 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008266static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008267{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008268 int ret_status;
8269
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008270 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008271 ret_status = hdd_driver_init();
8272 wlan_hdd_inited = ret_status ? 0 : 1;
8273 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008274 }
8275
8276 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008277
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008278 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008279
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008280 ret_status = hdd_driver_init();
8281 wlan_hdd_inited = ret_status ? 0 : 1;
8282 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008283}
8284
Jeff Johnson295189b2012-06-20 16:38:30 -07008285/**---------------------------------------------------------------------------
8286
Jeff Johnson76052702013-04-16 13:55:05 -07008287 \brief fwpath_changed_handler() - Handler Function
8288
8289 Handle changes to the fwpath parameter
8290
8291 \return - 0 for success, non zero for failure
8292
8293 --------------------------------------------------------------------------*/
8294static int fwpath_changed_handler(const char *kmessage,
8295 struct kernel_param *kp)
8296{
8297 int ret;
8298
8299 ret = param_set_copystring(kmessage, kp);
8300 if (0 == ret)
8301 ret = kickstart_driver();
8302 return ret;
8303}
8304
8305/**---------------------------------------------------------------------------
8306
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008307 \brief con_mode_handler() -
8308
8309 Handler function for module param con_mode when it is changed by userspace
8310 Dynamically linked - do nothing
8311 Statically linked - exit and init driver, as in rmmod and insmod
8312
Jeff Johnson76052702013-04-16 13:55:05 -07008313 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008314
Jeff Johnson76052702013-04-16 13:55:05 -07008315 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008316
8317 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008318static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008319{
Jeff Johnson76052702013-04-16 13:55:05 -07008320 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008321
Jeff Johnson76052702013-04-16 13:55:05 -07008322 ret = param_set_int(kmessage, kp);
8323 if (0 == ret)
8324 ret = kickstart_driver();
8325 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008326}
8327#endif /* #ifdef MODULE */
8328
8329/**---------------------------------------------------------------------------
8330
Jeff Johnson295189b2012-06-20 16:38:30 -07008331 \brief hdd_get_conparam() -
8332
8333 This is the driver exit point (invoked when module is unloaded using rmmod)
8334
8335 \param - None
8336
8337 \return - tVOS_CON_MODE
8338
8339 --------------------------------------------------------------------------*/
8340tVOS_CON_MODE hdd_get_conparam ( void )
8341{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008342#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008343 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008344#else
8345 return (tVOS_CON_MODE)curr_con_mode;
8346#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008347}
8348void hdd_set_conparam ( v_UINT_t newParam )
8349{
8350 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008351#ifndef MODULE
8352 curr_con_mode = con_mode;
8353#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008354}
8355/**---------------------------------------------------------------------------
8356
8357 \brief hdd_softap_sta_deauth() - function
8358
8359 This to take counter measure to handle deauth req from HDD
8360
8361 \param - pAdapter - Pointer to the HDD
8362
8363 \param - enable - boolean value
8364
8365 \return - None
8366
8367 --------------------------------------------------------------------------*/
8368
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008369VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008370{
Jeff Johnson295189b2012-06-20 16:38:30 -07008371 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008372 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008373
8374 ENTER();
8375
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008376 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8377 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008378
8379 //Ignore request to deauth bcmc station
8380 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008381 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008382
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008383 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008384
8385 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008386 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008387}
8388
8389/**---------------------------------------------------------------------------
8390
8391 \brief hdd_softap_sta_disassoc() - function
8392
8393 This to take counter measure to handle deauth req from HDD
8394
8395 \param - pAdapter - Pointer to the HDD
8396
8397 \param - enable - boolean value
8398
8399 \return - None
8400
8401 --------------------------------------------------------------------------*/
8402
8403void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8404{
8405 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8406
8407 ENTER();
8408
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308409 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008410
8411 //Ignore request to disassoc bcmc station
8412 if( pDestMacAddress[0] & 0x1 )
8413 return;
8414
8415 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8416}
8417
8418void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8419{
8420 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8421
8422 ENTER();
8423
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308424 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008425
8426 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8427}
8428
Jeff Johnson295189b2012-06-20 16:38:30 -07008429/**---------------------------------------------------------------------------
8430 *
8431 * \brief hdd_get__concurrency_mode() -
8432 *
8433 *
8434 * \param - None
8435 *
8436 * \return - CONCURRENCY MODE
8437 *
8438 * --------------------------------------------------------------------------*/
8439tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8440{
8441 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8442 hdd_context_t *pHddCtx;
8443
8444 if (NULL != pVosContext)
8445 {
8446 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8447 if (NULL != pHddCtx)
8448 {
8449 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8450 }
8451 }
8452
8453 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008454 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008455 return VOS_STA;
8456}
8457
8458/* Decide whether to allow/not the apps power collapse.
8459 * Allow apps power collapse if we are in connected state.
8460 * if not, allow only if we are in IMPS */
8461v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8462{
8463 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008464 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008465 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8467 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8468 hdd_adapter_t *pAdapter = NULL;
8469 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008470 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008471
Jeff Johnson295189b2012-06-20 16:38:30 -07008472 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8473 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008474
Yathish9f22e662012-12-10 14:21:35 -08008475 concurrent_state = hdd_get_concurrency_mode();
8476
8477#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8478 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8479 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8480 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8481 return TRUE;
8482#endif
8483
Jeff Johnson295189b2012-06-20 16:38:30 -07008484 /*loop through all adapters. TBD fix for Concurrency */
8485 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8486 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8487 {
8488 pAdapter = pAdapterNode->pAdapter;
8489 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8490 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8491 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008492 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008493 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008494 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008495 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8496 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008497 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008498 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008499 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8500 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008501 return FALSE;
8502 }
8503 }
8504 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8505 pAdapterNode = pNext;
8506 }
8507 return TRUE;
8508}
8509
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008510/* Decides whether to send suspend notification to Riva
8511 * if any adapter is in BMPS; then it is required */
8512v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8513{
8514 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8515 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8516
8517 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8518 {
8519 return TRUE;
8520 }
8521 return FALSE;
8522}
8523
Jeff Johnson295189b2012-06-20 16:38:30 -07008524void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8525{
8526 switch(mode)
8527 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008528 case VOS_STA_MODE:
8529 case VOS_P2P_CLIENT_MODE:
8530 case VOS_P2P_GO_MODE:
8531 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008532 pHddCtx->concurrency_mode |= (1 << mode);
8533 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008534 break;
8535 default:
8536 break;
8537
8538 }
8539 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8540 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8541}
8542
8543
8544void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8545{
8546 switch(mode)
8547 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008548 case VOS_STA_MODE:
8549 case VOS_P2P_CLIENT_MODE:
8550 case VOS_P2P_GO_MODE:
8551 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008552 pHddCtx->no_of_sessions[mode]--;
8553 if (!(pHddCtx->no_of_sessions[mode]))
8554 pHddCtx->concurrency_mode &= (~(1 << mode));
8555 break;
8556 default:
8557 break;
8558 }
8559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8560 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8561}
8562
Jeff Johnsone7245742012-09-05 17:12:55 -07008563/**---------------------------------------------------------------------------
8564 *
8565 * \brief wlan_hdd_restart_init
8566 *
8567 * This function initalizes restart timer/flag. An internal function.
8568 *
8569 * \param - pHddCtx
8570 *
8571 * \return - None
8572 *
8573 * --------------------------------------------------------------------------*/
8574
8575static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8576{
8577 /* Initialize */
8578 pHddCtx->hdd_restart_retries = 0;
8579 atomic_set(&pHddCtx->isRestartInProgress, 0);
8580 vos_timer_init(&pHddCtx->hdd_restart_timer,
8581 VOS_TIMER_TYPE_SW,
8582 wlan_hdd_restart_timer_cb,
8583 pHddCtx);
8584}
8585/**---------------------------------------------------------------------------
8586 *
8587 * \brief wlan_hdd_restart_deinit
8588 *
8589 * This function cleans up the resources used. An internal function.
8590 *
8591 * \param - pHddCtx
8592 *
8593 * \return - None
8594 *
8595 * --------------------------------------------------------------------------*/
8596
8597static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8598{
8599
8600 VOS_STATUS vos_status;
8601 /* Block any further calls */
8602 atomic_set(&pHddCtx->isRestartInProgress, 1);
8603 /* Cleanup */
8604 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8605 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008606 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008607 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8608 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008609 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008610
8611}
8612
8613/**---------------------------------------------------------------------------
8614 *
8615 * \brief wlan_hdd_framework_restart
8616 *
8617 * This function uses a cfg80211 API to start a framework initiated WLAN
8618 * driver module unload/load.
8619 *
8620 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8621 *
8622 *
8623 * \param - pHddCtx
8624 *
8625 * \return - VOS_STATUS_SUCCESS: Success
8626 * VOS_STATUS_E_EMPTY: Adapter is Empty
8627 * VOS_STATUS_E_NOMEM: No memory
8628
8629 * --------------------------------------------------------------------------*/
8630
8631static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8632{
8633 VOS_STATUS status = VOS_STATUS_SUCCESS;
8634 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008635 int len = (sizeof (struct ieee80211_mgmt));
8636 struct ieee80211_mgmt *mgmt = NULL;
8637
8638 /* Prepare the DEAUTH managment frame with reason code */
8639 mgmt = kzalloc(len, GFP_KERNEL);
8640 if(mgmt == NULL)
8641 {
8642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8643 "%s: memory allocation failed (%d bytes)", __func__, len);
8644 return VOS_STATUS_E_NOMEM;
8645 }
8646 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008647
8648 /* Iterate over all adapters/devices */
8649 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8650 do
8651 {
8652 if( (status == VOS_STATUS_SUCCESS) &&
8653 pAdapterNode &&
8654 pAdapterNode->pAdapter)
8655 {
8656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8657 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8658 pAdapterNode->pAdapter->dev->name,
8659 pAdapterNode->pAdapter->device_mode,
8660 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008661 /*
8662 * CFG80211 event to restart the driver
8663 *
8664 * 'cfg80211_send_unprot_deauth' sends a
8665 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8666 * of SME(Linux Kernel) state machine.
8667 *
8668 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8669 * the driver.
8670 *
8671 */
8672
8673 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008674 }
8675 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8676 pAdapterNode = pNext;
8677 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8678
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008679
8680 /* Free the allocated management frame */
8681 kfree(mgmt);
8682
Jeff Johnsone7245742012-09-05 17:12:55 -07008683 /* Retry until we unload or reach max count */
8684 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8685 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8686
8687 return status;
8688
8689}
8690/**---------------------------------------------------------------------------
8691 *
8692 * \brief wlan_hdd_restart_timer_cb
8693 *
8694 * Restart timer callback. An internal function.
8695 *
8696 * \param - User data:
8697 *
8698 * \return - None
8699 *
8700 * --------------------------------------------------------------------------*/
8701
8702void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8703{
8704 hdd_context_t *pHddCtx = usrDataForCallback;
8705 wlan_hdd_framework_restart(pHddCtx);
8706 return;
8707
8708}
8709
8710
8711/**---------------------------------------------------------------------------
8712 *
8713 * \brief wlan_hdd_restart_driver
8714 *
8715 * This function sends an event to supplicant to restart the WLAN driver.
8716 *
8717 * This function is called from vos_wlanRestart.
8718 *
8719 * \param - pHddCtx
8720 *
8721 * \return - VOS_STATUS_SUCCESS: Success
8722 * VOS_STATUS_E_EMPTY: Adapter is Empty
8723 * VOS_STATUS_E_ALREADY: Request already in progress
8724
8725 * --------------------------------------------------------------------------*/
8726VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8727{
8728 VOS_STATUS status = VOS_STATUS_SUCCESS;
8729
8730 /* A tight check to make sure reentrancy */
8731 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8732 {
8733 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8734 "%s: WLAN restart is already in progress", __func__);
8735
8736 return VOS_STATUS_E_ALREADY;
8737 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008738 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008739#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008740 wcnss_reset_intr();
8741#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008742
Jeff Johnsone7245742012-09-05 17:12:55 -07008743 return status;
8744}
8745
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008746/*
8747 * API to find if there is any STA or P2P-Client is connected
8748 */
8749VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8750{
8751 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8752}
Jeff Johnsone7245742012-09-05 17:12:55 -07008753
Jeff Johnson295189b2012-06-20 16:38:30 -07008754//Register the module init/exit functions
8755module_init(hdd_module_init);
8756module_exit(hdd_module_exit);
8757
8758MODULE_LICENSE("Dual BSD/GPL");
8759MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8760MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8761
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008762module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8763 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008764
Jeff Johnson76052702013-04-16 13:55:05 -07008765module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008766 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);