blob: edef39eb7b5e9ebdcd21304395b367a0733e5c72 [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>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700126#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700127
128#ifdef MODULE
129#define WLAN_MODULE_NAME module_name(THIS_MODULE)
130#else
131#define WLAN_MODULE_NAME "wlan"
132#endif
133
134#ifdef TIMER_MANAGER
135#define TIMER_MANAGER_STR " +TIMER_MANAGER"
136#else
137#define TIMER_MANAGER_STR ""
138#endif
139
140#ifdef MEMORY_DEBUG
141#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
142#else
143#define MEMORY_DEBUG_STR ""
144#endif
145
146/* the Android framework expects this param even though we don't use it */
147#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700148static char fwpath_buffer[BUF_LEN];
149static struct kparam_string fwpath = {
150 .string = fwpath_buffer,
151 .maxlen = BUF_LEN,
152};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700153#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700154static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Jeff Johnsone7245742012-09-05 17:12:55 -0700157/*
158 * The rate at which the driver sends RESTART event to supplicant
159 * once the function 'vos_wlanRestart()' is called
160 *
161 */
162#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
163#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700164
165/*
166 * Size of Driver command strings from upper layer
167 */
168#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
169#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
170
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700171/*
172 * Driver miracast parameters 0-Disabled
173 * 1-Source, 2-Sink
174 */
175#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
176#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
177
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800178#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700179static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700180#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700181/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700182static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700185static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
186static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
188void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800189void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700190
Jeff Johnson295189b2012-06-20 16:38:30 -0700191v_U16_t hdd_select_queue(struct net_device *dev,
192 struct sk_buff *skb);
193
194#ifdef WLAN_FEATURE_PACKET_FILTERING
195static void hdd_set_multicast_list(struct net_device *dev);
196#endif
197
198void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700199int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700200
201extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800202#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
203void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
204static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700205static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
206 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
207 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700208static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
209 tANI_U8 *pTargetApBssid,
210 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700212static int hdd_netdev_notifier_call(struct notifier_block * nb,
213 unsigned long state,
214 void *ndev)
215{
216 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219#ifdef WLAN_BTAMP_FEATURE
220 VOS_STATUS status;
221 hdd_context_t *pHddCtx;
222#endif
223
224 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700226 (strncmp(dev->name, "p2p", 3)))
227 return NOTIFY_DONE;
228
229 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 return NOTIFY_DONE;
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700233 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 VOS_ASSERT(0);
239 return NOTIFY_DONE;
240 }
241
Jeff Johnson27cee452013-03-27 11:10:24 -0700242 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
243 if (NULL == pHddCtx)
244 {
245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
246 VOS_ASSERT(0);
247 return NOTIFY_DONE;
248 }
249
250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
251 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252
253 switch (state) {
254 case NETDEV_REGISTER:
255 break;
256
257 case NETDEV_UNREGISTER:
258 break;
259
260 case NETDEV_UP:
261 break;
262
263 case NETDEV_DOWN:
264 break;
265
266 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700267 if(TRUE == pAdapter->isLinkUpSvcNeeded)
268 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 break;
270
271 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700272 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 {
274 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800275 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530276 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800278 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
280 if(!result)
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800283 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700284 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 }
286 }
287 else
288 {
289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700290 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 }
292#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 status = WLANBAP_StopAmp();
295 if(VOS_STATUS_SUCCESS != status )
296 {
297 pHddCtx->isAmpAllowed = VOS_TRUE;
298 hddLog(VOS_TRACE_LEVEL_FATAL,
299 "%s: Failed to stop AMP", __func__);
300 }
301 else
302 {
303 //a state m/c implementation in PAL is TBD to avoid this delay
304 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700305 if ( pHddCtx->isAmpAllowed )
306 {
307 WLANBAP_DeregisterFromHCI();
308 pHddCtx->isAmpAllowed = VOS_FALSE;
309 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311#endif //WLAN_BTAMP_FEATURE
312 break;
313
314 default:
315 break;
316 }
317
318 return NOTIFY_DONE;
319}
320
321struct notifier_block hdd_netdev_notifier = {
322 .notifier_call = hdd_netdev_notifier_call,
323};
324
325/*---------------------------------------------------------------------------
326 * Function definitions
327 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700328void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
329void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700330//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700331static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700332#ifndef MODULE
333/* current con_mode - used only for statically linked driver
334 * con_mode is changed by userspace to indicate a mode change which will
335 * result in calling the module exit and init functions. The module
336 * exit function will clean up based on the value of con_mode prior to it
337 * being changed by userspace. So curr_con_mode records the current con_mode
338 * for exit when con_mode becomes the next mode for init
339 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700340static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700341#endif
342
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800343/**---------------------------------------------------------------------------
344
345 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
346
347 Called immediately after the cfg.ini is read in order to configure
348 the desired trace levels.
349
350 \param - moduleId - module whose trace level is being configured
351 \param - bitmask - bitmask of log levels to be enabled
352
353 \return - void
354
355 --------------------------------------------------------------------------*/
356static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
357{
358 wpt_tracelevel level;
359
360 /* if the bitmask is the default value, then a bitmask was not
361 specified in cfg.ini, so leave the logging level alone (it
362 will remain at the "compiled in" default value) */
363 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
364 {
365 return;
366 }
367
368 /* a mask was specified. start by disabling all logging */
369 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
370
371 /* now cycle through the bitmask until all "set" bits are serviced */
372 level = VOS_TRACE_LEVEL_FATAL;
373 while (0 != bitmask)
374 {
375 if (bitmask & 1)
376 {
377 vos_trace_setValue(moduleId, level, 1);
378 }
379 level++;
380 bitmask >>= 1;
381 }
382}
383
384
Jeff Johnson295189b2012-06-20 16:38:30 -0700385/**---------------------------------------------------------------------------
386
387 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
388
389 Called immediately after the cfg.ini is read in order to configure
390 the desired trace levels in the WDI.
391
392 \param - moduleId - module whose trace level is being configured
393 \param - bitmask - bitmask of log levels to be enabled
394
395 \return - void
396
397 --------------------------------------------------------------------------*/
398static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
399{
400 wpt_tracelevel level;
401
402 /* if the bitmask is the default value, then a bitmask was not
403 specified in cfg.ini, so leave the logging level alone (it
404 will remain at the "compiled in" default value) */
405 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
406 {
407 return;
408 }
409
410 /* a mask was specified. start by disabling all logging */
411 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
412
413 /* now cycle through the bitmask until all "set" bits are serviced */
414 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
415 while (0 != bitmask)
416 {
417 if (bitmask & 1)
418 {
419 wpalTraceSetLevel(moduleId, level, 1);
420 }
421 level++;
422 bitmask >>= 1;
423 }
424}
Jeff Johnson295189b2012-06-20 16:38:30 -0700425
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530426/*
427 * FUNCTION: wlan_hdd_validate_context
428 * This function is used to check the HDD context
429 */
430int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
431{
432 ENTER();
433
434 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
435 {
436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: HDD context is Null", __func__);
438 return -ENODEV;
439 }
440
441 if (pHddCtx->isLogpInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: LOGP in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447
448 if (pHddCtx->isLoadUnloadInProgress)
449 {
450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
451 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
452 return -EAGAIN;
453 }
454 return 0;
455}
456
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530457void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
458{
459 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
460 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
461 hdd_config_t *cfg_param;
462 eCsrPhyMode phyMode;
463
464 if (NULL == pHddCtx)
465 {
466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
467 "HDD Context is null !!");
468 return ;
469 }
470
471 cfg_param = pHddCtx->cfg_ini;
472
473 if (NULL == cfg_param)
474 {
475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
476 "cfg_params not available !!");
477 return ;
478 }
479
480 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
481
482 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
483 {
484 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
485 (eCSR_DOT11_MODE_11ac == phyMode) ||
486 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
489 "Setting phymode to 11n!!");
490 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
491 }
492 }
493 else
494 {
495 /*New country Supports 11ac as well resetting value back from .ini*/
496 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
497 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
498 return ;
499 }
500
501 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
502 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
503 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
504 {
505 VOS_STATUS vosStatus;
506
507 // need to issue a disconnect to CSR.
508 INIT_COMPLETION(pAdapter->disconnect_comp_var);
509 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
510 pAdapter->sessionId,
511 eCSR_DISCONNECT_REASON_UNSPECIFIED );
512
513 if (VOS_STATUS_SUCCESS == vosStatus)
514 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
515 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
516
517 }
518}
519
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700520void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
521{
522 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
523 hdd_config_t *cfg_param;
524
525 if (NULL == pHddCtx)
526 {
527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
528 "HDD Context is null !!");
529 return ;
530 }
531
532 cfg_param = pHddCtx->cfg_ini;
533
534 if (NULL == cfg_param)
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
537 "cfg_params not available !!");
538 return ;
539 }
540
541 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
542 {
543 /*New country doesn't support DFS */
544 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
545 }
546 else
547 {
548 /*New country Supports DFS as well resetting value back from .ini*/
549 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
550 }
551
552}
553
Jeff Johnson295189b2012-06-20 16:38:30 -0700554int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
555{
556 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
557 hdd_priv_data_t priv_data;
558 tANI_U8 *command = NULL;
559 int ret = 0;
560
561 if (NULL == pAdapter)
562 {
563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700564 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 ret = -ENODEV;
566 goto exit;
567 }
568
Jeff Johnsone7245742012-09-05 17:12:55 -0700569 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700570 {
571 ret = -EINVAL;
572 goto exit;
573 }
574
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700575 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
576 {
577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
578 "%s:LOGP in Progress. Ignore!!!", __func__);
579 ret = -EBUSY;
580 goto exit;
581 }
582
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
584 {
585 ret = -EFAULT;
586 goto exit;
587 }
588
589 command = kmalloc(priv_data.total_len, GFP_KERNEL);
590 if (!command)
591 {
592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700593 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 ret = -ENOMEM;
595 goto exit;
596 }
597
598 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
599 {
600 ret = -EFAULT;
601 goto exit;
602 }
603
604 if ((SIOCDEVPRIVATE + 1) == cmd)
605 {
606 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
607
608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700609 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700610
611 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
612 {
613 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
614 sizeof(tSirMacAddr)))
615 {
616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700617 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700618 ret = -EFAULT;
619 }
620 }
Amar Singhal0974e402013-02-12 14:27:46 -0800621 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 {
Amar Singhal0974e402013-02-12 14:27:46 -0800623 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700624 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800625
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800627
628 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800631 "%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 -0700632 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800633 ret = hdd_setBand_helper(dev, ptr);
634 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700635 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
636 {
637 char *country_code;
638
639 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700640
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -0700641 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700642 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530643 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -0700644 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
645 (void *)(tSmeChangeCountryCallback)
646 wlan_hdd_change_country_code_callback,
647 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
648 if (eHAL_STATUS_SUCCESS == ret)
649 {
650 ret = wait_for_completion_interruptible_timeout(
651 &pAdapter->change_country_code,
652 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
653 if (0 >= ret)
654 {
655 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
656 __func__);
657 }
658 }
659 else
Jeff Johnson32d95a32012-09-10 13:15:23 -0700660 {
661 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -0700662 "%s: SME Change Country code fail ret=%d", __func__, ret);
663 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700664 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -0700665
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700666 }
667 /*
668 command should be a string having format
669 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
670 */
Amar Singhal0974e402013-02-12 14:27:46 -0800671 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700672 {
Amar Singhal0974e402013-02-12 14:27:46 -0800673 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700674
675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700676 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700677
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800678 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700679 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800680 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
681 {
682 int suspend = 0;
683 tANI_U8 *ptr = (tANI_U8*)command + 15;
684
685 suspend = *ptr - '0';
686 hdd_set_wlan_suspend_mode(suspend);
687 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800688#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
689 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
690 {
691 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700692 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800693 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
694 eHalStatus status = eHAL_STATUS_SUCCESS;
695
696 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
697 value = value + 15;
698
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700699 /* Convert the value from ascii to integer */
700 ret = kstrtos8(value, 10, &rssi);
701 if (ret < 0)
702 {
703 /* If the input value is greater than max value of datatype, then also
704 kstrtou8 fails */
705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
706 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
707 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
708 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
709 ret = -EINVAL;
710 goto exit;
711 }
712
Srinivas Girigowdade697412013-02-14 16:31:48 -0800713 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700714
Srinivas Girigowdade697412013-02-14 16:31:48 -0800715 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
716 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
717 {
718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
719 "Neighbor lookup threshold value %d is out of range"
720 " (Min: %d Max: %d)", lookUpThreshold,
721 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
722 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
723 ret = -EINVAL;
724 goto exit;
725 }
726
727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
728 "%s: Received Command to Set Roam trigger"
729 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
730
731 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
732 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
733 if (eHAL_STATUS_SUCCESS != status)
734 {
735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
736 "%s: Failed to set roam trigger, try again", __func__);
737 ret = -EPERM;
738 goto exit;
739 }
740
741 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
742 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
743 }
744 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
745 {
746 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
747 int rssi = (-1) * lookUpThreshold;
748 char extra[32];
749 tANI_U8 len = 0;
750
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700751 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800752 if (copy_to_user(priv_data.buf, &extra, len + 1))
753 {
754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
755 "%s: failed to copy data to user buffer", __func__);
756 ret = -EFAULT;
757 goto exit;
758 }
759 }
760 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
761 {
762 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700763 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700764 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700765
Srinivas Girigowdade697412013-02-14 16:31:48 -0800766 /* input refresh period is in terms of seconds */
767 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
768 value = value + 18;
769 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700770 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800771 if (ret < 0)
772 {
773 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700774 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700776 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800777 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700778 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
779 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800780 ret = -EINVAL;
781 goto exit;
782 }
783
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700784 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
785 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800786 {
787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700788 "Roam scan period value %d is out of range"
789 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700790 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
791 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800792 ret = -EINVAL;
793 goto exit;
794 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700795 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800796
797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
798 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700799 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800800
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700801 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
802 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800803 }
804 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
805 {
806 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
807 char extra[32];
808 tANI_U8 len = 0;
809
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700810 len = scnprintf(extra, sizeof(extra), "%s %d",
811 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800812 /* Returned value is in units of seconds */
813 if (copy_to_user(priv_data.buf, &extra, len + 1))
814 {
815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
816 "%s: failed to copy data to user buffer", __func__);
817 ret = -EFAULT;
818 goto exit;
819 }
820 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700821 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
822 {
823 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700824 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700825 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700826
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700827 /* input refresh period is in terms of seconds */
828 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
829 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700830
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700831 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700832 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700833 if (ret < 0)
834 {
835 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700836 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700838 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700839 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700840 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
841 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
842 ret = -EINVAL;
843 goto exit;
844 }
845
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700846 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
847 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
848 {
849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
850 "Neighbor scan results refresh period value %d is out of range"
851 " (Min: %d Max: %d)", roamScanRefreshPeriod,
852 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
853 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
854 ret = -EINVAL;
855 goto exit;
856 }
857 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
858
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
860 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700861 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700862
863 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
864 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
865 }
866 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
867 {
868 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
869 char extra[32];
870 tANI_U8 len = 0;
871
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700872 len = scnprintf(extra, sizeof(extra), "%s %d",
873 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700874 /* Returned value is in units of seconds */
875 if (copy_to_user(priv_data.buf, &extra, len + 1))
876 {
877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
878 "%s: failed to copy data to user buffer", __func__);
879 ret = -EFAULT;
880 goto exit;
881 }
882 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700883#ifdef FEATURE_WLAN_LFR
884 /* SETROAMMODE */
885 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
886 {
887 tANI_U8 *value = command;
888 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
889
890 /* Move pointer to ahead of SETROAMMODE<delimiter> */
891 value = value + SIZE_OF_SETROAMMODE + 1;
892
893 /* Convert the value from ascii to integer */
894 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
895 if (ret < 0)
896 {
897 /* If the input value is greater than max value of datatype, then also
898 kstrtou8 fails */
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
900 "%s: kstrtou8 failed range [%d - %d]", __func__,
901 CFG_LFR_FEATURE_ENABLED_MIN,
902 CFG_LFR_FEATURE_ENABLED_MAX);
903 ret = -EINVAL;
904 goto exit;
905 }
906 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
907 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
908 {
909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
910 "Roam Mode value %d is out of range"
911 " (Min: %d Max: %d)", roamMode,
912 CFG_LFR_FEATURE_ENABLED_MIN,
913 CFG_LFR_FEATURE_ENABLED_MAX);
914 ret = -EINVAL;
915 goto exit;
916 }
917
918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
919 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
920 /*
921 * Note that
922 * SETROAMMODE 0 is to enable LFR while
923 * SETROAMMODE 1 is to disable LFR, but
924 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
925 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
926 */
927 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
928 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
929 else
930 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
931
932 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
933 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
934 }
935 /* GETROAMMODE */
936 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
937 {
938 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
939 char extra[32];
940 tANI_U8 len = 0;
941
942 /*
943 * roamMode value shall be inverted because the sementics is different.
944 */
945 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
946 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
947 else
948 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
949
Sameer Thalappilb0a30232013-09-27 15:37:48 -0700950 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700951 if (copy_to_user(priv_data.buf, &extra, len + 1))
952 {
953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
954 "%s: failed to copy data to user buffer", __func__);
955 ret = -EFAULT;
956 goto exit;
957 }
958 }
959#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800960#endif
961#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
962 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
963 {
964 tANI_U8 *value = command;
965 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
966
967 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
968 value = value + 13;
969 /* Convert the value from ascii to integer */
970 ret = kstrtou8(value, 10, &roamRssiDiff);
971 if (ret < 0)
972 {
973 /* If the input value is greater than max value of datatype, then also
974 kstrtou8 fails */
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: kstrtou8 failed range [%d - %d]", __func__,
977 CFG_ROAM_RSSI_DIFF_MIN,
978 CFG_ROAM_RSSI_DIFF_MAX);
979 ret = -EINVAL;
980 goto exit;
981 }
982
983 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
984 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
985 {
986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
987 "Roam rssi diff value %d is out of range"
988 " (Min: %d Max: %d)", roamRssiDiff,
989 CFG_ROAM_RSSI_DIFF_MIN,
990 CFG_ROAM_RSSI_DIFF_MAX);
991 ret = -EINVAL;
992 goto exit;
993 }
994
995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
996 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
997
998 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
999 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1000 }
1001 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1002 {
1003 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1004 char extra[32];
1005 tANI_U8 len = 0;
1006
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001007 len = scnprintf(extra, sizeof(extra), "%s %d",
1008 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001009 if (copy_to_user(priv_data.buf, &extra, len + 1))
1010 {
1011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1012 "%s: failed to copy data to user buffer", __func__);
1013 ret = -EFAULT;
1014 goto exit;
1015 }
1016 }
1017#endif
1018#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1019 else if (strncmp(command, "GETBAND", 7) == 0)
1020 {
1021 int band = -1;
1022 char extra[32];
1023 tANI_U8 len = 0;
1024 hdd_getBand_helper(pHddCtx, &band);
1025
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001026 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001027 if (copy_to_user(priv_data.buf, &extra, len + 1))
1028 {
1029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1030 "%s: failed to copy data to user buffer", __func__);
1031 ret = -EFAULT;
1032 goto exit;
1033 }
1034 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001035 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1036 {
1037 tANI_U8 *value = command;
1038 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1039 tANI_U8 numChannels = 0;
1040 eHalStatus status = eHAL_STATUS_SUCCESS;
1041
1042 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1043 if (eHAL_STATUS_SUCCESS != status)
1044 {
1045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: Failed to parse channel list information", __func__);
1047 ret = -EINVAL;
1048 goto exit;
1049 }
1050
1051 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1052 {
1053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1054 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1055 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1056 ret = -EINVAL;
1057 goto exit;
1058 }
1059 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1060 numChannels);
1061 if (eHAL_STATUS_SUCCESS != status)
1062 {
1063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1064 "%s: Failed to update channel list information", __func__);
1065 ret = -EINVAL;
1066 goto exit;
1067 }
1068 }
1069 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1070 {
1071 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1072 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001073 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001074 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001075 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001076
1077 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1078 ChannelList, &numChannels ))
1079 {
1080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1081 "%s: failed to get roam scan channel list", __func__);
1082 ret = -EFAULT;
1083 goto exit;
1084 }
1085 /* output channel list is of the format
1086 [Number of roam scan channels][Channel1][Channel2]... */
1087 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001088 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001089 for (j = 0; (j < numChannels); j++)
1090 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001091 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
1092 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001093 }
1094
1095 if (copy_to_user(priv_data.buf, &extra, len + 1))
1096 {
1097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1098 "%s: failed to copy data to user buffer", __func__);
1099 ret = -EFAULT;
1100 goto exit;
1101 }
1102 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001103 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1104 {
1105 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1106 char extra[32];
1107 tANI_U8 len = 0;
1108
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001109 /* Check if the features OKC/CCX/11R are supported simultaneously,
1110 then this operation is not permitted (return FAILURE) */
1111 if (ccxMode &&
1112 hdd_is_okc_mode_enabled(pHddCtx) &&
1113 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1114 {
1115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1116 "%s: OKC/CCX/11R are supported simultaneously"
1117 " hence this operation is not permitted!", __func__);
1118 ret = -EPERM;
1119 goto exit;
1120 }
1121
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001122 len = scnprintf(extra, sizeof(extra), "%s %d",
1123 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001124 if (copy_to_user(priv_data.buf, &extra, len + 1))
1125 {
1126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1127 "%s: failed to copy data to user buffer", __func__);
1128 ret = -EFAULT;
1129 goto exit;
1130 }
1131 }
1132 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1133 {
1134 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1135 char extra[32];
1136 tANI_U8 len = 0;
1137
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001138 /* Check if the features OKC/CCX/11R are supported simultaneously,
1139 then this operation is not permitted (return FAILURE) */
1140 if (okcMode &&
1141 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1142 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1143 {
1144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1145 "%s: OKC/CCX/11R are supported simultaneously"
1146 " hence this operation is not permitted!", __func__);
1147 ret = -EPERM;
1148 goto exit;
1149 }
1150
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001151 len = scnprintf(extra, sizeof(extra), "%s %d",
1152 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001153 if (copy_to_user(priv_data.buf, &extra, len + 1))
1154 {
1155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1156 "%s: failed to copy data to user buffer", __func__);
1157 ret = -EFAULT;
1158 goto exit;
1159 }
1160 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001161 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001162 {
1163 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1164 char extra[32];
1165 tANI_U8 len = 0;
1166
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001167 len = scnprintf(extra, sizeof(extra), "%s %d",
1168 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001169 if (copy_to_user(priv_data.buf, &extra, len + 1))
1170 {
1171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1172 "%s: failed to copy data to user buffer", __func__);
1173 ret = -EFAULT;
1174 goto exit;
1175 }
1176 }
1177 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1178 {
1179 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1180 char extra[32];
1181 tANI_U8 len = 0;
1182
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001183 len = scnprintf(extra, sizeof(extra), "%s %d",
1184 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001185 if (copy_to_user(priv_data.buf, &extra, len + 1))
1186 {
1187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1188 "%s: failed to copy data to user buffer", __func__);
1189 ret = -EFAULT;
1190 goto exit;
1191 }
1192 }
1193 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1194 {
1195 tANI_U8 *value = command;
1196 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1197
1198 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1199 value = value + 26;
1200 /* Convert the value from ascii to integer */
1201 ret = kstrtou8(value, 10, &minTime);
1202 if (ret < 0)
1203 {
1204 /* If the input value is greater than max value of datatype, then also
1205 kstrtou8 fails */
1206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1207 "%s: kstrtou8 failed range [%d - %d]", __func__,
1208 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1209 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1210 ret = -EINVAL;
1211 goto exit;
1212 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001213 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1214 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1215 {
1216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1217 "scan min channel time value %d is out of range"
1218 " (Min: %d Max: %d)", minTime,
1219 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1220 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1221 ret = -EINVAL;
1222 goto exit;
1223 }
1224
1225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1226 "%s: Received Command to change channel min time = %d", __func__, minTime);
1227
1228 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1229 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1230 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001231 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1232 {
1233 tANI_U8 *value = command;
1234 tANI_U8 channel = 0;
1235 tANI_U8 dwellTime = 0;
1236 tANI_U8 bufLen = 0;
1237 tANI_U8 *buf = NULL;
1238 tSirMacAddr targetApBssid;
1239 eHalStatus status = eHAL_STATUS_SUCCESS;
1240 struct ieee80211_channel chan;
1241 tANI_U8 finalLen = 0;
1242 tANI_U8 *finalBuf = NULL;
1243 tANI_U8 temp = 0;
1244 u64 cookie;
1245 hdd_station_ctx_t *pHddStaCtx = NULL;
1246 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1247
1248 /* if not associated, no need to send action frame */
1249 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1250 {
1251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1252 ret = -EINVAL;
1253 goto exit;
1254 }
1255
1256 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1257 &dwellTime, &buf, &bufLen);
1258 if (eHAL_STATUS_SUCCESS != status)
1259 {
1260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1261 "%s: Failed to parse send action frame data", __func__);
1262 ret = -EINVAL;
1263 goto exit;
1264 }
1265
1266 /* if the target bssid is different from currently associated AP,
1267 then no need to send action frame */
1268 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1269 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1270 {
1271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1272 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001273 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001274 goto exit;
1275 }
1276
1277 /* if the channel number is different from operating channel then
1278 no need to send action frame */
1279 if (channel != pHddStaCtx->conn_info.operationChannel)
1280 {
1281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1282 "%s: channel(%d) is different from operating channel(%d)",
1283 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1284 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001285 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001286 goto exit;
1287 }
1288 chan.center_freq = sme_ChnToFreq(channel);
1289
1290 finalLen = bufLen + 24;
1291 finalBuf = vos_mem_malloc(finalLen);
1292 if (NULL == finalBuf)
1293 {
1294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1295 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001296 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 goto exit;
1298 }
1299 vos_mem_zero(finalBuf, finalLen);
1300
1301 /* Fill subtype */
1302 temp = SIR_MAC_MGMT_ACTION << 4;
1303 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1304
1305 /* Fill type */
1306 temp = SIR_MAC_MGMT_FRAME;
1307 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1308
1309 /* Fill destination address (bssid of the AP) */
1310 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1311
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001312 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001313 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1314
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001315 /* Fill BSSID (AP mac address) */
1316 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001317
1318 /* Fill received buffer from 24th address */
1319 vos_mem_copy(finalBuf + 24, buf, bufLen);
1320
Jeff Johnson11c33152013-04-16 17:52:40 -07001321 /* done with the parsed buffer */
1322 vos_mem_free(buf);
1323
Yue Maf49ba872013-08-19 12:04:25 -07001324 wlan_hdd_action( NULL,
1325#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1326 &(pAdapter->wdev),
1327#else
1328 dev,
1329#endif
1330 &chan, 0,
1331#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1332 NL80211_CHAN_HT20, 1,
1333#endif
1334 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001335 1, &cookie );
1336 vos_mem_free(finalBuf);
1337 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001338 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1339 {
1340 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1341 char extra[32];
1342 tANI_U8 len = 0;
1343
1344 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001345 len = scnprintf(extra, sizeof(extra), "%s %d",
1346 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001347 if (copy_to_user(priv_data.buf, &extra, len + 1))
1348 {
1349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1350 "%s: failed to copy data to user buffer", __func__);
1351 ret = -EFAULT;
1352 goto exit;
1353 }
1354 }
1355 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1356 {
1357 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001358 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001359 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001360
1361 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1362 value = value + 19;
1363 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001364 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001365 if (ret < 0)
1366 {
1367 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001368 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001370 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001371 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1372 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1373 ret = -EINVAL;
1374 goto exit;
1375 }
1376
1377 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1378 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1379 {
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1381 "lfr mode value %d is out of range"
1382 " (Min: %d Max: %d)", maxTime,
1383 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1384 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1385 ret = -EINVAL;
1386 goto exit;
1387 }
1388
1389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1390 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1391
1392 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001393
1394 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1395 * where RFS is the RF Switching time. It is twice RFS to consider the
1396 * time to go off channel and return to the home channel. */
1397 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1398 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1399 {
1400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1401 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1402 " Hence enforcing home away time to disable (0)",
1403 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1404 homeAwayTime = 0;
1405 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1406 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1407 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001408 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1409 }
1410 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1411 {
1412 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1413 char extra[32];
1414 tANI_U8 len = 0;
1415
1416 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001417 len = scnprintf(extra, sizeof(extra), "%s %d",
1418 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001419 if (copy_to_user(priv_data.buf, &extra, len + 1))
1420 {
1421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1422 "%s: failed to copy data to user buffer", __func__);
1423 ret = -EFAULT;
1424 goto exit;
1425 }
1426 }
1427 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1428 {
1429 tANI_U8 *value = command;
1430 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1431
1432 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1433 value = value + 16;
1434 /* Convert the value from ascii to integer */
1435 ret = kstrtou16(value, 10, &val);
1436 if (ret < 0)
1437 {
1438 /* If the input value is greater than max value of datatype, then also
1439 kstrtou16 fails */
1440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1441 "%s: kstrtou16 failed range [%d - %d]", __func__,
1442 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1443 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1444 ret = -EINVAL;
1445 goto exit;
1446 }
1447
1448 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1449 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1450 {
1451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1452 "scan home time value %d is out of range"
1453 " (Min: %d Max: %d)", val,
1454 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1455 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1456 ret = -EINVAL;
1457 goto exit;
1458 }
1459
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1461 "%s: Received Command to change scan home time = %d", __func__, val);
1462
1463 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1464 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1465 }
1466 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1467 {
1468 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1469 char extra[32];
1470 tANI_U8 len = 0;
1471
1472 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001473 len = scnprintf(extra, sizeof(extra), "%s %d",
1474 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001475 if (copy_to_user(priv_data.buf, &extra, len + 1))
1476 {
1477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1478 "%s: failed to copy data to user buffer", __func__);
1479 ret = -EFAULT;
1480 goto exit;
1481 }
1482 }
1483 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1484 {
1485 tANI_U8 *value = command;
1486 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1487
1488 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1489 value = value + 17;
1490 /* Convert the value from ascii to integer */
1491 ret = kstrtou8(value, 10, &val);
1492 if (ret < 0)
1493 {
1494 /* If the input value is greater than max value of datatype, then also
1495 kstrtou8 fails */
1496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1497 "%s: kstrtou8 failed range [%d - %d]", __func__,
1498 CFG_ROAM_INTRA_BAND_MIN,
1499 CFG_ROAM_INTRA_BAND_MAX);
1500 ret = -EINVAL;
1501 goto exit;
1502 }
1503
1504 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1505 (val > CFG_ROAM_INTRA_BAND_MAX))
1506 {
1507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1508 "intra band mode value %d is out of range"
1509 " (Min: %d Max: %d)", val,
1510 CFG_ROAM_INTRA_BAND_MIN,
1511 CFG_ROAM_INTRA_BAND_MAX);
1512 ret = -EINVAL;
1513 goto exit;
1514 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1516 "%s: Received Command to change intra band = %d", __func__, val);
1517
1518 pHddCtx->cfg_ini->nRoamIntraBand = val;
1519 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1520 }
1521 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1522 {
1523 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1524 char extra[32];
1525 tANI_U8 len = 0;
1526
1527 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001528 len = scnprintf(extra, sizeof(extra), "%s %d",
1529 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001530 if (copy_to_user(priv_data.buf, &extra, len + 1))
1531 {
1532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1533 "%s: failed to copy data to user buffer", __func__);
1534 ret = -EFAULT;
1535 goto exit;
1536 }
1537 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001538 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1539 {
1540 tANI_U8 *value = command;
1541 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1542
1543 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1544 value = value + 15;
1545 /* Convert the value from ascii to integer */
1546 ret = kstrtou8(value, 10, &nProbes);
1547 if (ret < 0)
1548 {
1549 /* If the input value is greater than max value of datatype, then also
1550 kstrtou8 fails */
1551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1552 "%s: kstrtou8 failed range [%d - %d]", __func__,
1553 CFG_ROAM_SCAN_N_PROBES_MIN,
1554 CFG_ROAM_SCAN_N_PROBES_MAX);
1555 ret = -EINVAL;
1556 goto exit;
1557 }
1558
1559 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1560 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1561 {
1562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1563 "NProbes value %d is out of range"
1564 " (Min: %d Max: %d)", nProbes,
1565 CFG_ROAM_SCAN_N_PROBES_MIN,
1566 CFG_ROAM_SCAN_N_PROBES_MAX);
1567 ret = -EINVAL;
1568 goto exit;
1569 }
1570
1571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1572 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1573
1574 pHddCtx->cfg_ini->nProbes = nProbes;
1575 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1576 }
1577 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1578 {
1579 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1580 char extra[32];
1581 tANI_U8 len = 0;
1582
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001583 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001584 if (copy_to_user(priv_data.buf, &extra, len + 1))
1585 {
1586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1587 "%s: failed to copy data to user buffer", __func__);
1588 ret = -EFAULT;
1589 goto exit;
1590 }
1591 }
1592 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1593 {
1594 tANI_U8 *value = command;
1595 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001596 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001597
1598 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1599 /* input value is in units of msec */
1600 value = value + 20;
1601 /* Convert the value from ascii to integer */
1602 ret = kstrtou16(value, 10, &homeAwayTime);
1603 if (ret < 0)
1604 {
1605 /* If the input value is greater than max value of datatype, then also
1606 kstrtou8 fails */
1607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1608 "%s: kstrtou8 failed range [%d - %d]", __func__,
1609 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1610 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1611 ret = -EINVAL;
1612 goto exit;
1613 }
1614
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001615 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1616 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1617 {
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "homeAwayTime value %d is out of range"
1620 " (Min: %d Max: %d)", homeAwayTime,
1621 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1622 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1623 ret = -EINVAL;
1624 goto exit;
1625 }
1626
1627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1628 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1629
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001630 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1631 * where RFS is the RF Switching time. It is twice RFS to consider the
1632 * time to go off channel and return to the home channel. */
1633 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1634 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1635 {
1636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1637 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1638 " Hence enforcing home away time to disable (0)",
1639 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1640 homeAwayTime = 0;
1641 }
1642
1643 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1644 {
1645 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1646 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1647 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001648 }
1649 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1650 {
1651 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1652 char extra[32];
1653 tANI_U8 len = 0;
1654
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001655 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001656 if (copy_to_user(priv_data.buf, &extra, len + 1))
1657 {
1658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1659 "%s: failed to copy data to user buffer", __func__);
1660 ret = -EFAULT;
1661 goto exit;
1662 }
1663 }
1664 else if (strncmp(command, "REASSOC", 7) == 0)
1665 {
1666 tANI_U8 *value = command;
1667 tANI_U8 channel = 0;
1668 tSirMacAddr targetApBssid;
1669 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001670#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1671 tCsrHandoffRequest handoffInfo;
1672#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001673 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001674 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1675
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001676 /* if not associated, no need to proceed with reassoc */
1677 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1678 {
1679 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1680 ret = -EINVAL;
1681 goto exit;
1682 }
1683
1684 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1685 if (eHAL_STATUS_SUCCESS != status)
1686 {
1687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1688 "%s: Failed to parse reassoc command data", __func__);
1689 ret = -EINVAL;
1690 goto exit;
1691 }
1692
1693 /* if the target bssid is same as currently associated AP,
1694 then no need to proceed with reassoc */
1695 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1696 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1697 {
1698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1699 ret = -EINVAL;
1700 goto exit;
1701 }
1702
1703 /* Check channel number is a valid channel number */
1704 if(VOS_STATUS_SUCCESS !=
1705 wlan_hdd_validate_operation_channel(pAdapter, channel))
1706 {
1707 hddLog(VOS_TRACE_LEVEL_ERROR,
1708 "%s: Invalid Channel [%d] \n", __func__, channel);
1709 return -EINVAL;
1710 }
1711
1712 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001713#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1714 handoffInfo.channel = channel;
1715 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1716 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1717#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001718 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001719#endif
1720#ifdef FEATURE_WLAN_LFR
1721 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1722 {
1723 tANI_U8 *value = command;
1724 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1725
1726 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1727 value = value + 12;
1728 /* Convert the value from ascii to integer */
1729 ret = kstrtou8(value, 10, &lfrMode);
1730 if (ret < 0)
1731 {
1732 /* If the input value is greater than max value of datatype, then also
1733 kstrtou8 fails */
1734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1735 "%s: kstrtou8 failed range [%d - %d]", __func__,
1736 CFG_LFR_FEATURE_ENABLED_MIN,
1737 CFG_LFR_FEATURE_ENABLED_MAX);
1738 ret = -EINVAL;
1739 goto exit;
1740 }
1741
1742 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1743 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1744 {
1745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1746 "lfr mode value %d is out of range"
1747 " (Min: %d Max: %d)", lfrMode,
1748 CFG_LFR_FEATURE_ENABLED_MIN,
1749 CFG_LFR_FEATURE_ENABLED_MAX);
1750 ret = -EINVAL;
1751 goto exit;
1752 }
1753
1754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1755 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1756
1757 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1758 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1759 }
1760#endif
1761#ifdef WLAN_FEATURE_VOWIFI_11R
1762 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1763 {
1764 tANI_U8 *value = command;
1765 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1766
1767 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1768 value = value + 18;
1769 /* Convert the value from ascii to integer */
1770 ret = kstrtou8(value, 10, &ft);
1771 if (ret < 0)
1772 {
1773 /* If the input value is greater than max value of datatype, then also
1774 kstrtou8 fails */
1775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1776 "%s: kstrtou8 failed range [%d - %d]", __func__,
1777 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1778 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1779 ret = -EINVAL;
1780 goto exit;
1781 }
1782
1783 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1784 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1785 {
1786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1787 "ft mode value %d is out of range"
1788 " (Min: %d Max: %d)", ft,
1789 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1790 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1791 ret = -EINVAL;
1792 goto exit;
1793 }
1794
1795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1796 "%s: Received Command to change ft mode = %d", __func__, ft);
1797
1798 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1799 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1800 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05301801
1802 else if (strncmp(command, "FASTREASSOC", 11) == 0)
1803 {
1804 tANI_U8 *value = command;
1805 tSirMacAddr targetApBssid;
1806 tANI_U8 trigger = 0;
1807 eHalStatus status = eHAL_STATUS_SUCCESS;
1808 hdd_station_ctx_t *pHddStaCtx = NULL;
1809 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1810
1811 /* if not associated, no need to proceed with reassoc */
1812 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1813 {
1814 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1815 ret = -EINVAL;
1816 goto exit;
1817 }
1818
1819 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
1820 if (eHAL_STATUS_SUCCESS != status)
1821 {
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1823 "%s: Failed to parse reassoc command data", __func__);
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827
1828 /* if the target bssid is same as currently associated AP,
1829 then no need to proceed with reassoc */
1830 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1831 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1832 {
1833 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1834 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
1835 __func__);
1836 ret = -EINVAL;
1837 goto exit;
1838 }
1839
1840 /* Proceed with scan/roam */
1841 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
1842 &targetApBssid[0],
1843 (tSmeFastRoamTrigger)(trigger));
1844 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001845#endif
1846#ifdef FEATURE_WLAN_CCX
1847 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1848 {
1849 tANI_U8 *value = command;
1850 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1851
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001852 /* Check if the features OKC/CCX/11R are supported simultaneously,
1853 then this operation is not permitted (return FAILURE) */
1854 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1855 hdd_is_okc_mode_enabled(pHddCtx) &&
1856 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1857 {
1858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1859 "%s: OKC/CCX/11R are supported simultaneously"
1860 " hence this operation is not permitted!", __func__);
1861 ret = -EPERM;
1862 goto exit;
1863 }
1864
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001865 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1866 value = value + 11;
1867 /* Convert the value from ascii to integer */
1868 ret = kstrtou8(value, 10, &ccxMode);
1869 if (ret < 0)
1870 {
1871 /* If the input value is greater than max value of datatype, then also
1872 kstrtou8 fails */
1873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1874 "%s: kstrtou8 failed range [%d - %d]", __func__,
1875 CFG_CCX_FEATURE_ENABLED_MIN,
1876 CFG_CCX_FEATURE_ENABLED_MAX);
1877 ret = -EINVAL;
1878 goto exit;
1879 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001880 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1881 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1882 {
1883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1884 "Ccx mode value %d is out of range"
1885 " (Min: %d Max: %d)", ccxMode,
1886 CFG_CCX_FEATURE_ENABLED_MIN,
1887 CFG_CCX_FEATURE_ENABLED_MAX);
1888 ret = -EINVAL;
1889 goto exit;
1890 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1892 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1893
1894 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1895 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1896 }
1897#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001898 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1899 {
1900 tANI_U8 *value = command;
1901 tANI_BOOLEAN roamScanControl = 0;
1902
1903 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1904 value = value + 19;
1905 /* Convert the value from ascii to integer */
1906 ret = kstrtou8(value, 10, &roamScanControl);
1907 if (ret < 0)
1908 {
1909 /* If the input value is greater than max value of datatype, then also
1910 kstrtou8 fails */
1911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1912 "%s: kstrtou8 failed ", __func__);
1913 ret = -EINVAL;
1914 goto exit;
1915 }
1916
1917 if (0 != roamScanControl)
1918 {
1919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1920 "roam scan control invalid value = %d",
1921 roamScanControl);
1922 ret = -EINVAL;
1923 goto exit;
1924 }
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1926 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1927
1928 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1929 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001930#ifdef FEATURE_WLAN_OKC
1931 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1932 {
1933 tANI_U8 *value = command;
1934 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1935
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001936 /* Check if the features OKC/CCX/11R are supported simultaneously,
1937 then this operation is not permitted (return FAILURE) */
1938 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1939 hdd_is_okc_mode_enabled(pHddCtx) &&
1940 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1941 {
1942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1943 "%s: OKC/CCX/11R are supported simultaneously"
1944 " hence this operation is not permitted!", __func__);
1945 ret = -EPERM;
1946 goto exit;
1947 }
1948
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001949 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1950 value = value + 11;
1951 /* Convert the value from ascii to integer */
1952 ret = kstrtou8(value, 10, &okcMode);
1953 if (ret < 0)
1954 {
1955 /* If the input value is greater than max value of datatype, then also
1956 kstrtou8 fails */
1957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1958 "%s: kstrtou8 failed range [%d - %d]", __func__,
1959 CFG_OKC_FEATURE_ENABLED_MIN,
1960 CFG_OKC_FEATURE_ENABLED_MAX);
1961 ret = -EINVAL;
1962 goto exit;
1963 }
1964
1965 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1966 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1967 {
1968 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1969 "Okc mode value %d is out of range"
1970 " (Min: %d Max: %d)", okcMode,
1971 CFG_OKC_FEATURE_ENABLED_MIN,
1972 CFG_OKC_FEATURE_ENABLED_MAX);
1973 ret = -EINVAL;
1974 goto exit;
1975 }
1976
1977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1978 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1979
1980 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1981 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001982 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1983 {
1984 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1985 char extra[32];
1986 tANI_U8 len = 0;
1987
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001988 len = scnprintf(extra, sizeof(extra), "%s %d",
1989 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001990 if (copy_to_user(priv_data.buf, &extra, len + 1))
1991 {
1992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1993 "%s: failed to copy data to user buffer", __func__);
1994 ret = -EFAULT;
1995 goto exit;
1996 }
1997 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001998#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301999#ifdef WLAN_FEATURE_PACKET_FILTERING
2000 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2001 {
2002 tANI_U8 filterType = 0;
2003 tANI_U8 *value = command;
2004
2005 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2006 value = value + 22;
2007
2008 /* Convert the value from ascii to integer */
2009 ret = kstrtou8(value, 10, &filterType);
2010 if (ret < 0)
2011 {
2012 /* If the input value is greater than max value of datatype,
2013 * then also kstrtou8 fails
2014 */
2015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2016 "%s: kstrtou8 failed range ", __func__);
2017 ret = -EINVAL;
2018 goto exit;
2019 }
2020
2021 if (filterType != 0 && filterType != 1)
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2024 "%s: Accepted Values are 0 and 1 ", __func__);
2025 ret = -EINVAL;
2026 goto exit;
2027 }
2028 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2029 pAdapter->sessionId);
2030 }
2031#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302032 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2033 {
2034 char *dhcpPhase;
2035 dhcpPhase = command + 12;
2036 if ('1' == *dhcpPhase)
2037 {
2038 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2039 pAdapter->macAddressCurrent.bytes);
2040 }
2041 else if ('2' == *dhcpPhase)
2042 {
2043 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2044 pAdapter->macAddressCurrent.bytes);
2045 }
2046 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002047 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2048 {
2049 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2050 }
2051 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2052 {
2053 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2054 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302055 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2056 {
2057 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2058 char extra[32];
2059 tANI_U8 len = 0;
2060
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002061 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302062 (int)pCfg->nActiveMaxChnTime);
2063 if (copy_to_user(priv_data.buf, &extra, len + 1))
2064 {
2065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2066 "%s: failed to copy data to user buffer", __func__);
2067 ret = -EFAULT;
2068 goto exit;
2069 }
2070 ret = len;
2071 }
2072 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2073 {
2074 tANI_U8 *value = command;
2075 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2076 int val = 0, temp;
2077
2078 value = value + 13;
2079 temp = kstrtou32(value, 10, &val);
2080 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2081 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2082 {
2083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2084 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2085 ret = -EFAULT;
2086 goto exit;
2087 }
2088 pCfg->nActiveMaxChnTime = val;
2089 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002090 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2091 {
2092 tANI_U8 filterType = 0;
2093 tANI_U8 *value;
2094 value = command + 9;
2095
2096 /* Convert the value from ascii to integer */
2097 ret = kstrtou8(value, 10, &filterType);
2098 if (ret < 0)
2099 {
2100 /* If the input value is greater than max value of datatype,
2101 * then also kstrtou8 fails
2102 */
2103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2104 "%s: kstrtou8 failed range ", __func__);
2105 ret = -EINVAL;
2106 goto exit;
2107 }
2108 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2109 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2110 {
2111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2112 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2113 " 2-Sink ", __func__);
2114 ret = -EINVAL;
2115 goto exit;
2116 }
2117 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2118 pHddCtx->drvr_miracast = filterType;
2119 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2120 }
Leo Chang614d2072013-08-22 14:59:44 -07002121 else if (strncmp(command, "SETMCRATE", 9) == 0)
2122 {
2123 int rc;
2124 tANI_U8 *value = command;
2125 int targetRate;
2126
2127 /* Only valid for SAP mode */
2128 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2129 {
2130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2131 "%s: SAP mode is not running", __func__);
2132 ret = -EFAULT;
2133 goto exit;
2134 }
2135
2136 /* Move pointer to ahead of SETMCRATE<delimiter> */
2137 /* input value is in units of hundred kbps */
2138 value = value + 10;
2139 /* Convert the value from ascii to integer, decimal base */
2140 ret = kstrtouint(value, 10, &targetRate);
2141
2142 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2143 if (rc)
2144 {
2145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2146 "%s: Set MC Rate Fail %d", __func__, rc);
2147 ret = -EFAULT;
2148 goto exit;
2149 }
2150 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002151 else {
2152 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2153 __func__, command);
2154 }
2155
Jeff Johnson295189b2012-06-20 16:38:30 -07002156 }
2157exit:
2158 if (command)
2159 {
2160 kfree(command);
2161 }
2162 return ret;
2163}
2164
Srinivas Girigowdade697412013-02-14 16:31:48 -08002165#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2166void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2167{
2168 eCsrBand band = -1;
2169 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2170 switch (band)
2171 {
2172 case eCSR_BAND_ALL:
2173 *pBand = WLAN_HDD_UI_BAND_AUTO;
2174 break;
2175
2176 case eCSR_BAND_24:
2177 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2178 break;
2179
2180 case eCSR_BAND_5G:
2181 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2182 break;
2183
2184 default:
2185 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2186 *pBand = -1;
2187 break;
2188 }
2189}
2190
2191/**---------------------------------------------------------------------------
2192
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002193 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2194
2195 This function parses the send action frame data passed in the format
2196 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2197
Srinivas Girigowda56076852013-08-20 14:00:50 -07002198 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002199 \param - pTargetApBssid Pointer to target Ap bssid
2200 \param - pChannel Pointer to the Target AP channel
2201 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2202 \param - pBuf Pointer to data
2203 \param - pBufLen Pointer to data length
2204
2205 \return - 0 for success non-zero for failure
2206
2207 --------------------------------------------------------------------------*/
2208VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2209 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2210{
2211 tANI_U8 *inPtr = pValue;
2212 tANI_U8 *dataEnd;
2213 int tempInt;
2214 int j = 0;
2215 int i = 0;
2216 int v = 0;
2217 tANI_U8 tempBuf[32];
2218 tANI_U8 tempByte = 0;
2219
2220 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2221 /*no argument after the command*/
2222 if (NULL == inPtr)
2223 {
2224 return -EINVAL;
2225 }
2226
2227 /*no space after the command*/
2228 else if (SPACE_ASCII_VALUE != *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 /*removing empty spaces*/
2234 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2235
2236 /*no argument followed by spaces*/
2237 if ('\0' == *inPtr)
2238 {
2239 return -EINVAL;
2240 }
2241
2242 /*getting the first argument ie the target AP bssid */
2243 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2244 {
2245 return -EINVAL;
2246 }
2247 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2248 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2249 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2250
2251 /* point to the next argument */
2252 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2253 /*no argument after the command*/
2254 if (NULL == inPtr) return -EINVAL;
2255
2256 /*removing empty spaces*/
2257 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2258
2259 /*no argument followed by spaces*/
2260 if ('\0' == *inPtr)
2261 {
2262 return -EINVAL;
2263 }
2264
2265 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002266 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002267 v = kstrtos32(tempBuf, 10, &tempInt);
2268 if ( v < 0) return -EINVAL;
2269
2270 *pChannel = tempInt;
2271
2272 /* point to the next argument */
2273 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2274 /*no argument after the command*/
2275 if (NULL == inPtr) return -EINVAL;
2276 /*removing empty spaces*/
2277 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2278
2279 /*no argument followed by spaces*/
2280 if ('\0' == *inPtr)
2281 {
2282 return -EINVAL;
2283 }
2284
2285 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002286 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002287 v = kstrtos32(tempBuf, 10, &tempInt);
2288 if ( v < 0) return -EINVAL;
2289
2290 *pDwellTime = tempInt;
2291
2292 /* point to the next argument */
2293 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2294 /*no argument after the command*/
2295 if (NULL == inPtr) return -EINVAL;
2296 /*removing empty spaces*/
2297 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2298
2299 /*no argument followed by spaces*/
2300 if ('\0' == *inPtr)
2301 {
2302 return -EINVAL;
2303 }
2304
2305 /* find the length of data */
2306 dataEnd = inPtr;
2307 while(('\0' != *dataEnd) )
2308 {
2309 dataEnd++;
2310 ++(*pBufLen);
2311 }
2312 if ( *pBufLen <= 0) return -EINVAL;
2313
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002314 /* Allocate the number of bytes based on the number of input characters
2315 whether it is even or odd.
2316 if the number of input characters are even, then we need N/2 byte.
2317 if the number of input characters are odd, then we need do (N+1)/2 to
2318 compensate rounding off.
2319 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2320 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2321 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002322 if (NULL == *pBuf)
2323 {
2324 hddLog(VOS_TRACE_LEVEL_FATAL,
2325 "%s: vos_mem_alloc failed ", __func__);
2326 return -EINVAL;
2327 }
2328
2329 /* the buffer received from the upper layer is character buffer,
2330 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2331 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2332 and f0 in 3rd location */
2333 for (i = 0, j = 0; j < *pBufLen; j += 2)
2334 {
2335 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2336 (*pBuf)[i++] = tempByte;
2337 }
2338 *pBufLen = i;
2339 return VOS_STATUS_SUCCESS;
2340}
2341
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002342/**---------------------------------------------------------------------------
2343
Srinivas Girigowdade697412013-02-14 16:31:48 -08002344 \brief hdd_parse_channellist() - HDD Parse channel list
2345
2346 This function parses the channel list passed in the format
2347 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002348 if the Number of channels (N) does not match with the actual number of channels passed
2349 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2350 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2351 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2352 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002353
2354 \param - pValue Pointer to input channel list
2355 \param - ChannelList Pointer to local output array to record channel list
2356 \param - pNumChannels Pointer to number of roam scan channels
2357
2358 \return - 0 for success non-zero for failure
2359
2360 --------------------------------------------------------------------------*/
2361VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2362{
2363 tANI_U8 *inPtr = pValue;
2364 int tempInt;
2365 int j = 0;
2366 int v = 0;
2367 char buf[32];
2368
2369 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2370 /*no argument after the command*/
2371 if (NULL == inPtr)
2372 {
2373 return -EINVAL;
2374 }
2375
2376 /*no space after the command*/
2377 else if (SPACE_ASCII_VALUE != *inPtr)
2378 {
2379 return -EINVAL;
2380 }
2381
2382 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002383 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384
2385 /*no argument followed by spaces*/
2386 if ('\0' == *inPtr)
2387 {
2388 return -EINVAL;
2389 }
2390
2391 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002392 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002393 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002394 if ((v < 0) ||
2395 (tempInt <= 0) ||
2396 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2397 {
2398 return -EINVAL;
2399 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002400
2401 *pNumChannels = tempInt;
2402
2403 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2404 "Number of channels are: %d", *pNumChannels);
2405
2406 for (j = 0; j < (*pNumChannels); j++)
2407 {
2408 /*inPtr pointing to the beginning of first space after number of channels*/
2409 inPtr = strpbrk( inPtr, " " );
2410 /*no channel list after the number of channels argument*/
2411 if (NULL == inPtr)
2412 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002413 if (0 != j)
2414 {
2415 *pNumChannels = j;
2416 return VOS_STATUS_SUCCESS;
2417 }
2418 else
2419 {
2420 return -EINVAL;
2421 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002422 }
2423
2424 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002425 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002426
2427 /*no channel list after the number of channels argument and spaces*/
2428 if ( '\0' == *inPtr )
2429 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002430 if (0 != j)
2431 {
2432 *pNumChannels = j;
2433 return VOS_STATUS_SUCCESS;
2434 }
2435 else
2436 {
2437 return -EINVAL;
2438 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002439 }
2440
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002441 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002442 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002443 if ((v < 0) ||
2444 (tempInt <= 0) ||
2445 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2446 {
2447 return -EINVAL;
2448 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002449 pChannelList[j] = tempInt;
2450
2451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2452 "Channel %d added to preferred channel list",
2453 pChannelList[j] );
2454 }
2455
Srinivas Girigowdade697412013-02-14 16:31:48 -08002456 return VOS_STATUS_SUCCESS;
2457}
2458
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002459
2460/**---------------------------------------------------------------------------
2461
2462 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2463
2464 This function parses the reasoc command data passed in the format
2465 REASSOC<space><bssid><space><channel>
2466
Srinivas Girigowda56076852013-08-20 14:00:50 -07002467 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002468 \param - pTargetApBssid Pointer to target Ap bssid
2469 \param - pChannel Pointer to the Target AP channel
2470
2471 \return - 0 for success non-zero for failure
2472
2473 --------------------------------------------------------------------------*/
2474VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2475{
2476 tANI_U8 *inPtr = pValue;
2477 int tempInt;
2478 int v = 0;
2479 tANI_U8 tempBuf[32];
2480
2481 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2482 /*no argument after the command*/
2483 if (NULL == inPtr)
2484 {
2485 return -EINVAL;
2486 }
2487
2488 /*no space after the command*/
2489 else if (SPACE_ASCII_VALUE != *inPtr)
2490 {
2491 return -EINVAL;
2492 }
2493
2494 /*removing empty spaces*/
2495 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2496
2497 /*no argument followed by spaces*/
2498 if ('\0' == *inPtr)
2499 {
2500 return -EINVAL;
2501 }
2502
2503 /*getting the first argument ie the target AP bssid */
2504 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2505 {
2506 return -EINVAL;
2507 }
2508 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2509 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2510 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2511
2512 /* point to the next argument */
2513 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2514 /*no argument after the command*/
2515 if (NULL == inPtr) return -EINVAL;
2516
2517 /*removing empty spaces*/
2518 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2519
2520 /*no argument followed by spaces*/
2521 if ('\0' == *inPtr)
2522 {
2523 return -EINVAL;
2524 }
2525
2526 /*getting the next argument ie the channel number */
2527 sscanf(inPtr, "%s ", tempBuf);
2528 v = kstrtos32(tempBuf, 10, &tempInt);
2529 if ( v < 0) return -EINVAL;
2530
2531 *pChannel = tempInt;
2532 return VOS_STATUS_SUCCESS;
2533}
2534
2535#endif
2536
Jeff Johnson295189b2012-06-20 16:38:30 -07002537/**---------------------------------------------------------------------------
2538
2539 \brief hdd_open() - HDD Open function
2540
2541 This is called in response to ifconfig up
2542
2543 \param - dev Pointer to net_device structure
2544
2545 \return - 0 for success non-zero for failure
2546
2547 --------------------------------------------------------------------------*/
2548int hdd_open (struct net_device *dev)
2549{
2550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2551 hdd_context_t *pHddCtx;
2552 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2553 VOS_STATUS status;
2554 v_BOOL_t in_standby = TRUE;
2555
2556 if (NULL == pAdapter)
2557 {
2558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002559 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 return -ENODEV;
2561 }
2562
2563 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2564 if (NULL == pHddCtx)
2565 {
2566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002567 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002568 return -ENODEV;
2569 }
2570
2571 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2572 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2573 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002574 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2575 {
2576 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302577 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002578 in_standby = FALSE;
2579 break;
2580 }
2581 else
2582 {
2583 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2584 pAdapterNode = pNext;
2585 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 }
2587
2588 if (TRUE == in_standby)
2589 {
2590 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2591 {
2592 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2593 "wlan out of power save", __func__);
2594 return -EINVAL;
2595 }
2596 }
2597
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002598 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2600 {
2601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002602 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 /* Enable TX queues only when we are connected */
2604 netif_tx_start_all_queues(dev);
2605 }
2606
2607 return 0;
2608}
2609
2610int hdd_mon_open (struct net_device *dev)
2611{
2612 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2613
2614 if(pAdapter == NULL) {
2615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002616 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002617 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002618 }
2619
2620 netif_start_queue(dev);
2621
2622 return 0;
2623}
2624/**---------------------------------------------------------------------------
2625
2626 \brief hdd_stop() - HDD stop function
2627
2628 This is called in response to ifconfig down
2629
2630 \param - dev Pointer to net_device structure
2631
2632 \return - 0 for success non-zero for failure
2633
2634 --------------------------------------------------------------------------*/
2635
2636int hdd_stop (struct net_device *dev)
2637{
2638 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2639 hdd_context_t *pHddCtx;
2640 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2641 VOS_STATUS status;
2642 v_BOOL_t enter_standby = TRUE;
2643
2644 ENTER();
2645
2646 if (NULL == pAdapter)
2647 {
2648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002649 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002650 return -ENODEV;
2651 }
2652
2653 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2654 if (NULL == pHddCtx)
2655 {
2656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002657 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002658 return -ENODEV;
2659 }
2660
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002661 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002662 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2663 netif_tx_disable(pAdapter->dev);
2664 netif_carrier_off(pAdapter->dev);
2665
2666
2667 /* SoftAP ifaces should never go in power save mode
2668 making sure same here. */
2669 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2670 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002671 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002672 )
2673 {
2674 /* SoftAP mode, so return from here */
2675 EXIT();
2676 return 0;
2677 }
2678
2679 /* Find if any iface is up then
2680 if any iface is up then can't put device to sleep/ power save mode. */
2681 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2682 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2683 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002684 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2685 {
2686 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302687 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002688 enter_standby = FALSE;
2689 break;
2690 }
2691 else
2692 {
2693 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2694 pAdapterNode = pNext;
2695 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002696 }
2697
2698 if (TRUE == enter_standby)
2699 {
2700 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2701 "entering standby", __func__);
2702 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2703 {
2704 /*log and return success*/
2705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2706 "wlan in power save", __func__);
2707 }
2708 }
2709
2710 EXIT();
2711 return 0;
2712}
2713
2714/**---------------------------------------------------------------------------
2715
2716 \brief hdd_uninit() - HDD uninit function
2717
2718 This is called during the netdev unregister to uninitialize all data
2719associated with the device
2720
2721 \param - dev Pointer to net_device structure
2722
2723 \return - void
2724
2725 --------------------------------------------------------------------------*/
2726static void hdd_uninit (struct net_device *dev)
2727{
2728 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2729
2730 ENTER();
2731
2732 do
2733 {
2734 if (NULL == pAdapter)
2735 {
2736 hddLog(VOS_TRACE_LEVEL_FATAL,
2737 "%s: NULL pAdapter", __func__);
2738 break;
2739 }
2740
2741 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2742 {
2743 hddLog(VOS_TRACE_LEVEL_FATAL,
2744 "%s: Invalid magic", __func__);
2745 break;
2746 }
2747
2748 if (NULL == pAdapter->pHddCtx)
2749 {
2750 hddLog(VOS_TRACE_LEVEL_FATAL,
2751 "%s: NULL pHddCtx", __func__);
2752 break;
2753 }
2754
2755 if (dev != pAdapter->dev)
2756 {
2757 hddLog(VOS_TRACE_LEVEL_FATAL,
2758 "%s: Invalid device reference", __func__);
2759 /* we haven't validated all cases so let this go for now */
2760 }
2761
2762 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2763
2764 /* after uninit our adapter structure will no longer be valid */
2765 pAdapter->dev = NULL;
2766 pAdapter->magic = 0;
2767 } while (0);
2768
2769 EXIT();
2770}
2771
2772/**---------------------------------------------------------------------------
2773
2774 \brief hdd_release_firmware() -
2775
2776 This function calls the release firmware API to free the firmware buffer.
2777
2778 \param - pFileName Pointer to the File Name.
2779 pCtx - Pointer to the adapter .
2780
2781
2782 \return - 0 for success, non zero for failure
2783
2784 --------------------------------------------------------------------------*/
2785
2786VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2787{
2788 VOS_STATUS status = VOS_STATUS_SUCCESS;
2789 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2790 ENTER();
2791
2792
2793 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2794
2795 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2796
2797 if(pHddCtx->fw) {
2798 release_firmware(pHddCtx->fw);
2799 pHddCtx->fw = NULL;
2800 }
2801 else
2802 status = VOS_STATUS_E_FAILURE;
2803 }
2804 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2805 if(pHddCtx->nv) {
2806 release_firmware(pHddCtx->nv);
2807 pHddCtx->nv = NULL;
2808 }
2809 else
2810 status = VOS_STATUS_E_FAILURE;
2811
2812 }
2813
2814 EXIT();
2815 return status;
2816}
2817
2818/**---------------------------------------------------------------------------
2819
2820 \brief hdd_request_firmware() -
2821
2822 This function reads the firmware file using the request firmware
2823 API and returns the the firmware data and the firmware file size.
2824
2825 \param - pfileName - Pointer to the file name.
2826 - pCtx - Pointer to the adapter .
2827 - ppfw_data - Pointer to the pointer of the firmware data.
2828 - pSize - Pointer to the file size.
2829
2830 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2831
2832 --------------------------------------------------------------------------*/
2833
2834
2835VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2836{
2837 int status;
2838 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2839 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2840 ENTER();
2841
2842 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2843
2844 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2845
2846 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2847 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2848 __func__, pfileName);
2849 retval = VOS_STATUS_E_FAILURE;
2850 }
2851
2852 else {
2853 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2854 *pSize = pHddCtx->fw->size;
2855 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2856 __func__, *pSize);
2857 }
2858 }
2859 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2860
2861 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2862
2863 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2865 __func__, pfileName);
2866 retval = VOS_STATUS_E_FAILURE;
2867 }
2868
2869 else {
2870 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2871 *pSize = pHddCtx->nv->size;
2872 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2873 __func__, *pSize);
2874 }
2875 }
2876
2877 EXIT();
2878 return retval;
2879}
2880/**---------------------------------------------------------------------------
2881 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2882
2883 This is the function invoked by SME to inform the result of a full power
2884 request issued by HDD
2885
2886 \param - callbackcontext - Pointer to cookie
2887 status - result of request
2888
2889 \return - None
2890
2891--------------------------------------------------------------------------*/
2892void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2893{
2894 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2895
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002896 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002897 if(&pHddCtx->full_pwr_comp_var)
2898 {
2899 complete(&pHddCtx->full_pwr_comp_var);
2900 }
2901}
2902
2903/**---------------------------------------------------------------------------
2904
2905 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2906
2907 This is the function invoked by SME to inform the result of BMPS
2908 request issued by HDD
2909
2910 \param - callbackcontext - Pointer to cookie
2911 status - result of request
2912
2913 \return - None
2914
2915--------------------------------------------------------------------------*/
2916void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2917{
2918
2919 struct completion *completion_var = (struct completion*) callbackContext;
2920
2921 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2922 if(completion_var != NULL)
2923 {
2924 complete(completion_var);
2925 }
2926}
2927
2928/**---------------------------------------------------------------------------
2929
2930 \brief hdd_get_cfg_file_size() -
2931
2932 This function reads the configuration file using the request firmware
2933 API and returns the configuration file size.
2934
2935 \param - pCtx - Pointer to the adapter .
2936 - pFileName - Pointer to the file name.
2937 - pBufSize - Pointer to the buffer size.
2938
2939 \return - 0 for success, non zero for failure
2940
2941 --------------------------------------------------------------------------*/
2942
2943VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2944{
2945 int status;
2946 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2947
2948 ENTER();
2949
2950 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2951
2952 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2954 status = VOS_STATUS_E_FAILURE;
2955 }
2956 else {
2957 *pBufSize = pHddCtx->fw->size;
2958 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2959 release_firmware(pHddCtx->fw);
2960 pHddCtx->fw = NULL;
2961 }
2962
2963 EXIT();
2964 return VOS_STATUS_SUCCESS;
2965}
2966
2967/**---------------------------------------------------------------------------
2968
2969 \brief hdd_read_cfg_file() -
2970
2971 This function reads the configuration file using the request firmware
2972 API and returns the cfg data and the buffer size of the configuration file.
2973
2974 \param - pCtx - Pointer to the adapter .
2975 - pFileName - Pointer to the file name.
2976 - pBuffer - Pointer to the data buffer.
2977 - pBufSize - Pointer to the buffer size.
2978
2979 \return - 0 for success, non zero for failure
2980
2981 --------------------------------------------------------------------------*/
2982
2983VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2984 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2985{
2986 int status;
2987 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2988
2989 ENTER();
2990
2991 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2992
2993 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2994 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2995 return VOS_STATUS_E_FAILURE;
2996 }
2997 else {
2998 if(*pBufSize != pHddCtx->fw->size) {
2999 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
3000 "file size", __func__);
3001 release_firmware(pHddCtx->fw);
3002 pHddCtx->fw = NULL;
3003 return VOS_STATUS_E_FAILURE;
3004 }
3005 else {
3006 if(pBuffer) {
3007 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
3008 }
3009 release_firmware(pHddCtx->fw);
3010 pHddCtx->fw = NULL;
3011 }
3012 }
3013
3014 EXIT();
3015
3016 return VOS_STATUS_SUCCESS;
3017}
3018
3019/**---------------------------------------------------------------------------
3020
Jeff Johnson295189b2012-06-20 16:38:30 -07003021 \brief hdd_set_mac_address() -
3022
3023 This function sets the user specified mac address using
3024 the command ifconfig wlanX hw ether <mac adress>.
3025
3026 \param - dev - Pointer to the net device.
3027 - addr - Pointer to the sockaddr.
3028 \return - 0 for success, non zero for failure
3029
3030 --------------------------------------------------------------------------*/
3031
3032static int hdd_set_mac_address(struct net_device *dev, void *addr)
3033{
3034 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3035 struct sockaddr *psta_mac_addr = addr;
3036 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3037
3038 ENTER();
3039
3040 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3041
3042#ifdef HDD_SESSIONIZE
3043 // set the MAC address though the STA ID CFG.
3044 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3045 (v_U8_t *)&pAdapter->macAddressCurrent,
3046 sizeof( pAdapter->macAddressCurrent ),
3047 hdd_set_mac_addr_cb, VOS_FALSE );
3048#endif
3049
3050 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3051
3052 EXIT();
3053 return halStatus;
3054}
3055
3056tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3057{
3058 int i;
3059 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3060 {
3061 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3062 break;
3063 }
3064
3065 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3066 return NULL;
3067
3068 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3069 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3070}
3071
3072void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3073{
3074 int i;
3075 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3076 {
3077 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3078 {
3079 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3080 break;
3081 }
3082 }
3083 return;
3084}
3085
3086#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3087 static struct net_device_ops wlan_drv_ops = {
3088 .ndo_open = hdd_open,
3089 .ndo_stop = hdd_stop,
3090 .ndo_uninit = hdd_uninit,
3091 .ndo_start_xmit = hdd_hard_start_xmit,
3092 .ndo_tx_timeout = hdd_tx_timeout,
3093 .ndo_get_stats = hdd_stats,
3094 .ndo_do_ioctl = hdd_ioctl,
3095 .ndo_set_mac_address = hdd_set_mac_address,
3096 .ndo_select_queue = hdd_select_queue,
3097#ifdef WLAN_FEATURE_PACKET_FILTERING
3098#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3099 .ndo_set_rx_mode = hdd_set_multicast_list,
3100#else
3101 .ndo_set_multicast_list = hdd_set_multicast_list,
3102#endif //LINUX_VERSION_CODE
3103#endif
3104 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003105 static struct net_device_ops wlan_mon_drv_ops = {
3106 .ndo_open = hdd_mon_open,
3107 .ndo_stop = hdd_stop,
3108 .ndo_uninit = hdd_uninit,
3109 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3110 .ndo_tx_timeout = hdd_tx_timeout,
3111 .ndo_get_stats = hdd_stats,
3112 .ndo_do_ioctl = hdd_ioctl,
3113 .ndo_set_mac_address = hdd_set_mac_address,
3114 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003115
3116#endif
3117
3118void hdd_set_station_ops( struct net_device *pWlanDev )
3119{
3120#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3121 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3122 pWlanDev->netdev_ops = &wlan_drv_ops;
3123#else
3124 pWlanDev->open = hdd_open;
3125 pWlanDev->stop = hdd_stop;
3126 pWlanDev->uninit = hdd_uninit;
3127 pWlanDev->hard_start_xmit = NULL;
3128 pWlanDev->tx_timeout = hdd_tx_timeout;
3129 pWlanDev->get_stats = hdd_stats;
3130 pWlanDev->do_ioctl = hdd_ioctl;
3131 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3132 pWlanDev->set_mac_address = hdd_set_mac_address;
3133#endif
3134}
3135
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003136static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003137{
3138 struct net_device *pWlanDev = NULL;
3139 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003140 /*
3141 * cfg80211 initialization and registration....
3142 */
3143 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3144
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 if(pWlanDev != NULL)
3146 {
3147
3148 //Save the pointer to the net_device in the HDD adapter
3149 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3150
Jeff Johnson295189b2012-06-20 16:38:30 -07003151 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3152
3153 pAdapter->dev = pWlanDev;
3154 pAdapter->pHddCtx = pHddCtx;
3155 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3156
3157 init_completion(&pAdapter->session_open_comp_var);
3158 init_completion(&pAdapter->session_close_comp_var);
3159 init_completion(&pAdapter->disconnect_comp_var);
3160 init_completion(&pAdapter->linkup_event_var);
3161 init_completion(&pAdapter->cancel_rem_on_chan_var);
3162 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003163#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3164 init_completion(&pAdapter->offchannel_tx_event);
3165#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003166 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003167#ifdef FEATURE_WLAN_TDLS
3168 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003169 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003170 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303171 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003173 init_completion(&pHddCtx->mc_sus_event_var);
3174 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303175 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003176 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003177 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07003178
Jeff Johnson295189b2012-06-20 16:38:30 -07003179 pAdapter->isLinkUpSvcNeeded = FALSE;
3180 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3181 //Init the net_device structure
3182 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3183
3184 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3185 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3186 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3187 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3188
3189 hdd_set_station_ops( pAdapter->dev );
3190
3191 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003192 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3193 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3194 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 /* set pWlanDev's parent to underlying device */
3196 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3197 }
3198
3199 return pAdapter;
3200}
3201
3202VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3203{
3204 struct net_device *pWlanDev = pAdapter->dev;
3205 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3206 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3207 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3208
3209 if( rtnl_lock_held )
3210 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003211 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003212 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3213 {
3214 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3215 return VOS_STATUS_E_FAILURE;
3216 }
3217 }
3218 if (register_netdevice(pWlanDev))
3219 {
3220 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3221 return VOS_STATUS_E_FAILURE;
3222 }
3223 }
3224 else
3225 {
3226 if(register_netdev(pWlanDev))
3227 {
3228 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3229 return VOS_STATUS_E_FAILURE;
3230 }
3231 }
3232 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3233
3234 return VOS_STATUS_SUCCESS;
3235}
3236
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003237static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003238{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003239 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003240
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003241 if (NULL == pAdapter)
3242 {
3243 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3244 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003246
3247 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3248 {
3249 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3250 return eHAL_STATUS_NOT_INITIALIZED;
3251 }
3252
3253 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3254
3255 /* need to make sure all of our scheduled work has completed.
3256 * This callback is called from MC thread context, so it is safe to
3257 * to call below flush workqueue API from here.
3258 */
3259 flush_scheduled_work();
3260
3261 /* We can be blocked while waiting for scheduled work to be
3262 * flushed, and the adapter structure can potentially be freed, in
3263 * which case the magic will have been reset. So make sure the
3264 * magic is still good, and hence the adapter structure is still
3265 * valid, before signaling completion */
3266 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3267 {
3268 complete(&pAdapter->session_close_comp_var);
3269 }
3270
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 return eHAL_STATUS_SUCCESS;
3272}
3273
3274VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3275{
3276 struct net_device *pWlanDev = pAdapter->dev;
3277 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3278 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3279 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3280 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3281 int rc = 0;
3282
3283 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003284 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 //Open a SME session for future operation
3286 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003287 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003288 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3289 {
3290 hddLog(VOS_TRACE_LEVEL_FATAL,
3291 "sme_OpenSession() failed with status code %08d [x%08lx]",
3292 halStatus, halStatus );
3293 status = VOS_STATUS_E_FAILURE;
3294 goto error_sme_open;
3295 }
3296
3297 //Block on a completion variable. Can't wait forever though.
3298 rc = wait_for_completion_interruptible_timeout(
3299 &pAdapter->session_open_comp_var,
3300 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3301 if (!rc)
3302 {
3303 hddLog(VOS_TRACE_LEVEL_FATAL,
3304 "Session is not opened within timeout period code %08d", rc );
3305 status = VOS_STATUS_E_FAILURE;
3306 goto error_sme_open;
3307 }
3308
3309 // Register wireless extensions
3310 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3311 {
3312 hddLog(VOS_TRACE_LEVEL_FATAL,
3313 "hdd_register_wext() failed with status code %08d [x%08lx]",
3314 halStatus, halStatus );
3315 status = VOS_STATUS_E_FAILURE;
3316 goto error_register_wext;
3317 }
3318 //Safe to register the hard_start_xmit function again
3319#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3320 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3321#else
3322 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3323#endif
3324
3325 //Set the Connection State to Not Connected
3326 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3327
3328 //Set the default operation channel
3329 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3330
3331 /* Make the default Auth Type as OPEN*/
3332 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3333
3334 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3335 {
3336 hddLog(VOS_TRACE_LEVEL_FATAL,
3337 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3338 status, status );
3339 goto error_init_txrx;
3340 }
3341
3342 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3343
3344 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3345 {
3346 hddLog(VOS_TRACE_LEVEL_FATAL,
3347 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3348 status, status );
3349 goto error_wmm_init;
3350 }
3351
3352 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3353
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003354#ifdef FEATURE_WLAN_TDLS
3355 if(0 != wlan_hdd_tdls_init(pAdapter))
3356 {
3357 status = VOS_STATUS_E_FAILURE;
3358 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3359 goto error_tdls_init;
3360 }
3361 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3362#endif
3363
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 return VOS_STATUS_SUCCESS;
3365
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003366#ifdef FEATURE_WLAN_TDLS
3367error_tdls_init:
3368 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3369 hdd_wmm_adapter_close(pAdapter);
3370#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003371error_wmm_init:
3372 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3373 hdd_deinit_tx_rx(pAdapter);
3374error_init_txrx:
3375 hdd_UnregisterWext(pWlanDev);
3376error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003377 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 {
3379 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003380 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003382 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003383 {
3384 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003385 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003387 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003388 }
3389}
3390error_sme_open:
3391 return status;
3392}
3393
Jeff Johnson295189b2012-06-20 16:38:30 -07003394void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3395{
3396 hdd_cfg80211_state_t *cfgState;
3397
3398 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3399
3400 if( NULL != cfgState->buf )
3401 {
3402 int rc;
3403 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3404 rc = wait_for_completion_interruptible_timeout(
3405 &pAdapter->tx_action_cnf_event,
3406 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3407 if(!rc)
3408 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003410 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3411 }
3412 }
3413 return;
3414}
Jeff Johnson295189b2012-06-20 16:38:30 -07003415
3416void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3417{
3418 ENTER();
3419 switch ( pAdapter->device_mode )
3420 {
3421 case WLAN_HDD_INFRA_STATION:
3422 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003423 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 {
3425 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3426 {
3427 hdd_deinit_tx_rx( pAdapter );
3428 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3429 }
3430
3431 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3432 {
3433 hdd_wmm_adapter_close( pAdapter );
3434 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3435 }
3436
Jeff Johnson295189b2012-06-20 16:38:30 -07003437 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003438#ifdef FEATURE_WLAN_TDLS
3439 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3440 {
3441 wlan_hdd_tdls_exit(pAdapter);
3442 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3443 }
3444#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003445
3446 break;
3447 }
3448
3449 case WLAN_HDD_SOFTAP:
3450 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003451 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05303452
3453 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3454 {
3455 hdd_wmm_adapter_close( pAdapter );
3456 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3457 }
3458
Jeff Johnson295189b2012-06-20 16:38:30 -07003459 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003460
3461 hdd_unregister_hostapd(pAdapter);
3462 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003463 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003464 break;
3465 }
3466
3467 case WLAN_HDD_MONITOR:
3468 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003469 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003470 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3471 {
3472 hdd_deinit_tx_rx( pAdapter );
3473 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003475 if(NULL != pAdapterforTx)
3476 {
3477 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003479 break;
3480 }
3481
3482
3483 default:
3484 break;
3485 }
3486
3487 EXIT();
3488}
3489
3490void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3491{
3492 struct net_device *pWlanDev = pAdapter->dev;
3493
3494 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3495 if( rtnl_held )
3496 {
3497 unregister_netdevice(pWlanDev);
3498 }
3499 else
3500 {
3501 unregister_netdev(pWlanDev);
3502 }
3503 // note that the pAdapter is no longer valid at this point
3504 // since the memory has been reclaimed
3505 }
3506
3507}
3508
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003509void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3510{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303511 VOS_STATUS status;
3512 hdd_adapter_t *pAdapter = NULL;
3513 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003514
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303515 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003516
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303517 /*loop through all adapters.*/
3518 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003519 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303520 pAdapter = pAdapterNode->pAdapter;
3521 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3522 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003523
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303524 { // we skip this registration for modes other than STA and P2P client modes.
3525 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3526 pAdapterNode = pNext;
3527 continue;
3528 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003529
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303530 //Apply Dynamic DTIM For P2P
3531 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3532 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3533 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3534 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3535 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3536 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3537 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3538 (eConnectionState_Associated ==
3539 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3540 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3541 {
3542 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003543
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303544 powerRequest.uIgnoreDTIM = 1;
3545 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3546
3547 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3548 {
3549 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3550 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3551 }
3552 else
3553 {
3554 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3555 }
3556
3557 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3558 * specified during Enter/Exit BMPS when LCD off*/
3559 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3560 NULL, eANI_BOOLEAN_FALSE);
3561 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3562 NULL, eANI_BOOLEAN_FALSE);
3563
3564 /* switch to the DTIM specified in cfg.ini */
3565 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3566 "Switch to DTIM %d", powerRequest.uListenInterval);
3567 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3568 break;
3569
3570 }
3571
3572 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3573 pAdapterNode = pNext;
3574 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003575}
3576
3577void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3578{
3579 /*Switch back to DTIM 1*/
3580 tSirSetPowerParamsReq powerRequest = { 0 };
3581
3582 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3583 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003584 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003585
3586 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3587 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3588 NULL, eANI_BOOLEAN_FALSE);
3589 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3590 NULL, eANI_BOOLEAN_FALSE);
3591
3592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3593 "Switch to DTIM%d",powerRequest.uListenInterval);
3594 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3595
3596}
3597
Jeff Johnson295189b2012-06-20 16:38:30 -07003598VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3599{
3600 VOS_STATUS status = VOS_STATUS_SUCCESS;
3601
3602 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3603 {
3604 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3605 }
3606
3607 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3608 {
3609 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3610 }
3611
3612 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3613 {
3614 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3615 }
3616
3617 return status;
3618}
3619
3620VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3621{
3622 hdd_adapter_t *pAdapter = NULL;
3623 eHalStatus halStatus;
3624 VOS_STATUS status = VOS_STATUS_E_INVAL;
3625 v_BOOL_t disableBmps = FALSE;
3626 v_BOOL_t disableImps = FALSE;
3627
3628 switch(session_type)
3629 {
3630 case WLAN_HDD_INFRA_STATION:
3631 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003632 case WLAN_HDD_P2P_CLIENT:
3633 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003634 //Exit BMPS -> Is Sta/P2P Client is already connected
3635 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3636 if((NULL != pAdapter)&&
3637 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3638 {
3639 disableBmps = TRUE;
3640 }
3641
3642 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3643 if((NULL != pAdapter)&&
3644 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3645 {
3646 disableBmps = TRUE;
3647 }
3648
3649 //Exit both Bmps and Imps incase of Go/SAP Mode
3650 if((WLAN_HDD_SOFTAP == session_type) ||
3651 (WLAN_HDD_P2P_GO == session_type))
3652 {
3653 disableBmps = TRUE;
3654 disableImps = TRUE;
3655 }
3656
3657 if(TRUE == disableImps)
3658 {
3659 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3660 {
3661 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3662 }
3663 }
3664
3665 if(TRUE == disableBmps)
3666 {
3667 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3668 {
3669 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3670
3671 if(eHAL_STATUS_SUCCESS != halStatus)
3672 {
3673 status = VOS_STATUS_E_FAILURE;
3674 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3675 VOS_ASSERT(0);
3676 return status;
3677 }
3678 }
3679
3680 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3681 {
3682 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3683
3684 if(eHAL_STATUS_SUCCESS != halStatus)
3685 {
3686 status = VOS_STATUS_E_FAILURE;
3687 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3688 VOS_ASSERT(0);
3689 return status;
3690 }
3691 }
3692 }
3693
3694 if((TRUE == disableBmps) ||
3695 (TRUE == disableImps))
3696 {
3697 /* Now, get the chip into Full Power now */
3698 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3699 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3700 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3701
3702 if(halStatus != eHAL_STATUS_SUCCESS)
3703 {
3704 if(halStatus == eHAL_STATUS_PMC_PENDING)
3705 {
3706 //Block on a completion variable. Can't wait forever though
3707 wait_for_completion_interruptible_timeout(
3708 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3709 }
3710 else
3711 {
3712 status = VOS_STATUS_E_FAILURE;
3713 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3714 VOS_ASSERT(0);
3715 return status;
3716 }
3717 }
3718
3719 status = VOS_STATUS_SUCCESS;
3720 }
3721
3722 break;
3723 }
3724 return status;
3725}
3726
3727hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003728 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 tANI_U8 rtnl_held )
3730{
3731 hdd_adapter_t *pAdapter = NULL;
3732 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3733 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3734 VOS_STATUS exitbmpsStatus;
3735
3736 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3737
3738 //Disable BMPS incase of Concurrency
3739 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3740
3741 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3742 {
3743 //Fail to Exit BMPS
3744 VOS_ASSERT(0);
3745 return NULL;
3746 }
3747
3748 switch(session_type)
3749 {
3750 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003752 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003753 {
3754 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3755
3756 if( NULL == pAdapter )
3757 return NULL;
3758
Jeff Johnsone7245742012-09-05 17:12:55 -07003759 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3760 NL80211_IFTYPE_P2P_CLIENT:
3761 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003762
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 pAdapter->device_mode = session_type;
3764
3765 status = hdd_init_station_mode( pAdapter );
3766 if( VOS_STATUS_SUCCESS != status )
3767 goto err_free_netdev;
3768
3769 status = hdd_register_interface( pAdapter, rtnl_held );
3770 if( VOS_STATUS_SUCCESS != status )
3771 {
3772 hdd_deinit_adapter(pHddCtx, pAdapter);
3773 goto err_free_netdev;
3774 }
3775 //Stop the Interface TX queue.
3776 netif_tx_disable(pAdapter->dev);
3777 //netif_tx_disable(pWlanDev);
3778 netif_carrier_off(pAdapter->dev);
3779
3780 break;
3781 }
3782
Jeff Johnson295189b2012-06-20 16:38:30 -07003783 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003784 case WLAN_HDD_SOFTAP:
3785 {
3786 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3787 if( NULL == pAdapter )
3788 return NULL;
3789
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3791 NL80211_IFTYPE_AP:
3792 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 pAdapter->device_mode = session_type;
3794
3795 status = hdd_init_ap_mode(pAdapter);
3796 if( VOS_STATUS_SUCCESS != status )
3797 goto err_free_netdev;
3798
3799 status = hdd_register_hostapd( pAdapter, rtnl_held );
3800 if( VOS_STATUS_SUCCESS != status )
3801 {
3802 hdd_deinit_adapter(pHddCtx, pAdapter);
3803 goto err_free_netdev;
3804 }
3805
3806 netif_tx_disable(pAdapter->dev);
3807 netif_carrier_off(pAdapter->dev);
3808
3809 hdd_set_conparam( 1 );
3810 break;
3811 }
3812 case WLAN_HDD_MONITOR:
3813 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003814 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3815 if( NULL == pAdapter )
3816 return NULL;
3817
3818 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3819 pAdapter->device_mode = session_type;
3820 status = hdd_register_interface( pAdapter, rtnl_held );
3821#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3822 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3823#else
3824 pAdapter->dev->open = hdd_mon_open;
3825 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3826#endif
3827 hdd_init_tx_rx( pAdapter );
3828 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3829 //Set adapter to be used for data tx. It will use either GO or softap.
3830 pAdapter->sessionCtx.monitor.pAdapterForTx =
3831 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003832 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3833 {
3834 pAdapter->sessionCtx.monitor.pAdapterForTx =
3835 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3836 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 /* This workqueue will be used to transmit management packet over
3838 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003839 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3840 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3841 return NULL;
3842 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003843
Jeff Johnson295189b2012-06-20 16:38:30 -07003844 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3845 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003846 }
3847 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003848 case WLAN_HDD_FTM:
3849 {
3850 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3851
3852 if( NULL == pAdapter )
3853 return NULL;
3854 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3855 * message while loading driver in FTM mode. */
3856 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3857 pAdapter->device_mode = session_type;
3858 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05303859
3860 hdd_init_tx_rx( pAdapter );
3861
3862 //Stop the Interface TX queue.
3863 netif_tx_disable(pAdapter->dev);
3864 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 }
3866 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003867 default:
3868 {
3869 VOS_ASSERT(0);
3870 return NULL;
3871 }
3872 }
3873
3874
3875 if( VOS_STATUS_SUCCESS == status )
3876 {
3877 //Add it to the hdd's session list.
3878 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3879 if( NULL == pHddAdapterNode )
3880 {
3881 status = VOS_STATUS_E_NOMEM;
3882 }
3883 else
3884 {
3885 pHddAdapterNode->pAdapter = pAdapter;
3886 status = hdd_add_adapter_back ( pHddCtx,
3887 pHddAdapterNode );
3888 }
3889 }
3890
3891 if( VOS_STATUS_SUCCESS != status )
3892 {
3893 if( NULL != pAdapter )
3894 {
3895 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3896 pAdapter = NULL;
3897 }
3898 if( NULL != pHddAdapterNode )
3899 {
3900 vos_mem_free( pHddAdapterNode );
3901 }
3902
3903 goto resume_bmps;
3904 }
3905
3906 if(VOS_STATUS_SUCCESS == status)
3907 {
3908 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3909
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003910 //Initialize the WoWL service
3911 if(!hdd_init_wowl(pAdapter))
3912 {
3913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3914 goto err_free_netdev;
3915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003916 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003917 return pAdapter;
3918
3919err_free_netdev:
3920 free_netdev(pAdapter->dev);
3921 wlan_hdd_release_intf_addr( pHddCtx,
3922 pAdapter->macAddressCurrent.bytes );
3923
3924resume_bmps:
3925 //If bmps disabled enable it
3926 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3927 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303928 if (pHddCtx->hdd_wlan_suspended)
3929 {
3930 hdd_set_pwrparams(pHddCtx);
3931 }
3932 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003933 }
3934 return NULL;
3935}
3936
3937VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3938 tANI_U8 rtnl_held )
3939{
3940 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3941 VOS_STATUS status;
3942
3943 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3944 if( VOS_STATUS_SUCCESS != status )
3945 return status;
3946
3947 while ( pCurrent->pAdapter != pAdapter )
3948 {
3949 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3950 if( VOS_STATUS_SUCCESS != status )
3951 break;
3952
3953 pCurrent = pNext;
3954 }
3955 pAdapterNode = pCurrent;
3956 if( VOS_STATUS_SUCCESS == status )
3957 {
3958 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3959 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3960 hdd_remove_adapter( pHddCtx, pAdapterNode );
3961 vos_mem_free( pAdapterNode );
3962
Jeff Johnson295189b2012-06-20 16:38:30 -07003963
3964 /* If there is a single session of STA/P2P client, re-enable BMPS */
3965 if ((!vos_concurrent_sessions_running()) &&
3966 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3967 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3968 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303969 if (pHddCtx->hdd_wlan_suspended)
3970 {
3971 hdd_set_pwrparams(pHddCtx);
3972 }
3973 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003974 }
3975
3976 return VOS_STATUS_SUCCESS;
3977 }
3978
3979 return VOS_STATUS_E_FAILURE;
3980}
3981
3982VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3983{
3984 hdd_adapter_list_node_t *pHddAdapterNode;
3985 VOS_STATUS status;
3986
3987 ENTER();
3988
3989 do
3990 {
3991 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3992 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3993 {
3994 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3995 vos_mem_free( pHddAdapterNode );
3996 }
3997 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3998
3999 EXIT();
4000
4001 return VOS_STATUS_SUCCESS;
4002}
4003
4004void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
4005{
4006 v_U8_t addIE[1] = {0};
4007
4008 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4009 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
4010 eANI_BOOLEAN_FALSE) )
4011 {
4012 hddLog(LOGE,
4013 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
4014 }
4015
4016 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4017 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
4018 eANI_BOOLEAN_FALSE) )
4019 {
4020 hddLog(LOGE,
4021 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
4022 }
4023
4024 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4025 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4026 eANI_BOOLEAN_FALSE) )
4027 {
4028 hddLog(LOGE,
4029 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4030 }
4031}
4032
4033VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4034{
4035 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4036 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4037 union iwreq_data wrqu;
4038
4039 ENTER();
4040
4041 switch(pAdapter->device_mode)
4042 {
4043 case WLAN_HDD_INFRA_STATION:
4044 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004045 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004046 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4047 {
4048 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4049 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4050 pAdapter->sessionId,
4051 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4052 else
4053 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4054 pAdapter->sessionId,
4055 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4056 //success implies disconnect command got queued up successfully
4057 if(halStatus == eHAL_STATUS_SUCCESS)
4058 {
4059 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4060 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4061 }
4062 memset(&wrqu, '\0', sizeof(wrqu));
4063 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4064 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4065 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4066 }
4067 else
4068 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304069 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004070 }
4071
4072 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4073 {
4074 INIT_COMPLETION(pAdapter->session_close_comp_var);
4075 if (eHAL_STATUS_SUCCESS ==
4076 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4077 hdd_smeCloseSessionCallback, pAdapter))
4078 {
4079 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004080 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 &pAdapter->session_close_comp_var,
4082 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4083 }
4084 }
4085
4086 break;
4087
4088 case WLAN_HDD_SOFTAP:
4089 case WLAN_HDD_P2P_GO:
4090 //Any softap specific cleanup here...
4091 mutex_lock(&pHddCtx->sap_lock);
4092 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4093 {
4094 VOS_STATUS status;
4095 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4096
4097 //Stop Bss.
4098 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4099 if (VOS_IS_STATUS_SUCCESS(status))
4100 {
4101 hdd_hostapd_state_t *pHostapdState =
4102 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4103
4104 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4105
4106 if (!VOS_IS_STATUS_SUCCESS(status))
4107 {
4108 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004109 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004110 }
4111 }
4112 else
4113 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004114 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004115 }
4116 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4117
4118 if (eHAL_STATUS_FAILURE ==
4119 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4120 0, NULL, eANI_BOOLEAN_FALSE))
4121 {
4122 hddLog(LOGE,
4123 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004124 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004125 }
4126
4127 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4128 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4129 eANI_BOOLEAN_FALSE) )
4130 {
4131 hddLog(LOGE,
4132 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4133 }
4134
4135 // Reset WNI_CFG_PROBE_RSP Flags
4136 wlan_hdd_reset_prob_rspies(pAdapter);
4137 kfree(pAdapter->sessionCtx.ap.beacon);
4138 pAdapter->sessionCtx.ap.beacon = NULL;
4139 }
4140 mutex_unlock(&pHddCtx->sap_lock);
4141 break;
4142 case WLAN_HDD_MONITOR:
4143 break;
4144 default:
4145 break;
4146 }
4147
4148 EXIT();
4149 return VOS_STATUS_SUCCESS;
4150}
4151
4152VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4153{
4154 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4155 VOS_STATUS status;
4156 hdd_adapter_t *pAdapter;
4157
4158 ENTER();
4159
4160 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4161
4162 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4163 {
4164 pAdapter = pAdapterNode->pAdapter;
4165 netif_tx_disable(pAdapter->dev);
4166 netif_carrier_off(pAdapter->dev);
4167
4168 hdd_stop_adapter( pHddCtx, pAdapter );
4169
4170 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4171 pAdapterNode = pNext;
4172 }
4173
4174 EXIT();
4175
4176 return VOS_STATUS_SUCCESS;
4177}
4178
4179VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4180{
4181 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4182 VOS_STATUS status;
4183 hdd_adapter_t *pAdapter;
4184
4185 ENTER();
4186
4187 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4188
4189 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4190 {
4191 pAdapter = pAdapterNode->pAdapter;
4192 netif_tx_disable(pAdapter->dev);
4193 netif_carrier_off(pAdapter->dev);
4194
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004195 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4196
Jeff Johnson295189b2012-06-20 16:38:30 -07004197 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304198 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4199 {
4200 hdd_wmm_adapter_close( pAdapter );
4201 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004203
4204 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4205 pAdapterNode = pNext;
4206 }
4207
4208 EXIT();
4209
4210 return VOS_STATUS_SUCCESS;
4211}
4212
4213VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4214{
4215 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4216 VOS_STATUS status;
4217 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304218 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004219
4220 ENTER();
4221
4222 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4223
4224 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4225 {
4226 pAdapter = pAdapterNode->pAdapter;
4227
4228 switch(pAdapter->device_mode)
4229 {
4230 case WLAN_HDD_INFRA_STATION:
4231 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004232 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304233
4234 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4235
Jeff Johnson295189b2012-06-20 16:38:30 -07004236 hdd_init_station_mode(pAdapter);
4237 /* Open the gates for HDD to receive Wext commands */
4238 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004239 pHddCtx->scan_info.mScanPending = FALSE;
4240 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004241
4242 //Trigger the initial scan
4243 hdd_wlan_initial_scan(pAdapter);
4244
4245 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304246 if (eConnectionState_Associated == connState ||
4247 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004248 {
4249 union iwreq_data wrqu;
4250 memset(&wrqu, '\0', sizeof(wrqu));
4251 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4252 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4253 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004254 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004255
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 /* indicate disconnected event to nl80211 */
4257 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4258 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304260 else if (eConnectionState_Connecting == connState)
4261 {
4262 /*
4263 * Indicate connect failure to supplicant if we were in the
4264 * process of connecting
4265 */
4266 cfg80211_connect_result(pAdapter->dev, NULL,
4267 NULL, 0, NULL, 0,
4268 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4269 GFP_KERNEL);
4270 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004271 break;
4272
4273 case WLAN_HDD_SOFTAP:
4274 /* softAP can handle SSR */
4275 break;
4276
4277 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004278 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07004279 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004280 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004281 break;
4282
4283 case WLAN_HDD_MONITOR:
4284 /* monitor interface start */
4285 break;
4286 default:
4287 break;
4288 }
4289
4290 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4291 pAdapterNode = pNext;
4292 }
4293
4294 EXIT();
4295
4296 return VOS_STATUS_SUCCESS;
4297}
4298
4299VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4300{
4301 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4302 hdd_adapter_t *pAdapter;
4303 VOS_STATUS status;
4304 v_U32_t roamId;
4305
4306 ENTER();
4307
4308 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4309
4310 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4311 {
4312 pAdapter = pAdapterNode->pAdapter;
4313
4314 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4315 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4316 {
4317 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4318 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4319
4320 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4321 init_completion(&pAdapter->disconnect_comp_var);
4322 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4323 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4324
4325 wait_for_completion_interruptible_timeout(
4326 &pAdapter->disconnect_comp_var,
4327 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4328
4329 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4330 pHddCtx->isAmpAllowed = VOS_FALSE;
4331 sme_RoamConnect(pHddCtx->hHal,
4332 pAdapter->sessionId, &(pWextState->roamProfile),
4333 &roamId);
4334 }
4335
4336 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4337 pAdapterNode = pNext;
4338 }
4339
4340 EXIT();
4341
4342 return VOS_STATUS_SUCCESS;
4343}
4344
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004345void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4346{
4347 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4348 VOS_STATUS status;
4349 hdd_adapter_t *pAdapter;
4350 hdd_station_ctx_t *pHddStaCtx;
4351 hdd_ap_ctx_t *pHddApCtx;
4352 hdd_hostapd_state_t * pHostapdState;
4353 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4354 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4355 const char *p2pMode = "DEV";
4356 const char *ccMode = "Standalone";
4357 int n;
4358
4359 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4360 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4361 {
4362 pAdapter = pAdapterNode->pAdapter;
4363 switch (pAdapter->device_mode) {
4364 case WLAN_HDD_INFRA_STATION:
4365 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4366 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4367 staChannel = pHddStaCtx->conn_info.operationChannel;
4368 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4369 }
4370 break;
4371 case WLAN_HDD_P2P_CLIENT:
4372 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4373 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4374 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4375 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4376 p2pMode = "CLI";
4377 }
4378 break;
4379 case WLAN_HDD_P2P_GO:
4380 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4381 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4382 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4383 p2pChannel = pHddApCtx->operatingChannel;
4384 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4385 }
4386 p2pMode = "GO";
4387 break;
4388 case WLAN_HDD_SOFTAP:
4389 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4390 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4391 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4392 apChannel = pHddApCtx->operatingChannel;
4393 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4394 }
4395 break;
4396 default:
4397 break;
4398 }
4399 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4400 pAdapterNode = pNext;
4401 }
4402 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4403 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4404 }
4405 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4406 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4407 if (p2pChannel > 0) {
4408 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4409 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4410 }
4411 if (apChannel > 0) {
4412 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4413 apChannel, MAC_ADDR_ARRAY(apBssid));
4414 }
4415
4416 if (p2pChannel > 0 && apChannel > 0) {
4417 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4418 }
4419}
4420
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004421bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004422{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004423 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004424}
4425
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004426/* Once SSR is disabled then it cannot be set. */
4427void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004428{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004429 if (HDD_SSR_DISABLED == isSsrRequired)
4430 return;
4431
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 isSsrRequired = value;
4433}
4434
4435VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4436 hdd_adapter_list_node_t** ppAdapterNode)
4437{
4438 VOS_STATUS status;
4439 spin_lock(&pHddCtx->hddAdapters.lock);
4440 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4441 (hdd_list_node_t**) ppAdapterNode );
4442 spin_unlock(&pHddCtx->hddAdapters.lock);
4443 return status;
4444}
4445
4446VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4447 hdd_adapter_list_node_t* pAdapterNode,
4448 hdd_adapter_list_node_t** pNextAdapterNode)
4449{
4450 VOS_STATUS status;
4451 spin_lock(&pHddCtx->hddAdapters.lock);
4452 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4453 (hdd_list_node_t*) pAdapterNode,
4454 (hdd_list_node_t**)pNextAdapterNode );
4455
4456 spin_unlock(&pHddCtx->hddAdapters.lock);
4457 return status;
4458}
4459
4460VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4461 hdd_adapter_list_node_t* pAdapterNode)
4462{
4463 VOS_STATUS status;
4464 spin_lock(&pHddCtx->hddAdapters.lock);
4465 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4466 &pAdapterNode->node );
4467 spin_unlock(&pHddCtx->hddAdapters.lock);
4468 return status;
4469}
4470
4471VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4472 hdd_adapter_list_node_t** ppAdapterNode)
4473{
4474 VOS_STATUS status;
4475 spin_lock(&pHddCtx->hddAdapters.lock);
4476 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4477 (hdd_list_node_t**) ppAdapterNode );
4478 spin_unlock(&pHddCtx->hddAdapters.lock);
4479 return status;
4480}
4481
4482VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4483 hdd_adapter_list_node_t* pAdapterNode)
4484{
4485 VOS_STATUS status;
4486 spin_lock(&pHddCtx->hddAdapters.lock);
4487 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4488 (hdd_list_node_t*) pAdapterNode );
4489 spin_unlock(&pHddCtx->hddAdapters.lock);
4490 return status;
4491}
4492
4493VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4494 hdd_adapter_list_node_t* pAdapterNode)
4495{
4496 VOS_STATUS status;
4497 spin_lock(&pHddCtx->hddAdapters.lock);
4498 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4499 (hdd_list_node_t*) pAdapterNode );
4500 spin_unlock(&pHddCtx->hddAdapters.lock);
4501 return status;
4502}
4503
4504hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4505 tSirMacAddr macAddr )
4506{
4507 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4508 hdd_adapter_t *pAdapter;
4509 VOS_STATUS status;
4510
4511 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4512
4513 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4514 {
4515 pAdapter = pAdapterNode->pAdapter;
4516
4517 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4518 macAddr, sizeof(tSirMacAddr) ) )
4519 {
4520 return pAdapter;
4521 }
4522 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4523 pAdapterNode = pNext;
4524 }
4525
4526 return NULL;
4527
4528}
4529
4530hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4531{
4532 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4533 hdd_adapter_t *pAdapter;
4534 VOS_STATUS status;
4535
4536 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4537
4538 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4539 {
4540 pAdapter = pAdapterNode->pAdapter;
4541
4542 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4543 IFNAMSIZ ) )
4544 {
4545 return pAdapter;
4546 }
4547 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4548 pAdapterNode = pNext;
4549 }
4550
4551 return NULL;
4552
4553}
4554
4555hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4556{
4557 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4558 hdd_adapter_t *pAdapter;
4559 VOS_STATUS status;
4560
4561 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4562
4563 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4564 {
4565 pAdapter = pAdapterNode->pAdapter;
4566
4567 if( pAdapter && (mode == pAdapter->device_mode) )
4568 {
4569 return pAdapter;
4570 }
4571 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4572 pAdapterNode = pNext;
4573 }
4574
4575 return NULL;
4576
4577}
4578
4579//Remove this function later
4580hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4581{
4582 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4583 hdd_adapter_t *pAdapter;
4584 VOS_STATUS status;
4585
4586 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4587
4588 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4589 {
4590 pAdapter = pAdapterNode->pAdapter;
4591
4592 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4593 {
4594 return pAdapter;
4595 }
4596
4597 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4598 pAdapterNode = pNext;
4599 }
4600
4601 return NULL;
4602
4603}
4604
Jeff Johnson295189b2012-06-20 16:38:30 -07004605/**---------------------------------------------------------------------------
4606
4607 \brief hdd_set_monitor_tx_adapter() -
4608
4609 This API initializes the adapter to be used while transmitting on monitor
4610 adapter.
4611
4612 \param - pHddCtx - Pointer to the HDD context.
4613 pAdapter - Adapter that will used for TX. This can be NULL.
4614 \return - None.
4615 --------------------------------------------------------------------------*/
4616void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4617{
4618 hdd_adapter_t *pMonAdapter;
4619
4620 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4621
4622 if( NULL != pMonAdapter )
4623 {
4624 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4625 }
4626}
Jeff Johnson295189b2012-06-20 16:38:30 -07004627/**---------------------------------------------------------------------------
4628
4629 \brief hdd_select_queue() -
4630
4631 This API returns the operating channel of the requested device mode
4632
4633 \param - pHddCtx - Pointer to the HDD context.
4634 - mode - Device mode for which operating channel is required
4635 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4636 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4637 \return - channel number. "0" id the requested device is not found OR it is not connected.
4638 --------------------------------------------------------------------------*/
4639v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4640{
4641 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4642 VOS_STATUS status;
4643 hdd_adapter_t *pAdapter;
4644 v_U8_t operatingChannel = 0;
4645
4646 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4647
4648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4649 {
4650 pAdapter = pAdapterNode->pAdapter;
4651
4652 if( mode == pAdapter->device_mode )
4653 {
4654 switch(pAdapter->device_mode)
4655 {
4656 case WLAN_HDD_INFRA_STATION:
4657 case WLAN_HDD_P2P_CLIENT:
4658 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4659 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4660 break;
4661 case WLAN_HDD_SOFTAP:
4662 case WLAN_HDD_P2P_GO:
4663 /*softap connection info */
4664 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4665 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4666 break;
4667 default:
4668 break;
4669 }
4670
4671 break; //Found the device of interest. break the loop
4672 }
4673
4674 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4675 pAdapterNode = pNext;
4676 }
4677 return operatingChannel;
4678}
4679
4680#ifdef WLAN_FEATURE_PACKET_FILTERING
4681/**---------------------------------------------------------------------------
4682
4683 \brief hdd_set_multicast_list() -
4684
4685 This used to set the multicast address list.
4686
4687 \param - dev - Pointer to the WLAN device.
4688 - skb - Pointer to OS packet (sk_buff).
4689 \return - success/fail
4690
4691 --------------------------------------------------------------------------*/
4692static void hdd_set_multicast_list(struct net_device *dev)
4693{
4694 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004695 int mc_count;
4696 int i = 0;
4697 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304698
4699 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004700 {
4701 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304702 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004703 return;
4704 }
4705
4706 if (dev->flags & IFF_ALLMULTI)
4707 {
4708 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004709 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304710 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004711 }
4712 else
4713 {
4714 mc_count = netdev_mc_count(dev);
4715 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004716 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4718 {
4719 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004720 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304721 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004722 return;
4723 }
4724
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304725 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004726
4727 netdev_for_each_mc_addr(ha, dev) {
4728 if (i == mc_count)
4729 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304730 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4731 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4732 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004733 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304734 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 i++;
4736 }
4737 }
4738 return;
4739}
4740#endif
4741
4742/**---------------------------------------------------------------------------
4743
4744 \brief hdd_select_queue() -
4745
4746 This function is registered with the Linux OS for network
4747 core to decide which queue to use first.
4748
4749 \param - dev - Pointer to the WLAN device.
4750 - skb - Pointer to OS packet (sk_buff).
4751 \return - ac, Queue Index/access category corresponding to UP in IP header
4752
4753 --------------------------------------------------------------------------*/
4754v_U16_t hdd_select_queue(struct net_device *dev,
4755 struct sk_buff *skb)
4756{
4757 return hdd_wmm_select_queue(dev, skb);
4758}
4759
4760
4761/**---------------------------------------------------------------------------
4762
4763 \brief hdd_wlan_initial_scan() -
4764
4765 This function triggers the initial scan
4766
4767 \param - pAdapter - Pointer to the HDD adapter.
4768
4769 --------------------------------------------------------------------------*/
4770void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4771{
4772 tCsrScanRequest scanReq;
4773 tCsrChannelInfo channelInfo;
4774 eHalStatus halStatus;
4775 unsigned long scanId;
4776 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4777
4778 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4779 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4780 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4781
4782 if(sme_Is11dSupported(pHddCtx->hHal))
4783 {
4784 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4785 if ( HAL_STATUS_SUCCESS( halStatus ) )
4786 {
4787 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4788 if( !scanReq.ChannelInfo.ChannelList )
4789 {
4790 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4791 vos_mem_free(channelInfo.ChannelList);
4792 return;
4793 }
4794 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4795 channelInfo.numOfChannels);
4796 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4797 vos_mem_free(channelInfo.ChannelList);
4798 }
4799
4800 scanReq.scanType = eSIR_PASSIVE_SCAN;
4801 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4802 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4803 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4804 }
4805 else
4806 {
4807 scanReq.scanType = eSIR_ACTIVE_SCAN;
4808 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4809 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4810 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4811 }
4812
4813 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4814 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4815 {
4816 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4817 __func__, halStatus );
4818 }
4819
4820 if(sme_Is11dSupported(pHddCtx->hHal))
4821 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4822}
4823
4824struct fullPowerContext
4825{
4826 struct completion completion;
4827 unsigned int magic;
4828};
4829#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4830
4831/**---------------------------------------------------------------------------
4832
4833 \brief hdd_full_power_callback() - HDD full power callback function
4834
4835 This is the function invoked by SME to inform the result of a full power
4836 request issued by HDD
4837
4838 \param - callbackcontext - Pointer to cookie
4839 \param - status - result of request
4840
4841 \return - None
4842
4843 --------------------------------------------------------------------------*/
4844static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4845{
4846 struct fullPowerContext *pContext = callbackContext;
4847
4848 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304849 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004850
4851 if (NULL == callbackContext)
4852 {
4853 hddLog(VOS_TRACE_LEVEL_ERROR,
4854 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004855 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 return;
4857 }
4858
4859 /* there is a race condition that exists between this callback function
4860 and the caller since the caller could time out either before or
4861 while this code is executing. we'll assume the timeout hasn't
4862 occurred, but we'll verify that right before we save our work */
4863
4864 if (POWER_CONTEXT_MAGIC != pContext->magic)
4865 {
4866 /* the caller presumably timed out so there is nothing we can do */
4867 hddLog(VOS_TRACE_LEVEL_WARN,
4868 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004869 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 return;
4871 }
4872
4873 /* the race is on. caller could have timed out immediately after
4874 we verified the magic, but if so, caller will wait a short time
4875 for us to notify the caller, so the context will stay valid */
4876 complete(&pContext->completion);
4877}
4878
4879/**---------------------------------------------------------------------------
4880
4881 \brief hdd_wlan_exit() - HDD WLAN exit function
4882
4883 This is the driver exit point (invoked during rmmod)
4884
4885 \param - pHddCtx - Pointer to the HDD Context
4886
4887 \return - None
4888
4889 --------------------------------------------------------------------------*/
4890void hdd_wlan_exit(hdd_context_t *pHddCtx)
4891{
4892 eHalStatus halStatus;
4893 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4894 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304895 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 struct fullPowerContext powerContext;
4898 long lrc;
4899
4900 ENTER();
4901
Jeff Johnson88ba7742013-02-27 14:36:02 -08004902 if (VOS_FTM_MODE != hdd_get_conparam())
4903 {
4904 // Unloading, restart logic is no more required.
4905 wlan_hdd_restart_deinit(pHddCtx);
4906 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004907
Jeff Johnson295189b2012-06-20 16:38:30 -07004908 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 {
4912 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4913 WLAN_HDD_INFRA_STATION);
4914 if (pAdapter == NULL)
4915 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4916
4917 if (pAdapter != NULL)
4918 {
4919 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4920 hdd_UnregisterWext(pAdapter->dev);
4921 }
4922 }
4923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004924
Jeff Johnson295189b2012-06-20 16:38:30 -07004925 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004926 {
4927 wlan_hdd_ftm_close(pHddCtx);
4928 goto free_hdd_ctx;
4929 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004930 //Stop the Interface TX queue.
4931 //netif_tx_disable(pWlanDev);
4932 //netif_carrier_off(pWlanDev);
4933
Jeff Johnson295189b2012-06-20 16:38:30 -07004934 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4935 {
4936 pAdapter = hdd_get_adapter(pHddCtx,
4937 WLAN_HDD_SOFTAP);
4938 }
4939 else
4940 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004941 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 {
4943 pAdapter = hdd_get_adapter(pHddCtx,
4944 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07004945 if (pAdapter == NULL)
4946 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004949 /* DeRegister with platform driver as client for Suspend/Resume */
4950 vosStatus = hddDeregisterPmOps(pHddCtx);
4951 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4952 {
4953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4954 VOS_ASSERT(0);
4955 }
4956
4957 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4958 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4959 {
4960 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4961 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004962
4963 // Cancel any outstanding scan requests. We are about to close all
4964 // of our adapters, but an adapter structure is what SME passes back
4965 // to our callback function. Hence if there are any outstanding scan
4966 // requests then there is a race condition between when the adapter
4967 // is closed and when the callback is invoked. We try to resolve that
4968 // race condition here by canceling any outstanding scans before we
4969 // close the adapters.
4970 // Note that the scans may be cancelled in an asynchronous manner, so
4971 // ideally there needs to be some kind of synchronization. Rather than
4972 // introduce a new synchronization here, we will utilize the fact that
4973 // we are about to Request Full Power, and since that is synchronized,
4974 // the expectation is that by the time Request Full Power has completed,
4975 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07004976 if (NULL != pAdapter)
4977 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
4978 else
4979 hddLog(VOS_TRACE_LEVEL_ERROR,
4980 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004981
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004982 //Stop the traffic monitor timer
4983 if ( VOS_TIMER_STATE_RUNNING ==
4984 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4985 {
4986 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4987 }
4988
4989 // Destroy the traffic monitor timer
4990 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4991 &pHddCtx->tx_rx_trafficTmr)))
4992 {
4993 hddLog(VOS_TRACE_LEVEL_ERROR,
4994 "%s: Cannot deallocate Traffic monitor timer", __func__);
4995 }
4996
Jeff Johnson295189b2012-06-20 16:38:30 -07004997 //Disable IMPS/BMPS as we do not want the device to enter any power
4998 //save mode during shutdown
4999 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5000 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5001 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
5002
5003 //Ensure that device is in full power as we will touch H/W during vos_Stop
5004 init_completion(&powerContext.completion);
5005 powerContext.magic = POWER_CONTEXT_MAGIC;
5006
5007 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
5008 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
5009
5010 if (eHAL_STATUS_SUCCESS != halStatus)
5011 {
5012 if (eHAL_STATUS_PMC_PENDING == halStatus)
5013 {
5014 /* request was sent -- wait for the response */
5015 lrc = wait_for_completion_interruptible_timeout(
5016 &powerContext.completion,
5017 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
5018 /* either we have a response or we timed out
5019 either way, first invalidate our magic */
5020 powerContext.magic = 0;
5021 if (lrc <= 0)
5022 {
5023 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005024 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 /* there is a race condition such that the callback
5026 function could be executing at the same time we are. of
5027 primary concern is if the callback function had already
5028 verified the "magic" but hasn't yet set the completion
5029 variable. Since the completion variable is on our
5030 stack, we'll delay just a bit to make sure the data is
5031 still valid if that is the case */
5032 msleep(50);
5033 }
5034 }
5035 else
5036 {
5037 hddLog(VOS_TRACE_LEVEL_ERROR,
5038 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005039 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005040 VOS_ASSERT(0);
5041 /* continue -- need to clean up as much as possible */
5042 }
5043 }
5044
Yue Ma0d4891e2013-08-06 17:01:45 -07005045 hdd_debugfs_exit(pHddCtx);
5046
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 // Unregister the Net Device Notifier
5048 unregister_netdevice_notifier(&hdd_netdev_notifier);
5049
Jeff Johnson295189b2012-06-20 16:38:30 -07005050 hdd_stop_all_adapters( pHddCtx );
5051
Jeff Johnson295189b2012-06-20 16:38:30 -07005052#ifdef WLAN_BTAMP_FEATURE
5053 vosStatus = WLANBAP_Stop(pVosContext);
5054 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5055 {
5056 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5057 "%s: Failed to stop BAP",__func__);
5058 }
5059#endif //WLAN_BTAMP_FEATURE
5060
5061 //Stop all the modules
5062 vosStatus = vos_stop( pVosContext );
5063 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5064 {
5065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5066 "%s: Failed to stop VOSS",__func__);
5067 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5068 }
5069
Jeff Johnson295189b2012-06-20 16:38:30 -07005070 //Assert Deep sleep signal now to put Libra HW in lowest power state
5071 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5072 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5073
5074 //Vote off any PMIC voltage supplies
5075 vos_chipPowerDown(NULL, NULL, NULL);
5076
5077 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5078
Leo Chang59cdc7e2013-07-10 10:08:21 -07005079
Jeff Johnson295189b2012-06-20 16:38:30 -07005080 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005082
5083 //Close the scheduler before calling vos_close to make sure no thread is
5084 // scheduled after the each module close is called i.e after all the data
5085 // structures are freed.
5086 vosStatus = vos_sched_close( pVosContext );
5087 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5088 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5089 "%s: Failed to close VOSS Scheduler",__func__);
5090 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5091 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005092#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005093#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5094 /* Destroy the wake lock */
5095 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5096#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005097 /* Destroy the wake lock */
5098 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005099#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005100
5101 //Close VOSS
5102 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5103 vos_close(pVosContext);
5104
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 //Close Watchdog
5106 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5107 vos_watchdog_close(pVosContext);
5108
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305109 //Clean up HDD Nlink Service
5110 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005111#ifdef WLAN_KD_READY_NOTIFIER
5112 nl_srv_exit(pHddCtx->ptt_pid);
5113#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305114 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005115#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305116
Jeff Johnson295189b2012-06-20 16:38:30 -07005117 /* Cancel the vote for XO Core ON.
5118 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5119 * exited at this point
5120 */
5121 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5122 " when WLAN is turned OFF\n");
5123 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5124 {
5125 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5126 " Not returning failure."
5127 " Power consumed will be high\n");
5128 }
5129
5130 hdd_close_all_adapters( pHddCtx );
5131
5132
5133 //Free up dynamically allocated members inside HDD Adapter
5134 kfree(pHddCtx->cfg_ini);
5135 pHddCtx->cfg_ini= NULL;
5136
5137 /* free the power on lock from platform driver */
5138 if (free_riva_power_on_lock("wlan"))
5139 {
5140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5141 __func__);
5142 }
5143
Jeff Johnson88ba7742013-02-27 14:36:02 -08005144free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07005145 /* FTM mode, WIPHY did not registered
5146 If un-register here, system crash will happen */
5147 if (VOS_FTM_MODE != hdd_get_conparam())
5148 {
5149 wiphy_unregister(wiphy) ;
5150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005151 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005152 if (hdd_is_ssr_required())
5153 {
5154 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005155 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 msleep(5000);
5157 }
5158 hdd_set_ssr_required (VOS_FALSE);
5159}
5160
5161
5162/**---------------------------------------------------------------------------
5163
5164 \brief hdd_update_config_from_nv() - Function to update the contents of
5165 the running configuration with parameters taken from NV storage
5166
5167 \param - pHddCtx - Pointer to the HDD global context
5168
5169 \return - VOS_STATUS_SUCCESS if successful
5170
5171 --------------------------------------------------------------------------*/
5172static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5173{
Jeff Johnson295189b2012-06-20 16:38:30 -07005174 v_BOOL_t itemIsValid = VOS_FALSE;
5175 VOS_STATUS status;
5176 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5177 v_U8_t macLoop;
5178
5179 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5180 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5181 if(status != VOS_STATUS_SUCCESS)
5182 {
5183 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5184 return VOS_STATUS_E_FAILURE;
5185 }
5186
5187 if (itemIsValid == VOS_TRUE)
5188 {
5189 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5190 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5191 VOS_MAX_CONCURRENCY_PERSONA);
5192 if(status != VOS_STATUS_SUCCESS)
5193 {
5194 /* Get MAC from NV fail, not update CFG info
5195 * INI MAC value will be used for MAC setting */
5196 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5197 return VOS_STATUS_E_FAILURE;
5198 }
5199
5200 /* If first MAC is not valid, treat all others are not valid
5201 * Then all MACs will be got from ini file */
5202 if(vos_is_macaddr_zero(&macFromNV[0]))
5203 {
5204 /* MAC address in NV file is not configured yet */
5205 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5206 return VOS_STATUS_E_INVAL;
5207 }
5208
5209 /* Get MAC address from NV, update CFG info */
5210 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5211 {
5212 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5213 {
5214 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5215 /* This MAC is not valid, skip it
5216 * This MAC will be got from ini file */
5217 }
5218 else
5219 {
5220 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5221 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5222 VOS_MAC_ADDR_SIZE);
5223 }
5224 }
5225 }
5226 else
5227 {
5228 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5229 return VOS_STATUS_E_FAILURE;
5230 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005231
Jeff Johnson295189b2012-06-20 16:38:30 -07005232
5233 return VOS_STATUS_SUCCESS;
5234}
5235
5236/**---------------------------------------------------------------------------
5237
5238 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5239
5240 \param - pAdapter - Pointer to the HDD
5241
5242 \return - None
5243
5244 --------------------------------------------------------------------------*/
5245VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5246{
5247 eHalStatus halStatus;
5248 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305249 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005250
Jeff Johnson295189b2012-06-20 16:38:30 -07005251
5252 // Send ready indication to the HDD. This will kick off the MAC
5253 // into a 'running' state and should kick off an initial scan.
5254 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5255 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5256 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305257 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 "code %08d [x%08x]",__func__, halStatus, halStatus );
5259 return VOS_STATUS_E_FAILURE;
5260 }
5261
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305262 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005263 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5264 // And RIVA will crash
5265 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5266 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305267 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5268 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5269
5270
Jeff Johnson295189b2012-06-20 16:38:30 -07005271 return VOS_STATUS_SUCCESS;
5272}
5273
Jeff Johnson295189b2012-06-20 16:38:30 -07005274/* wake lock APIs for HDD */
5275void hdd_prevent_suspend(void)
5276{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005277#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005279#else
5280 wcnss_prevent_suspend();
5281#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005282}
5283
5284void hdd_allow_suspend(void)
5285{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005286#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005287 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005288#else
5289 wcnss_allow_suspend();
5290#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005291}
5292
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005293void hdd_allow_suspend_timeout(v_U32_t timeout)
5294{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005295#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005296 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005297#else
5298 /* Do nothing as there is no API in wcnss for timeout*/
5299#endif
5300}
5301
Jeff Johnson295189b2012-06-20 16:38:30 -07005302/**---------------------------------------------------------------------------
5303
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005304 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5305 information between Host and Riva
5306
5307 This function gets reported version of FW
5308 It also finds the version of Riva headers used to compile the host
5309 It compares the above two and prints a warning if they are different
5310 It gets the SW and HW version string
5311 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5312 indicating the features they support through a bitmap
5313
5314 \param - pHddCtx - Pointer to HDD context
5315
5316 \return - void
5317
5318 --------------------------------------------------------------------------*/
5319
5320void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5321{
5322
5323 tSirVersionType versionCompiled;
5324 tSirVersionType versionReported;
5325 tSirVersionString versionString;
5326 tANI_U8 fwFeatCapsMsgSupported = 0;
5327 VOS_STATUS vstatus;
5328
5329 /* retrieve and display WCNSS version information */
5330 do {
5331
5332 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5333 &versionCompiled);
5334 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5335 {
5336 hddLog(VOS_TRACE_LEVEL_FATAL,
5337 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005338 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005339 break;
5340 }
5341
5342 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5343 &versionReported);
5344 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5345 {
5346 hddLog(VOS_TRACE_LEVEL_FATAL,
5347 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005348 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005349 break;
5350 }
5351
5352 if ((versionCompiled.major != versionReported.major) ||
5353 (versionCompiled.minor != versionReported.minor) ||
5354 (versionCompiled.version != versionReported.version) ||
5355 (versionCompiled.revision != versionReported.revision))
5356 {
5357 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5358 "Host expected %u.%u.%u.%u\n",
5359 WLAN_MODULE_NAME,
5360 (int)versionReported.major,
5361 (int)versionReported.minor,
5362 (int)versionReported.version,
5363 (int)versionReported.revision,
5364 (int)versionCompiled.major,
5365 (int)versionCompiled.minor,
5366 (int)versionCompiled.version,
5367 (int)versionCompiled.revision);
5368 }
5369 else
5370 {
5371 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5372 WLAN_MODULE_NAME,
5373 (int)versionReported.major,
5374 (int)versionReported.minor,
5375 (int)versionReported.version,
5376 (int)versionReported.revision);
5377 }
5378
5379 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5380 versionString,
5381 sizeof(versionString));
5382 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5383 {
5384 hddLog(VOS_TRACE_LEVEL_FATAL,
5385 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005386 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005387 break;
5388 }
5389
5390 pr_info("%s: WCNSS software version %s\n",
5391 WLAN_MODULE_NAME, versionString);
5392
5393 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5394 versionString,
5395 sizeof(versionString));
5396 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5397 {
5398 hddLog(VOS_TRACE_LEVEL_FATAL,
5399 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005400 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005401 break;
5402 }
5403
5404 pr_info("%s: WCNSS hardware version %s\n",
5405 WLAN_MODULE_NAME, versionString);
5406
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005407 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5408 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005409 send the message only if it the riva is 1.1
5410 minor numbers for different riva branches:
5411 0 -> (1.0)Mainline Build
5412 1 -> (1.1)Mainline Build
5413 2->(1.04) Stability Build
5414 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005415 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005416 ((versionReported.minor>=1) && (versionReported.version>=1)))
5417 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5418 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005419
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005420 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005421 {
5422#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5423 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5424 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5425#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005426 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5427 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5428 {
5429 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5430 }
5431
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005432 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005433 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005434
5435 } while (0);
5436
5437}
5438
5439/**---------------------------------------------------------------------------
5440
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305441 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5442
5443 \param - pHddCtx - Pointer to the hdd context
5444
5445 \return - true if hardware supports 5GHz
5446
5447 --------------------------------------------------------------------------*/
5448static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5449{
5450 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5451 * then hardware support 5Ghz.
5452 */
5453 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5454 {
5455 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5456 return true;
5457 }
5458 else
5459 {
5460 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5461 __func__);
5462 return false;
5463 }
5464}
5465
5466
5467/**---------------------------------------------------------------------------
5468
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 \brief hdd_wlan_startup() - HDD init function
5470
5471 This is the driver startup code executed once a WLAN device has been detected
5472
5473 \param - dev - Pointer to the underlying device
5474
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005475 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005476
5477 --------------------------------------------------------------------------*/
5478
5479int hdd_wlan_startup(struct device *dev )
5480{
5481 VOS_STATUS status;
5482 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005483 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 hdd_context_t *pHddCtx = NULL;
5485 v_CONTEXT_t pVosContext= NULL;
5486#ifdef WLAN_BTAMP_FEATURE
5487 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5488 WLANBAP_ConfigType btAmpConfig;
5489 hdd_config_t *pConfig;
5490#endif
5491 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005492 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005493
5494 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 /*
5496 * cfg80211: wiphy allocation
5497 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305498 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005499
5500 if(wiphy == NULL)
5501 {
5502 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005503 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 }
5505
5506 pHddCtx = wiphy_priv(wiphy);
5507
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 //Initialize the adapter context to zeros.
5509 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5510
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 hdd_prevent_suspend();
5513 pHddCtx->isLoadUnloadInProgress = TRUE;
5514
5515 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5516
5517 /*Get vos context here bcoz vos_open requires it*/
5518 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5519
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005520 if(pVosContext == NULL)
5521 {
5522 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5523 goto err_free_hdd_context;
5524 }
5525
Jeff Johnson295189b2012-06-20 16:38:30 -07005526 //Save the Global VOSS context in adapter context for future.
5527 pHddCtx->pvosContext = pVosContext;
5528
5529 //Save the adapter context in global context for future.
5530 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5531
Jeff Johnson295189b2012-06-20 16:38:30 -07005532 pHddCtx->parent_dev = dev;
5533
5534 init_completion(&pHddCtx->full_pwr_comp_var);
5535 init_completion(&pHddCtx->standby_comp_var);
5536 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005537 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005538 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhalfddc28c2013-09-05 13:03:40 -07005539 init_completion(&pHddCtx->linux_reg_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005540
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305541 spin_lock_init(&pHddCtx->schedScan_lock);
5542
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5544
5545 // Load all config first as TL config is needed during vos_open
5546 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5547 if(pHddCtx->cfg_ini == NULL)
5548 {
5549 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5550 goto err_free_hdd_context;
5551 }
5552
5553 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5554
5555 // Read and parse the qcom_cfg.ini file
5556 status = hdd_parse_config_ini( pHddCtx );
5557 if ( VOS_STATUS_SUCCESS != status )
5558 {
5559 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5560 __func__, WLAN_INI_FILE);
5561 goto err_config;
5562 }
5563
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305564 /* INI has been read, initialise the configuredMcastBcastFilter with
5565 * INI value as this will serve as the default value
5566 */
5567 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5568 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5569 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305570
5571 if (false == hdd_is_5g_supported(pHddCtx))
5572 {
5573 //5Ghz is not supported.
5574 if (1 != pHddCtx->cfg_ini->nBandCapability)
5575 {
5576 hddLog(VOS_TRACE_LEVEL_INFO,
5577 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5578 pHddCtx->cfg_ini->nBandCapability = 1;
5579 }
5580 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305581
5582 /* If SNR Monitoring is enabled, FW has to parse all beacons
5583 * for calcaluting and storing the average SNR, so set Nth beacon
5584 * filter to 1 to enable FW to parse all the beaocons
5585 */
5586 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5587 {
5588 /* The log level is deliberately set to WARN as overriding
5589 * nthBeaconFilter to 1 will increase power cosumption and this
5590 * might just prove helpful to detect the power issue.
5591 */
5592 hddLog(VOS_TRACE_LEVEL_WARN,
5593 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5594 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5595 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305597 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305599 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07005600 {
5601 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305602 "%s: wlan_hdd_cfg80211_init return failure", __func__);
5603 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07005604 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005605
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005606 // Update VOS trace levels based upon the cfg.ini
5607 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5608 pHddCtx->cfg_ini->vosTraceEnableBAP);
5609 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5610 pHddCtx->cfg_ini->vosTraceEnableTL);
5611 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5612 pHddCtx->cfg_ini->vosTraceEnableWDI);
5613 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5614 pHddCtx->cfg_ini->vosTraceEnableHDD);
5615 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5616 pHddCtx->cfg_ini->vosTraceEnableSME);
5617 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5618 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05305619 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
5620 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005621 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5622 pHddCtx->cfg_ini->vosTraceEnableWDA);
5623 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5624 pHddCtx->cfg_ini->vosTraceEnableSYS);
5625 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5626 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005627 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5628 pHddCtx->cfg_ini->vosTraceEnableSAP);
5629 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5630 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005631
Jeff Johnson295189b2012-06-20 16:38:30 -07005632 // Update WDI trace levels based upon the cfg.ini
5633 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5634 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5635 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5636 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5637 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5638 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5639 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5640 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005641
Jeff Johnson88ba7742013-02-27 14:36:02 -08005642 if (VOS_FTM_MODE == hdd_get_conparam())
5643 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5645 {
5646 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5647 goto err_free_hdd_context;
5648 }
5649 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5650 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005652
Jeff Johnson88ba7742013-02-27 14:36:02 -08005653 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5655 {
5656 status = vos_watchdog_open(pVosContext,
5657 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5658
5659 if(!VOS_IS_STATUS_SUCCESS( status ))
5660 {
5661 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305662 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 }
5664 }
5665
5666 pHddCtx->isLogpInProgress = FALSE;
5667 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5668
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5670 if(!VOS_IS_STATUS_SUCCESS(status))
5671 {
5672 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005673 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005674 }
5675
Jeff Johnson295189b2012-06-20 16:38:30 -07005676 status = vos_open( &pVosContext, 0);
5677 if ( !VOS_IS_STATUS_SUCCESS( status ))
5678 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005679 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5680 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005681 }
5682
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5684
5685 if ( NULL == pHddCtx->hHal )
5686 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005687 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 goto err_vosclose;
5689 }
5690
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005691 status = vos_preStart( pHddCtx->pvosContext );
5692 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5693 {
5694 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5695 goto err_vosclose;
5696 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005697
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005698 /* Note that the vos_preStart() sequence triggers the cfg download.
5699 The cfg download must occur before we update the SME config
5700 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005701 status = hdd_set_sme_config( pHddCtx );
5702
5703 if ( VOS_STATUS_SUCCESS != status )
5704 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005705 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5706 goto err_vosclose;
5707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005708
5709 //Initialize the WMM module
5710 status = hdd_wmm_init(pHddCtx);
5711 if (!VOS_IS_STATUS_SUCCESS(status))
5712 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005713 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 goto err_vosclose;
5715 }
5716
Jeff Johnson295189b2012-06-20 16:38:30 -07005717 /* In the integrated architecture we update the configuration from
5718 the INI file and from NV before vOSS has been started so that
5719 the final contents are available to send down to the cCPU */
5720
5721 // Apply the cfg.ini to cfg.dat
5722 if (FALSE == hdd_update_config_dat(pHddCtx))
5723 {
5724 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5725 goto err_vosclose;
5726 }
5727
5728 // Apply the NV to cfg.dat
5729 /* Prima Update MAC address only at here */
5730 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5731 {
5732#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5733 /* There was not a valid set of MAC Addresses in NV. See if the
5734 default addresses were modified by the cfg.ini settings. If so,
5735 we'll use them, but if not, we'll autogenerate a set of MAC
5736 addresses based upon the device serial number */
5737
5738 static const v_MACADDR_t default_address =
5739 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5740 unsigned int serialno;
5741 int i;
5742
5743 serialno = wcnss_get_serial_number();
5744 if ((0 != serialno) &&
5745 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5746 sizeof(default_address))))
5747 {
5748 /* cfg.ini has the default address, invoke autogen logic */
5749
5750 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5751 bytes of the serial number that can be used to generate
5752 the other 3 bytes of the MAC address. Mask off all but
5753 the lower 3 bytes (this will also make sure we don't
5754 overflow in the next step) */
5755 serialno &= 0x00FFFFFF;
5756
5757 /* we need a unique address for each session */
5758 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5759
5760 /* autogen all addresses */
5761 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5762 {
5763 /* start with the entire default address */
5764 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5765 /* then replace the lower 3 bytes */
5766 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5767 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5768 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5769
5770 serialno++;
5771 }
5772
5773 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5774 MAC_ADDRESS_STR,
5775 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5776 }
5777 else
5778#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5779 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005780 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 "%s: Invalid MAC address in NV, using MAC from ini file "
5782 MAC_ADDRESS_STR, __func__,
5783 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5784 }
5785 }
5786 {
5787 eHalStatus halStatus;
5788 // Set the MAC Address
5789 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5790 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5791 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5792 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5793
5794 if (!HAL_STATUS_SUCCESS( halStatus ))
5795 {
5796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5797 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005798 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 }
5800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005801
5802 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5803 Note: Firmware image will be read and downloaded inside vos_start API */
5804 status = vos_start( pHddCtx->pvosContext );
5805 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5806 {
5807 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5808 goto err_vosclose;
5809 }
5810
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005811 /* Exchange capability info between Host and FW and also get versioning info from FW */
5812 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005813
5814 status = hdd_post_voss_start_config( pHddCtx );
5815 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5816 {
5817 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5818 __func__);
5819 goto err_vosstop;
5820 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305821 wlan_hdd_cfg80211_update_reg_info( wiphy );
5822
5823 /* registration of wiphy dev with cfg80211 */
5824 if (0 > wlan_hdd_cfg80211_register(wiphy))
5825 {
5826 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5827 goto err_vosstop;
5828 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5831 {
5832 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5833 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5834 }
5835 else
5836 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5838 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5839 if (pAdapter != NULL)
5840 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305841 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005842 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305843 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5844 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5845 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005846
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305847 /* Generate the P2P Device Address. This consists of the device's
5848 * primary MAC address with the locally administered bit set.
5849 */
5850 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005851 }
5852 else
5853 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305854 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5855 if (p2p_dev_addr != NULL)
5856 {
5857 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5858 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5859 }
5860 else
5861 {
5862 hddLog(VOS_TRACE_LEVEL_FATAL,
5863 "%s: Failed to allocate mac_address for p2p_device",
5864 __func__);
5865 goto err_close_adapter;
5866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005868
5869 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5870 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5871 if ( NULL == pP2pAdapter )
5872 {
5873 hddLog(VOS_TRACE_LEVEL_FATAL,
5874 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005875 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005876 goto err_close_adapter;
5877 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005880
5881 if( pAdapter == NULL )
5882 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005883 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5884 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887#ifdef WLAN_BTAMP_FEATURE
5888 vStatus = WLANBAP_Open(pVosContext);
5889 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5890 {
5891 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5892 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005893 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 }
5895
5896 vStatus = BSL_Init(pVosContext);
5897 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5898 {
5899 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5900 "%s: Failed to Init BSL",__func__);
5901 goto err_bap_close;
5902 }
5903 vStatus = WLANBAP_Start(pVosContext);
5904 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5905 {
5906 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5907 "%s: Failed to start TL",__func__);
5908 goto err_bap_close;
5909 }
5910
5911 pConfig = pHddCtx->cfg_ini;
5912 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5913 status = WLANBAP_SetConfig(&btAmpConfig);
5914
5915#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005916
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005917#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5918 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5919 {
5920 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5921 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5922 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5923 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5924 }
5925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005926#ifdef FEATURE_WLAN_SCAN_PNO
5927 /*SME must send channel update configuration to RIVA*/
5928 sme_UpdateChannelConfig(pHddCtx->hHal);
5929#endif
5930
Jeff Johnson295189b2012-06-20 16:38:30 -07005931 /* Register with platform driver as client for Suspend/Resume */
5932 status = hddRegisterPmOps(pHddCtx);
5933 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5934 {
5935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5936#ifdef WLAN_BTAMP_FEATURE
5937 goto err_bap_stop;
5938#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005939 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005940#endif //WLAN_BTAMP_FEATURE
5941 }
5942
Yue Ma0d4891e2013-08-06 17:01:45 -07005943 /* Open debugfs interface */
5944 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5945 {
5946 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5947 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07005948 }
5949
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 /* Register TM level change handler function to the platform */
5951 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5952 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5953 {
5954 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5955 goto err_unregister_pmops;
5956 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005957
5958 /* register for riva power on lock to platform driver */
5959 if (req_riva_power_on_lock("wlan"))
5960 {
5961 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5962 __func__);
5963 goto err_unregister_pmops;
5964 }
5965
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 // register net device notifier for device change notification
5967 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5968
5969 if(ret < 0)
5970 {
5971 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5972 goto err_free_power_on_lock;
5973 }
5974
5975 //Initialize the nlink service
5976 if(nl_srv_init() != 0)
5977 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005979 goto err_reg_netdev;
5980 }
5981
5982 //Initialize the BTC service
5983 if(btc_activate_service(pHddCtx) != 0)
5984 {
5985 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5986 goto err_nl_srv;
5987 }
5988
5989#ifdef PTT_SOCK_SVC_ENABLE
5990 //Initialize the PTT service
5991 if(ptt_sock_activate_svc(pHddCtx) != 0)
5992 {
5993 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5994 goto err_nl_srv;
5995 }
5996#endif
5997
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005999 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07006001 /* Action frame registered in one adapter which will
6002 * applicable to all interfaces
6003 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07006004 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006006
6007 mutex_init(&pHddCtx->sap_lock);
6008
6009 pHddCtx->isLoadUnloadInProgress = FALSE;
6010
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006011#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006012#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6013 /* Initialize the wake lcok */
6014 wake_lock_init(&pHddCtx->rx_wake_lock,
6015 WAKE_LOCK_SUSPEND,
6016 "qcom_rx_wakelock");
6017#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006018 /* Initialize the wake lcok */
6019 wake_lock_init(&pHddCtx->sap_wake_lock,
6020 WAKE_LOCK_SUSPEND,
6021 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006022#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07006023
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006024 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
6025 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006026
6027 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6028 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306029
Jeff Johnsone7245742012-09-05 17:12:55 -07006030 // Initialize the restart logic
6031 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05306032
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006033 //Register the traffic monitor timer now
6034 if ( pHddCtx->cfg_ini->dynSplitscan)
6035 {
6036 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
6037 VOS_TIMER_TYPE_SW,
6038 hdd_tx_rx_pkt_cnt_stat_timer_handler,
6039 (void *)pHddCtx);
6040 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006041 goto success;
6042
6043err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07006044#ifdef WLAN_KD_READY_NOTIFIER
6045 nl_srv_exit(pHddCtx->ptt_pid);
6046#else
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006048#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07006049err_reg_netdev:
6050 unregister_netdevice_notifier(&hdd_netdev_notifier);
6051
6052err_free_power_on_lock:
6053 free_riva_power_on_lock("wlan");
6054
6055err_unregister_pmops:
6056 hddDevTmUnregisterNotifyCallback(pHddCtx);
6057 hddDeregisterPmOps(pHddCtx);
6058
Yue Ma0d4891e2013-08-06 17:01:45 -07006059 hdd_debugfs_exit(pHddCtx);
6060
Jeff Johnson295189b2012-06-20 16:38:30 -07006061#ifdef WLAN_BTAMP_FEATURE
6062err_bap_stop:
6063 WLANBAP_Stop(pVosContext);
6064#endif
6065
6066#ifdef WLAN_BTAMP_FEATURE
6067err_bap_close:
6068 WLANBAP_Close(pVosContext);
6069#endif
6070
Jeff Johnson295189b2012-06-20 16:38:30 -07006071err_close_adapter:
6072 hdd_close_all_adapters( pHddCtx );
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306073 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006074
6075err_vosstop:
6076 vos_stop(pVosContext);
6077
6078err_vosclose:
6079 status = vos_sched_close( pVosContext );
6080 if (!VOS_IS_STATUS_SUCCESS(status)) {
6081 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6082 "%s: Failed to close VOSS Scheduler", __func__);
6083 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6084 }
6085 vos_close(pVosContext );
6086
Jeff Johnson295189b2012-06-20 16:38:30 -07006087err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006088 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006089
6090err_wdclose:
6091 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6092 vos_watchdog_close(pVosContext);
6093
Jeff Johnson295189b2012-06-20 16:38:30 -07006094err_config:
6095 kfree(pHddCtx->cfg_ini);
6096 pHddCtx->cfg_ini= NULL;
6097
6098err_free_hdd_context:
6099 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006100 wiphy_free(wiphy) ;
6101 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006102 VOS_BUG(1);
6103
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006104 if (hdd_is_ssr_required())
6105 {
6106 /* WDI timeout had happened during load, so SSR is needed here */
6107 subsystem_restart("wcnss");
6108 msleep(5000);
6109 }
6110 hdd_set_ssr_required (VOS_FALSE);
6111
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006112 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006113
6114success:
6115 EXIT();
6116 return 0;
6117}
6118
6119/**---------------------------------------------------------------------------
6120
Jeff Johnson32d95a32012-09-10 13:15:23 -07006121 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006122
Jeff Johnson32d95a32012-09-10 13:15:23 -07006123 This is the driver entry point - called in different timeline depending
6124 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006125
6126 \param - None
6127
6128 \return - 0 for success, non zero for failure
6129
6130 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006131static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006132{
6133 VOS_STATUS status;
6134 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 struct device *dev = NULL;
6136 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006137#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6138 int max_retries = 0;
6139#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006140
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306141#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6142 vos_wconn_trace_init();
6143#endif
6144
Jeff Johnson295189b2012-06-20 16:38:30 -07006145 ENTER();
6146
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006147#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006150
6151 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6152 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6153
6154 //Power Up Libra WLAN card first if not already powered up
6155 status = vos_chipPowerUp(NULL,NULL,NULL);
6156 if (!VOS_IS_STATUS_SUCCESS(status))
6157 {
6158 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6159 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306160#ifdef WLAN_OPEN_SOURCE
6161 wake_lock_destroy(&wlan_wake_lock);
6162#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006163 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 }
6165
Jeff Johnson295189b2012-06-20 16:38:30 -07006166#ifdef ANI_BUS_TYPE_PCI
6167
6168 dev = wcnss_wlan_get_device();
6169
6170#endif // ANI_BUS_TYPE_PCI
6171
6172#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006173
6174#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6175 /* wait until WCNSS driver downloads NV */
6176 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6177 msleep(1000);
6178 }
6179 if (max_retries >= 5) {
6180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306181#ifdef WLAN_OPEN_SOURCE
6182 wake_lock_destroy(&wlan_wake_lock);
6183#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006184 return -ENODEV;
6185 }
6186#endif
6187
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 dev = wcnss_wlan_get_device();
6189#endif // ANI_BUS_TYPE_PLATFORM
6190
6191
6192 do {
6193 if (NULL == dev) {
6194 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6195 ret_status = -1;
6196 break;
6197 }
6198
6199#ifdef MEMORY_DEBUG
6200 vos_mem_init();
6201#endif
6202
6203#ifdef TIMER_MANAGER
6204 vos_timer_manager_init();
6205#endif
6206
6207 /* Preopen VOSS so that it is ready to start at least SAL */
6208 status = vos_preOpen(&pVosContext);
6209
6210 if (!VOS_IS_STATUS_SUCCESS(status))
6211 {
6212 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6213 ret_status = -1;
6214 break;
6215 }
6216
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006217#ifndef MODULE
6218 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6219 */
6220 hdd_set_conparam((v_UINT_t)con_mode);
6221#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006222
6223 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006224 if (hdd_wlan_startup(dev))
6225 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006227 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006228 vos_preClose( &pVosContext );
6229 ret_status = -1;
6230 break;
6231 }
6232
6233 /* Cancel the vote for XO Core ON
6234 * This is done here for safety purposes in case we re-initialize without turning
6235 * it OFF in any error scenario.
6236 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006237 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006238 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006239 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006240 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6241 {
6242 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6243 " Power consumed will be high\n");
6244 }
6245 } while (0);
6246
6247 if (0 != ret_status)
6248 {
6249 //Assert Deep sleep signal now to put Libra HW in lowest power state
6250 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6251 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6252
6253 //Vote off any PMIC voltage supplies
6254 vos_chipPowerDown(NULL, NULL, NULL);
6255#ifdef TIMER_MANAGER
6256 vos_timer_exit();
6257#endif
6258#ifdef MEMORY_DEBUG
6259 vos_mem_exit();
6260#endif
6261
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006262#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006263 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006264#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6266 }
6267 else
6268 {
6269 //Send WLAN UP indication to Nlink Service
6270 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6271
6272 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006273 }
6274
6275 EXIT();
6276
6277 return ret_status;
6278}
6279
Jeff Johnson32d95a32012-09-10 13:15:23 -07006280/**---------------------------------------------------------------------------
6281
6282 \brief hdd_module_init() - Init Function
6283
6284 This is the driver entry point (invoked when module is loaded using insmod)
6285
6286 \param - None
6287
6288 \return - 0 for success, non zero for failure
6289
6290 --------------------------------------------------------------------------*/
6291#ifdef MODULE
6292static int __init hdd_module_init ( void)
6293{
6294 return hdd_driver_init();
6295}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006296#else /* #ifdef MODULE */
6297static int __init hdd_module_init ( void)
6298{
6299 /* Driver initialization is delayed to fwpath_changed_handler */
6300 return 0;
6301}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006302#endif /* #ifdef MODULE */
6303
Jeff Johnson295189b2012-06-20 16:38:30 -07006304
6305/**---------------------------------------------------------------------------
6306
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006307 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006308
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006309 This is the driver exit point (invoked when module is unloaded using rmmod
6310 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006311
6312 \param - None
6313
6314 \return - None
6315
6316 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006317static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006318{
6319 hdd_context_t *pHddCtx = NULL;
6320 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006321 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006322
6323 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6324
6325 //Get the global vos context
6326 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6327
6328 if(!pVosContext)
6329 {
6330 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6331 goto done;
6332 }
6333
6334 //Get the HDD context.
6335 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6336
6337 if(!pHddCtx)
6338 {
6339 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6340 }
6341 else
6342 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006343 while(isWDresetInProgress()) {
6344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6345 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006346 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006347
6348 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6349 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6350 "%s:SSR never completed, fatal error", __func__);
6351 VOS_BUG(0);
6352 }
6353 }
6354
Jeff Johnson295189b2012-06-20 16:38:30 -07006355
6356 pHddCtx->isLoadUnloadInProgress = TRUE;
6357 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6358
6359 //Do all the cleanup before deregistering the driver
6360 hdd_wlan_exit(pHddCtx);
6361 }
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 vos_preClose( &pVosContext );
6364
6365#ifdef TIMER_MANAGER
6366 vos_timer_exit();
6367#endif
6368#ifdef MEMORY_DEBUG
6369 vos_mem_exit();
6370#endif
6371
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306372#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6373 vos_wconn_trace_exit();
6374#endif
6375
Jeff Johnson295189b2012-06-20 16:38:30 -07006376done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006377#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006379#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006380 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6381}
6382
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006383/**---------------------------------------------------------------------------
6384
6385 \brief hdd_module_exit() - Exit function
6386
6387 This is the driver exit point (invoked when module is unloaded using rmmod)
6388
6389 \param - None
6390
6391 \return - None
6392
6393 --------------------------------------------------------------------------*/
6394static void __exit hdd_module_exit(void)
6395{
6396 hdd_driver_exit();
6397}
6398
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006399#ifdef MODULE
6400static int fwpath_changed_handler(const char *kmessage,
6401 struct kernel_param *kp)
6402{
Jeff Johnson76052702013-04-16 13:55:05 -07006403 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006404}
6405
6406static int con_mode_handler(const char *kmessage,
6407 struct kernel_param *kp)
6408{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006409 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006410}
6411#else /* #ifdef MODULE */
6412/**---------------------------------------------------------------------------
6413
Jeff Johnson76052702013-04-16 13:55:05 -07006414 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006415
Jeff Johnson76052702013-04-16 13:55:05 -07006416 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006417 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006418 - invoked when module parameter fwpath is modified from userspace to signal
6419 initializing the WLAN driver or when con_mode is modified from userspace
6420 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006421
6422 \return - 0 for success, non zero for failure
6423
6424 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006425static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006426{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006427 int ret_status;
6428
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006429 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006430 ret_status = hdd_driver_init();
6431 wlan_hdd_inited = ret_status ? 0 : 1;
6432 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006433 }
6434
6435 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006436
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006437 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006438
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006439 ret_status = hdd_driver_init();
6440 wlan_hdd_inited = ret_status ? 0 : 1;
6441 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006442}
6443
Jeff Johnson295189b2012-06-20 16:38:30 -07006444/**---------------------------------------------------------------------------
6445
Jeff Johnson76052702013-04-16 13:55:05 -07006446 \brief fwpath_changed_handler() - Handler Function
6447
6448 Handle changes to the fwpath parameter
6449
6450 \return - 0 for success, non zero for failure
6451
6452 --------------------------------------------------------------------------*/
6453static int fwpath_changed_handler(const char *kmessage,
6454 struct kernel_param *kp)
6455{
6456 int ret;
6457
6458 ret = param_set_copystring(kmessage, kp);
6459 if (0 == ret)
6460 ret = kickstart_driver();
6461 return ret;
6462}
6463
6464/**---------------------------------------------------------------------------
6465
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006466 \brief con_mode_handler() -
6467
6468 Handler function for module param con_mode when it is changed by userspace
6469 Dynamically linked - do nothing
6470 Statically linked - exit and init driver, as in rmmod and insmod
6471
Jeff Johnson76052702013-04-16 13:55:05 -07006472 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006473
Jeff Johnson76052702013-04-16 13:55:05 -07006474 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006475
6476 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006477static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006478{
Jeff Johnson76052702013-04-16 13:55:05 -07006479 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006480
Jeff Johnson76052702013-04-16 13:55:05 -07006481 ret = param_set_int(kmessage, kp);
6482 if (0 == ret)
6483 ret = kickstart_driver();
6484 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006485}
6486#endif /* #ifdef MODULE */
6487
6488/**---------------------------------------------------------------------------
6489
Jeff Johnson295189b2012-06-20 16:38:30 -07006490 \brief hdd_get_conparam() -
6491
6492 This is the driver exit point (invoked when module is unloaded using rmmod)
6493
6494 \param - None
6495
6496 \return - tVOS_CON_MODE
6497
6498 --------------------------------------------------------------------------*/
6499tVOS_CON_MODE hdd_get_conparam ( void )
6500{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006501#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006502 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006503#else
6504 return (tVOS_CON_MODE)curr_con_mode;
6505#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006506}
6507void hdd_set_conparam ( v_UINT_t newParam )
6508{
6509 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006510#ifndef MODULE
6511 curr_con_mode = con_mode;
6512#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006513}
6514/**---------------------------------------------------------------------------
6515
6516 \brief hdd_softap_sta_deauth() - function
6517
6518 This to take counter measure to handle deauth req from HDD
6519
6520 \param - pAdapter - Pointer to the HDD
6521
6522 \param - enable - boolean value
6523
6524 \return - None
6525
6526 --------------------------------------------------------------------------*/
6527
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006528VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006529{
Jeff Johnson295189b2012-06-20 16:38:30 -07006530 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006531 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
6533 ENTER();
6534
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006535 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6536 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006537
6538 //Ignore request to deauth bcmc station
6539 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006540 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006541
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006542 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006543
6544 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006545 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006546}
6547
6548/**---------------------------------------------------------------------------
6549
6550 \brief hdd_softap_sta_disassoc() - function
6551
6552 This to take counter measure to handle deauth req from HDD
6553
6554 \param - pAdapter - Pointer to the HDD
6555
6556 \param - enable - boolean value
6557
6558 \return - None
6559
6560 --------------------------------------------------------------------------*/
6561
6562void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6563{
6564 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6565
6566 ENTER();
6567
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306568 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006569
6570 //Ignore request to disassoc bcmc station
6571 if( pDestMacAddress[0] & 0x1 )
6572 return;
6573
6574 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6575}
6576
6577void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6578{
6579 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6580
6581 ENTER();
6582
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306583 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006584
6585 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6586}
6587
Jeff Johnson295189b2012-06-20 16:38:30 -07006588/**---------------------------------------------------------------------------
6589 *
6590 * \brief hdd_get__concurrency_mode() -
6591 *
6592 *
6593 * \param - None
6594 *
6595 * \return - CONCURRENCY MODE
6596 *
6597 * --------------------------------------------------------------------------*/
6598tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6599{
6600 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6601 hdd_context_t *pHddCtx;
6602
6603 if (NULL != pVosContext)
6604 {
6605 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6606 if (NULL != pHddCtx)
6607 {
6608 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6609 }
6610 }
6611
6612 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006613 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006614 return VOS_STA;
6615}
6616
6617/* Decide whether to allow/not the apps power collapse.
6618 * Allow apps power collapse if we are in connected state.
6619 * if not, allow only if we are in IMPS */
6620v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6621{
6622 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006623 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006624 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6626 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6627 hdd_adapter_t *pAdapter = NULL;
6628 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006629 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006630
Jeff Johnson295189b2012-06-20 16:38:30 -07006631 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6632 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006633
Yathish9f22e662012-12-10 14:21:35 -08006634 concurrent_state = hdd_get_concurrency_mode();
6635
6636#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6637 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6638 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6639 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6640 return TRUE;
6641#endif
6642
Jeff Johnson295189b2012-06-20 16:38:30 -07006643 /*loop through all adapters. TBD fix for Concurrency */
6644 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6645 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6646 {
6647 pAdapter = pAdapterNode->pAdapter;
6648 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6649 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6650 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006651 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006652 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006653 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006654 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6655 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006656 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006657 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006658 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6659 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006660 return FALSE;
6661 }
6662 }
6663 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6664 pAdapterNode = pNext;
6665 }
6666 return TRUE;
6667}
6668
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006669/* Decides whether to send suspend notification to Riva
6670 * if any adapter is in BMPS; then it is required */
6671v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6672{
6673 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6674 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6675
6676 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6677 {
6678 return TRUE;
6679 }
6680 return FALSE;
6681}
6682
Jeff Johnson295189b2012-06-20 16:38:30 -07006683void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6684{
6685 switch(mode)
6686 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006687 case VOS_STA_MODE:
6688 case VOS_P2P_CLIENT_MODE:
6689 case VOS_P2P_GO_MODE:
6690 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006691 pHddCtx->concurrency_mode |= (1 << mode);
6692 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 break;
6694 default:
6695 break;
6696
6697 }
6698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6699 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6700}
6701
6702
6703void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6704{
6705 switch(mode)
6706 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006707 case VOS_STA_MODE:
6708 case VOS_P2P_CLIENT_MODE:
6709 case VOS_P2P_GO_MODE:
6710 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006711 pHddCtx->no_of_sessions[mode]--;
6712 if (!(pHddCtx->no_of_sessions[mode]))
6713 pHddCtx->concurrency_mode &= (~(1 << mode));
6714 break;
6715 default:
6716 break;
6717 }
6718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6719 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6720}
6721
Jeff Johnsone7245742012-09-05 17:12:55 -07006722/**---------------------------------------------------------------------------
6723 *
6724 * \brief wlan_hdd_restart_init
6725 *
6726 * This function initalizes restart timer/flag. An internal function.
6727 *
6728 * \param - pHddCtx
6729 *
6730 * \return - None
6731 *
6732 * --------------------------------------------------------------------------*/
6733
6734static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6735{
6736 /* Initialize */
6737 pHddCtx->hdd_restart_retries = 0;
6738 atomic_set(&pHddCtx->isRestartInProgress, 0);
6739 vos_timer_init(&pHddCtx->hdd_restart_timer,
6740 VOS_TIMER_TYPE_SW,
6741 wlan_hdd_restart_timer_cb,
6742 pHddCtx);
6743}
6744/**---------------------------------------------------------------------------
6745 *
6746 * \brief wlan_hdd_restart_deinit
6747 *
6748 * This function cleans up the resources used. An internal function.
6749 *
6750 * \param - pHddCtx
6751 *
6752 * \return - None
6753 *
6754 * --------------------------------------------------------------------------*/
6755
6756static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6757{
6758
6759 VOS_STATUS vos_status;
6760 /* Block any further calls */
6761 atomic_set(&pHddCtx->isRestartInProgress, 1);
6762 /* Cleanup */
6763 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6764 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006765 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006766 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6767 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006768 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006769
6770}
6771
6772/**---------------------------------------------------------------------------
6773 *
6774 * \brief wlan_hdd_framework_restart
6775 *
6776 * This function uses a cfg80211 API to start a framework initiated WLAN
6777 * driver module unload/load.
6778 *
6779 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6780 *
6781 *
6782 * \param - pHddCtx
6783 *
6784 * \return - VOS_STATUS_SUCCESS: Success
6785 * VOS_STATUS_E_EMPTY: Adapter is Empty
6786 * VOS_STATUS_E_NOMEM: No memory
6787
6788 * --------------------------------------------------------------------------*/
6789
6790static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6791{
6792 VOS_STATUS status = VOS_STATUS_SUCCESS;
6793 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006794 int len = (sizeof (struct ieee80211_mgmt));
6795 struct ieee80211_mgmt *mgmt = NULL;
6796
6797 /* Prepare the DEAUTH managment frame with reason code */
6798 mgmt = kzalloc(len, GFP_KERNEL);
6799 if(mgmt == NULL)
6800 {
6801 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6802 "%s: memory allocation failed (%d bytes)", __func__, len);
6803 return VOS_STATUS_E_NOMEM;
6804 }
6805 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006806
6807 /* Iterate over all adapters/devices */
6808 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6809 do
6810 {
6811 if( (status == VOS_STATUS_SUCCESS) &&
6812 pAdapterNode &&
6813 pAdapterNode->pAdapter)
6814 {
6815 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6816 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6817 pAdapterNode->pAdapter->dev->name,
6818 pAdapterNode->pAdapter->device_mode,
6819 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006820 /*
6821 * CFG80211 event to restart the driver
6822 *
6823 * 'cfg80211_send_unprot_deauth' sends a
6824 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6825 * of SME(Linux Kernel) state machine.
6826 *
6827 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6828 * the driver.
6829 *
6830 */
6831
6832 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006833 }
6834 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6835 pAdapterNode = pNext;
6836 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6837
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006838
6839 /* Free the allocated management frame */
6840 kfree(mgmt);
6841
Jeff Johnsone7245742012-09-05 17:12:55 -07006842 /* Retry until we unload or reach max count */
6843 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6844 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6845
6846 return status;
6847
6848}
6849/**---------------------------------------------------------------------------
6850 *
6851 * \brief wlan_hdd_restart_timer_cb
6852 *
6853 * Restart timer callback. An internal function.
6854 *
6855 * \param - User data:
6856 *
6857 * \return - None
6858 *
6859 * --------------------------------------------------------------------------*/
6860
6861void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6862{
6863 hdd_context_t *pHddCtx = usrDataForCallback;
6864 wlan_hdd_framework_restart(pHddCtx);
6865 return;
6866
6867}
6868
6869
6870/**---------------------------------------------------------------------------
6871 *
6872 * \brief wlan_hdd_restart_driver
6873 *
6874 * This function sends an event to supplicant to restart the WLAN driver.
6875 *
6876 * This function is called from vos_wlanRestart.
6877 *
6878 * \param - pHddCtx
6879 *
6880 * \return - VOS_STATUS_SUCCESS: Success
6881 * VOS_STATUS_E_EMPTY: Adapter is Empty
6882 * VOS_STATUS_E_ALREADY: Request already in progress
6883
6884 * --------------------------------------------------------------------------*/
6885VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6886{
6887 VOS_STATUS status = VOS_STATUS_SUCCESS;
6888
6889 /* A tight check to make sure reentrancy */
6890 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6891 {
6892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6893 "%s: WLAN restart is already in progress", __func__);
6894
6895 return VOS_STATUS_E_ALREADY;
6896 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006897 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006898#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006899 wcnss_reset_intr();
6900#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006901
Jeff Johnsone7245742012-09-05 17:12:55 -07006902 return status;
6903}
6904
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006905/*
6906 * API to find if there is any STA or P2P-Client is connected
6907 */
6908VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6909{
6910 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6911}
Jeff Johnsone7245742012-09-05 17:12:55 -07006912
Jeff Johnson295189b2012-06-20 16:38:30 -07006913//Register the module init/exit functions
6914module_init(hdd_module_init);
6915module_exit(hdd_module_exit);
6916
6917MODULE_LICENSE("Dual BSD/GPL");
6918MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6919MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6920
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006921module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6922 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006923
Jeff Johnson76052702013-04-16 13:55:05 -07006924module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006925 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);