blob: fadebb8a4ea2834951baeaf500496c94a2c2e492 [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
751 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
752 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
810 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
811 /* Returned value is in units of seconds */
812 if (copy_to_user(priv_data.buf, &extra, len + 1))
813 {
814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
815 "%s: failed to copy data to user buffer", __func__);
816 ret = -EFAULT;
817 goto exit;
818 }
819 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700820 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
821 {
822 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700823 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700826 /* input refresh period is in terms of seconds */
827 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
828 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700830 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700831 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700832 if (ret < 0)
833 {
834 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700835 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700837 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700838 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700839 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
840 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
841 ret = -EINVAL;
842 goto exit;
843 }
844
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700845 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
846 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
847 {
848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
849 "Neighbor scan results refresh period value %d is out of range"
850 " (Min: %d Max: %d)", roamScanRefreshPeriod,
851 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
852 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
853 ret = -EINVAL;
854 goto exit;
855 }
856 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
857
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
859 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700860 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700861
862 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
863 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
864 }
865 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
866 {
867 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
868 char extra[32];
869 tANI_U8 len = 0;
870
871 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
872 /* Returned value is in units of seconds */
873 if (copy_to_user(priv_data.buf, &extra, len + 1))
874 {
875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
876 "%s: failed to copy data to user buffer", __func__);
877 ret = -EFAULT;
878 goto exit;
879 }
880 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700881#ifdef FEATURE_WLAN_LFR
882 /* SETROAMMODE */
883 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
884 {
885 tANI_U8 *value = command;
886 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
887
888 /* Move pointer to ahead of SETROAMMODE<delimiter> */
889 value = value + SIZE_OF_SETROAMMODE + 1;
890
891 /* Convert the value from ascii to integer */
892 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
893 if (ret < 0)
894 {
895 /* If the input value is greater than max value of datatype, then also
896 kstrtou8 fails */
897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
898 "%s: kstrtou8 failed range [%d - %d]", __func__,
899 CFG_LFR_FEATURE_ENABLED_MIN,
900 CFG_LFR_FEATURE_ENABLED_MAX);
901 ret = -EINVAL;
902 goto exit;
903 }
904 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
905 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
906 {
907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
908 "Roam Mode value %d is out of range"
909 " (Min: %d Max: %d)", roamMode,
910 CFG_LFR_FEATURE_ENABLED_MIN,
911 CFG_LFR_FEATURE_ENABLED_MAX);
912 ret = -EINVAL;
913 goto exit;
914 }
915
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
917 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
918 /*
919 * Note that
920 * SETROAMMODE 0 is to enable LFR while
921 * SETROAMMODE 1 is to disable LFR, but
922 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
923 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
924 */
925 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
926 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
927 else
928 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
929
930 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
931 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
932 }
933 /* GETROAMMODE */
934 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
935 {
936 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
937 char extra[32];
938 tANI_U8 len = 0;
939
940 /*
941 * roamMode value shall be inverted because the sementics is different.
942 */
943 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
944 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
945 else
946 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
947
948 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
949 if (copy_to_user(priv_data.buf, &extra, len + 1))
950 {
951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
952 "%s: failed to copy data to user buffer", __func__);
953 ret = -EFAULT;
954 goto exit;
955 }
956 }
957#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800958#endif
959#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
960 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
961 {
962 tANI_U8 *value = command;
963 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
964
965 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
966 value = value + 13;
967 /* Convert the value from ascii to integer */
968 ret = kstrtou8(value, 10, &roamRssiDiff);
969 if (ret < 0)
970 {
971 /* If the input value is greater than max value of datatype, then also
972 kstrtou8 fails */
973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
974 "%s: kstrtou8 failed range [%d - %d]", __func__,
975 CFG_ROAM_RSSI_DIFF_MIN,
976 CFG_ROAM_RSSI_DIFF_MAX);
977 ret = -EINVAL;
978 goto exit;
979 }
980
981 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
982 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
983 {
984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
985 "Roam rssi diff value %d is out of range"
986 " (Min: %d Max: %d)", roamRssiDiff,
987 CFG_ROAM_RSSI_DIFF_MIN,
988 CFG_ROAM_RSSI_DIFF_MAX);
989 ret = -EINVAL;
990 goto exit;
991 }
992
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
994 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
995
996 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
997 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
998 }
999 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1000 {
1001 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1002 char extra[32];
1003 tANI_U8 len = 0;
1004
1005 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1006 if (copy_to_user(priv_data.buf, &extra, len + 1))
1007 {
1008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1009 "%s: failed to copy data to user buffer", __func__);
1010 ret = -EFAULT;
1011 goto exit;
1012 }
1013 }
1014#endif
1015#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1016 else if (strncmp(command, "GETBAND", 7) == 0)
1017 {
1018 int band = -1;
1019 char extra[32];
1020 tANI_U8 len = 0;
1021 hdd_getBand_helper(pHddCtx, &band);
1022
1023 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1024 if (copy_to_user(priv_data.buf, &extra, len + 1))
1025 {
1026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1027 "%s: failed to copy data to user buffer", __func__);
1028 ret = -EFAULT;
1029 goto exit;
1030 }
1031 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001032 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1033 {
1034 tANI_U8 *value = command;
1035 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1036 tANI_U8 numChannels = 0;
1037 eHalStatus status = eHAL_STATUS_SUCCESS;
1038
1039 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1040 if (eHAL_STATUS_SUCCESS != status)
1041 {
1042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1043 "%s: Failed to parse channel list information", __func__);
1044 ret = -EINVAL;
1045 goto exit;
1046 }
1047
1048 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1049 {
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1052 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1053 ret = -EINVAL;
1054 goto exit;
1055 }
1056 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1057 numChannels);
1058 if (eHAL_STATUS_SUCCESS != status)
1059 {
1060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1061 "%s: Failed to update channel list information", __func__);
1062 ret = -EINVAL;
1063 goto exit;
1064 }
1065 }
1066 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1067 {
1068 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1069 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001070 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001071 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001072 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001073
1074 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1075 ChannelList, &numChannels ))
1076 {
1077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1078 "%s: failed to get roam scan channel list", __func__);
1079 ret = -EFAULT;
1080 goto exit;
1081 }
1082 /* output channel list is of the format
1083 [Number of roam scan channels][Channel1][Channel2]... */
1084 /* copy the number of channels in the 0th index */
1085 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1086 for (j = 0; (j < numChannels); j++)
1087 {
1088 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1089 }
1090
1091 if (copy_to_user(priv_data.buf, &extra, len + 1))
1092 {
1093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1094 "%s: failed to copy data to user buffer", __func__);
1095 ret = -EFAULT;
1096 goto exit;
1097 }
1098 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001099 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1100 {
1101 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1102 char extra[32];
1103 tANI_U8 len = 0;
1104
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001105 /* Check if the features OKC/CCX/11R are supported simultaneously,
1106 then this operation is not permitted (return FAILURE) */
1107 if (ccxMode &&
1108 hdd_is_okc_mode_enabled(pHddCtx) &&
1109 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1110 {
1111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1112 "%s: OKC/CCX/11R are supported simultaneously"
1113 " hence this operation is not permitted!", __func__);
1114 ret = -EPERM;
1115 goto exit;
1116 }
1117
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001118 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1119 if (copy_to_user(priv_data.buf, &extra, len + 1))
1120 {
1121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1122 "%s: failed to copy data to user buffer", __func__);
1123 ret = -EFAULT;
1124 goto exit;
1125 }
1126 }
1127 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1128 {
1129 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1130 char extra[32];
1131 tANI_U8 len = 0;
1132
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001133 /* Check if the features OKC/CCX/11R are supported simultaneously,
1134 then this operation is not permitted (return FAILURE) */
1135 if (okcMode &&
1136 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1137 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1138 {
1139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1140 "%s: OKC/CCX/11R are supported simultaneously"
1141 " hence this operation is not permitted!", __func__);
1142 ret = -EPERM;
1143 goto exit;
1144 }
1145
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001146 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1147 if (copy_to_user(priv_data.buf, &extra, len + 1))
1148 {
1149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: failed to copy data to user buffer", __func__);
1151 ret = -EFAULT;
1152 goto exit;
1153 }
1154 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001155 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001156 {
1157 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1158 char extra[32];
1159 tANI_U8 len = 0;
1160
1161 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1162 if (copy_to_user(priv_data.buf, &extra, len + 1))
1163 {
1164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: failed to copy data to user buffer", __func__);
1166 ret = -EFAULT;
1167 goto exit;
1168 }
1169 }
1170 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1171 {
1172 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1173 char extra[32];
1174 tANI_U8 len = 0;
1175
1176 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1177 if (copy_to_user(priv_data.buf, &extra, len + 1))
1178 {
1179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1180 "%s: failed to copy data to user buffer", __func__);
1181 ret = -EFAULT;
1182 goto exit;
1183 }
1184 }
1185 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1186 {
1187 tANI_U8 *value = command;
1188 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1189
1190 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1191 value = value + 26;
1192 /* Convert the value from ascii to integer */
1193 ret = kstrtou8(value, 10, &minTime);
1194 if (ret < 0)
1195 {
1196 /* If the input value is greater than max value of datatype, then also
1197 kstrtou8 fails */
1198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1199 "%s: kstrtou8 failed range [%d - %d]", __func__,
1200 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1201 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1202 ret = -EINVAL;
1203 goto exit;
1204 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001205 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1206 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1207 {
1208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1209 "scan min channel time value %d is out of range"
1210 " (Min: %d Max: %d)", minTime,
1211 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1212 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1213 ret = -EINVAL;
1214 goto exit;
1215 }
1216
1217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1218 "%s: Received Command to change channel min time = %d", __func__, minTime);
1219
1220 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1221 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1222 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001223 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1224 {
1225 tANI_U8 *value = command;
1226 tANI_U8 channel = 0;
1227 tANI_U8 dwellTime = 0;
1228 tANI_U8 bufLen = 0;
1229 tANI_U8 *buf = NULL;
1230 tSirMacAddr targetApBssid;
1231 eHalStatus status = eHAL_STATUS_SUCCESS;
1232 struct ieee80211_channel chan;
1233 tANI_U8 finalLen = 0;
1234 tANI_U8 *finalBuf = NULL;
1235 tANI_U8 temp = 0;
1236 u64 cookie;
1237 hdd_station_ctx_t *pHddStaCtx = NULL;
1238 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1239
1240 /* if not associated, no need to send action frame */
1241 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1242 {
1243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1244 ret = -EINVAL;
1245 goto exit;
1246 }
1247
1248 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1249 &dwellTime, &buf, &bufLen);
1250 if (eHAL_STATUS_SUCCESS != status)
1251 {
1252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1253 "%s: Failed to parse send action frame data", __func__);
1254 ret = -EINVAL;
1255 goto exit;
1256 }
1257
1258 /* if the target bssid is different from currently associated AP,
1259 then no need to send action frame */
1260 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1261 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1262 {
1263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1264 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001265 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001266 goto exit;
1267 }
1268
1269 /* if the channel number is different from operating channel then
1270 no need to send action frame */
1271 if (channel != pHddStaCtx->conn_info.operationChannel)
1272 {
1273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1274 "%s: channel(%d) is different from operating channel(%d)",
1275 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1276 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001277 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001278 goto exit;
1279 }
1280 chan.center_freq = sme_ChnToFreq(channel);
1281
1282 finalLen = bufLen + 24;
1283 finalBuf = vos_mem_malloc(finalLen);
1284 if (NULL == finalBuf)
1285 {
1286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1287 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001288 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001289 goto exit;
1290 }
1291 vos_mem_zero(finalBuf, finalLen);
1292
1293 /* Fill subtype */
1294 temp = SIR_MAC_MGMT_ACTION << 4;
1295 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1296
1297 /* Fill type */
1298 temp = SIR_MAC_MGMT_FRAME;
1299 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1300
1301 /* Fill destination address (bssid of the AP) */
1302 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1303
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001304 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001305 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1306
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001307 /* Fill BSSID (AP mac address) */
1308 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001309
1310 /* Fill received buffer from 24th address */
1311 vos_mem_copy(finalBuf + 24, buf, bufLen);
1312
Jeff Johnson11c33152013-04-16 17:52:40 -07001313 /* done with the parsed buffer */
1314 vos_mem_free(buf);
1315
Yue Maf49ba872013-08-19 12:04:25 -07001316 wlan_hdd_action( NULL,
1317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1318 &(pAdapter->wdev),
1319#else
1320 dev,
1321#endif
1322 &chan, 0,
1323#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1324 NL80211_CHAN_HT20, 1,
1325#endif
1326 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001327 1, &cookie );
1328 vos_mem_free(finalBuf);
1329 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001330 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1331 {
1332 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1333 char extra[32];
1334 tANI_U8 len = 0;
1335
1336 /* value is interms of msec */
1337 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1338 if (copy_to_user(priv_data.buf, &extra, len + 1))
1339 {
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1341 "%s: failed to copy data to user buffer", __func__);
1342 ret = -EFAULT;
1343 goto exit;
1344 }
1345 }
1346 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1347 {
1348 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001349 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001350 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001351
1352 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1353 value = value + 19;
1354 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001355 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001356 if (ret < 0)
1357 {
1358 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001359 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001361 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001362 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1363 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1364 ret = -EINVAL;
1365 goto exit;
1366 }
1367
1368 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1369 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1370 {
1371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1372 "lfr mode value %d is out of range"
1373 " (Min: %d Max: %d)", maxTime,
1374 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1375 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1376 ret = -EINVAL;
1377 goto exit;
1378 }
1379
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1381 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1382
1383 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001384
1385 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1386 * where RFS is the RF Switching time. It is twice RFS to consider the
1387 * time to go off channel and return to the home channel. */
1388 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1389 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1390 {
1391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1392 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1393 " Hence enforcing home away time to disable (0)",
1394 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1395 homeAwayTime = 0;
1396 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1397 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1398 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001399 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1400 }
1401 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1402 {
1403 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1404 char extra[32];
1405 tANI_U8 len = 0;
1406
1407 /* value is interms of msec */
1408 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1409 if (copy_to_user(priv_data.buf, &extra, len + 1))
1410 {
1411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1412 "%s: failed to copy data to user buffer", __func__);
1413 ret = -EFAULT;
1414 goto exit;
1415 }
1416 }
1417 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1418 {
1419 tANI_U8 *value = command;
1420 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1421
1422 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1423 value = value + 16;
1424 /* Convert the value from ascii to integer */
1425 ret = kstrtou16(value, 10, &val);
1426 if (ret < 0)
1427 {
1428 /* If the input value is greater than max value of datatype, then also
1429 kstrtou16 fails */
1430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1431 "%s: kstrtou16 failed range [%d - %d]", __func__,
1432 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1433 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1434 ret = -EINVAL;
1435 goto exit;
1436 }
1437
1438 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1439 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1440 {
1441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1442 "scan home time value %d is out of range"
1443 " (Min: %d Max: %d)", val,
1444 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1445 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1446 ret = -EINVAL;
1447 goto exit;
1448 }
1449
1450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1451 "%s: Received Command to change scan home time = %d", __func__, val);
1452
1453 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1454 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1455 }
1456 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1457 {
1458 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1459 char extra[32];
1460 tANI_U8 len = 0;
1461
1462 /* value is interms of msec */
1463 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1464 if (copy_to_user(priv_data.buf, &extra, len + 1))
1465 {
1466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1467 "%s: failed to copy data to user buffer", __func__);
1468 ret = -EFAULT;
1469 goto exit;
1470 }
1471 }
1472 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1473 {
1474 tANI_U8 *value = command;
1475 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1476
1477 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1478 value = value + 17;
1479 /* Convert the value from ascii to integer */
1480 ret = kstrtou8(value, 10, &val);
1481 if (ret < 0)
1482 {
1483 /* If the input value is greater than max value of datatype, then also
1484 kstrtou8 fails */
1485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1486 "%s: kstrtou8 failed range [%d - %d]", __func__,
1487 CFG_ROAM_INTRA_BAND_MIN,
1488 CFG_ROAM_INTRA_BAND_MAX);
1489 ret = -EINVAL;
1490 goto exit;
1491 }
1492
1493 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1494 (val > CFG_ROAM_INTRA_BAND_MAX))
1495 {
1496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1497 "intra band mode value %d is out of range"
1498 " (Min: %d Max: %d)", val,
1499 CFG_ROAM_INTRA_BAND_MIN,
1500 CFG_ROAM_INTRA_BAND_MAX);
1501 ret = -EINVAL;
1502 goto exit;
1503 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1505 "%s: Received Command to change intra band = %d", __func__, val);
1506
1507 pHddCtx->cfg_ini->nRoamIntraBand = val;
1508 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1509 }
1510 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1511 {
1512 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1513 char extra[32];
1514 tANI_U8 len = 0;
1515
1516 /* value is interms of msec */
1517 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1518 if (copy_to_user(priv_data.buf, &extra, len + 1))
1519 {
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1521 "%s: failed to copy data to user buffer", __func__);
1522 ret = -EFAULT;
1523 goto exit;
1524 }
1525 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001526 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1527 {
1528 tANI_U8 *value = command;
1529 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1530
1531 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1532 value = value + 15;
1533 /* Convert the value from ascii to integer */
1534 ret = kstrtou8(value, 10, &nProbes);
1535 if (ret < 0)
1536 {
1537 /* If the input value is greater than max value of datatype, then also
1538 kstrtou8 fails */
1539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1540 "%s: kstrtou8 failed range [%d - %d]", __func__,
1541 CFG_ROAM_SCAN_N_PROBES_MIN,
1542 CFG_ROAM_SCAN_N_PROBES_MAX);
1543 ret = -EINVAL;
1544 goto exit;
1545 }
1546
1547 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1548 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1549 {
1550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1551 "NProbes value %d is out of range"
1552 " (Min: %d Max: %d)", nProbes,
1553 CFG_ROAM_SCAN_N_PROBES_MIN,
1554 CFG_ROAM_SCAN_N_PROBES_MAX);
1555 ret = -EINVAL;
1556 goto exit;
1557 }
1558
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1560 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1561
1562 pHddCtx->cfg_ini->nProbes = nProbes;
1563 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1564 }
1565 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1566 {
1567 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1568 char extra[32];
1569 tANI_U8 len = 0;
1570
1571 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1572 if (copy_to_user(priv_data.buf, &extra, len + 1))
1573 {
1574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1575 "%s: failed to copy data to user buffer", __func__);
1576 ret = -EFAULT;
1577 goto exit;
1578 }
1579 }
1580 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1581 {
1582 tANI_U8 *value = command;
1583 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001584 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001585
1586 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1587 /* input value is in units of msec */
1588 value = value + 20;
1589 /* Convert the value from ascii to integer */
1590 ret = kstrtou16(value, 10, &homeAwayTime);
1591 if (ret < 0)
1592 {
1593 /* If the input value is greater than max value of datatype, then also
1594 kstrtou8 fails */
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1596 "%s: kstrtou8 failed range [%d - %d]", __func__,
1597 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1598 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1599 ret = -EINVAL;
1600 goto exit;
1601 }
1602
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001603 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1604 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1605 {
1606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "homeAwayTime value %d is out of range"
1608 " (Min: %d Max: %d)", homeAwayTime,
1609 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1610 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1611 ret = -EINVAL;
1612 goto exit;
1613 }
1614
1615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1616 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1617
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001618 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1619 * where RFS is the RF Switching time. It is twice RFS to consider the
1620 * time to go off channel and return to the home channel. */
1621 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1622 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1623 {
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1625 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1626 " Hence enforcing home away time to disable (0)",
1627 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1628 homeAwayTime = 0;
1629 }
1630
1631 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1632 {
1633 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1634 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1635 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001636 }
1637 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1638 {
1639 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1640 char extra[32];
1641 tANI_U8 len = 0;
1642
1643 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1644 if (copy_to_user(priv_data.buf, &extra, len + 1))
1645 {
1646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "%s: failed to copy data to user buffer", __func__);
1648 ret = -EFAULT;
1649 goto exit;
1650 }
1651 }
1652 else if (strncmp(command, "REASSOC", 7) == 0)
1653 {
1654 tANI_U8 *value = command;
1655 tANI_U8 channel = 0;
1656 tSirMacAddr targetApBssid;
1657 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001658#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1659 tCsrHandoffRequest handoffInfo;
1660#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001661 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001662 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1663
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001664 /* if not associated, no need to proceed with reassoc */
1665 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1666 {
1667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1668 ret = -EINVAL;
1669 goto exit;
1670 }
1671
1672 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1673 if (eHAL_STATUS_SUCCESS != status)
1674 {
1675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1676 "%s: Failed to parse reassoc command data", __func__);
1677 ret = -EINVAL;
1678 goto exit;
1679 }
1680
1681 /* if the target bssid is same as currently associated AP,
1682 then no need to proceed with reassoc */
1683 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1684 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1685 {
1686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1687 ret = -EINVAL;
1688 goto exit;
1689 }
1690
1691 /* Check channel number is a valid channel number */
1692 if(VOS_STATUS_SUCCESS !=
1693 wlan_hdd_validate_operation_channel(pAdapter, channel))
1694 {
1695 hddLog(VOS_TRACE_LEVEL_ERROR,
1696 "%s: Invalid Channel [%d] \n", __func__, channel);
1697 return -EINVAL;
1698 }
1699
1700 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001701#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1702 handoffInfo.channel = channel;
1703 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1704 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1705#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001706 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001707#endif
1708#ifdef FEATURE_WLAN_LFR
1709 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1710 {
1711 tANI_U8 *value = command;
1712 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1713
1714 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1715 value = value + 12;
1716 /* Convert the value from ascii to integer */
1717 ret = kstrtou8(value, 10, &lfrMode);
1718 if (ret < 0)
1719 {
1720 /* If the input value is greater than max value of datatype, then also
1721 kstrtou8 fails */
1722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1723 "%s: kstrtou8 failed range [%d - %d]", __func__,
1724 CFG_LFR_FEATURE_ENABLED_MIN,
1725 CFG_LFR_FEATURE_ENABLED_MAX);
1726 ret = -EINVAL;
1727 goto exit;
1728 }
1729
1730 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1731 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "lfr mode value %d is out of range"
1735 " (Min: %d Max: %d)", lfrMode,
1736 CFG_LFR_FEATURE_ENABLED_MIN,
1737 CFG_LFR_FEATURE_ENABLED_MAX);
1738 ret = -EINVAL;
1739 goto exit;
1740 }
1741
1742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1743 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1744
1745 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1746 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1747 }
1748#endif
1749#ifdef WLAN_FEATURE_VOWIFI_11R
1750 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1751 {
1752 tANI_U8 *value = command;
1753 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1754
1755 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1756 value = value + 18;
1757 /* Convert the value from ascii to integer */
1758 ret = kstrtou8(value, 10, &ft);
1759 if (ret < 0)
1760 {
1761 /* If the input value is greater than max value of datatype, then also
1762 kstrtou8 fails */
1763 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1764 "%s: kstrtou8 failed range [%d - %d]", __func__,
1765 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1766 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1767 ret = -EINVAL;
1768 goto exit;
1769 }
1770
1771 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1772 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1773 {
1774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 "ft mode value %d is out of range"
1776 " (Min: %d Max: %d)", ft,
1777 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1778 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1779 ret = -EINVAL;
1780 goto exit;
1781 }
1782
1783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1784 "%s: Received Command to change ft mode = %d", __func__, ft);
1785
1786 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1787 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1788 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05301789
1790 else if (strncmp(command, "FASTREASSOC", 11) == 0)
1791 {
1792 tANI_U8 *value = command;
1793 tSirMacAddr targetApBssid;
1794 tANI_U8 trigger = 0;
1795 eHalStatus status = eHAL_STATUS_SUCCESS;
1796 hdd_station_ctx_t *pHddStaCtx = NULL;
1797 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1798
1799 /* if not associated, no need to proceed with reassoc */
1800 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1801 {
1802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
1807 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
1808 if (eHAL_STATUS_SUCCESS != status)
1809 {
1810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1811 "%s: Failed to parse reassoc command data", __func__);
1812 ret = -EINVAL;
1813 goto exit;
1814 }
1815
1816 /* if the target bssid is same as currently associated AP,
1817 then no need to proceed with reassoc */
1818 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1819 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1820 {
1821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1822 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
1823 __func__);
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827
1828 /* Proceed with scan/roam */
1829 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
1830 &targetApBssid[0],
1831 (tSmeFastRoamTrigger)(trigger));
1832 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001833#endif
1834#ifdef FEATURE_WLAN_CCX
1835 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1836 {
1837 tANI_U8 *value = command;
1838 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1839
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001840 /* Check if the features OKC/CCX/11R are supported simultaneously,
1841 then this operation is not permitted (return FAILURE) */
1842 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1843 hdd_is_okc_mode_enabled(pHddCtx) &&
1844 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1845 {
1846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1847 "%s: OKC/CCX/11R are supported simultaneously"
1848 " hence this operation is not permitted!", __func__);
1849 ret = -EPERM;
1850 goto exit;
1851 }
1852
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001853 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1854 value = value + 11;
1855 /* Convert the value from ascii to integer */
1856 ret = kstrtou8(value, 10, &ccxMode);
1857 if (ret < 0)
1858 {
1859 /* If the input value is greater than max value of datatype, then also
1860 kstrtou8 fails */
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1862 "%s: kstrtou8 failed range [%d - %d]", __func__,
1863 CFG_CCX_FEATURE_ENABLED_MIN,
1864 CFG_CCX_FEATURE_ENABLED_MAX);
1865 ret = -EINVAL;
1866 goto exit;
1867 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001868 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1869 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1870 {
1871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1872 "Ccx mode value %d is out of range"
1873 " (Min: %d Max: %d)", ccxMode,
1874 CFG_CCX_FEATURE_ENABLED_MIN,
1875 CFG_CCX_FEATURE_ENABLED_MAX);
1876 ret = -EINVAL;
1877 goto exit;
1878 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1880 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1881
1882 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1883 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1884 }
1885#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001886 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1887 {
1888 tANI_U8 *value = command;
1889 tANI_BOOLEAN roamScanControl = 0;
1890
1891 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1892 value = value + 19;
1893 /* Convert the value from ascii to integer */
1894 ret = kstrtou8(value, 10, &roamScanControl);
1895 if (ret < 0)
1896 {
1897 /* If the input value is greater than max value of datatype, then also
1898 kstrtou8 fails */
1899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1900 "%s: kstrtou8 failed ", __func__);
1901 ret = -EINVAL;
1902 goto exit;
1903 }
1904
1905 if (0 != roamScanControl)
1906 {
1907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1908 "roam scan control invalid value = %d",
1909 roamScanControl);
1910 ret = -EINVAL;
1911 goto exit;
1912 }
1913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1914 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1915
1916 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1917 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001918#ifdef FEATURE_WLAN_OKC
1919 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1920 {
1921 tANI_U8 *value = command;
1922 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1923
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001924 /* Check if the features OKC/CCX/11R are supported simultaneously,
1925 then this operation is not permitted (return FAILURE) */
1926 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1927 hdd_is_okc_mode_enabled(pHddCtx) &&
1928 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1929 {
1930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1931 "%s: OKC/CCX/11R are supported simultaneously"
1932 " hence this operation is not permitted!", __func__);
1933 ret = -EPERM;
1934 goto exit;
1935 }
1936
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001937 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1938 value = value + 11;
1939 /* Convert the value from ascii to integer */
1940 ret = kstrtou8(value, 10, &okcMode);
1941 if (ret < 0)
1942 {
1943 /* If the input value is greater than max value of datatype, then also
1944 kstrtou8 fails */
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 "%s: kstrtou8 failed range [%d - %d]", __func__,
1947 CFG_OKC_FEATURE_ENABLED_MIN,
1948 CFG_OKC_FEATURE_ENABLED_MAX);
1949 ret = -EINVAL;
1950 goto exit;
1951 }
1952
1953 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1954 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1955 {
1956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1957 "Okc mode value %d is out of range"
1958 " (Min: %d Max: %d)", okcMode,
1959 CFG_OKC_FEATURE_ENABLED_MIN,
1960 CFG_OKC_FEATURE_ENABLED_MAX);
1961 ret = -EINVAL;
1962 goto exit;
1963 }
1964
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1966 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1967
1968 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1969 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001970 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1971 {
1972 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1973 char extra[32];
1974 tANI_U8 len = 0;
1975
1976 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1977 if (copy_to_user(priv_data.buf, &extra, len + 1))
1978 {
1979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 "%s: failed to copy data to user buffer", __func__);
1981 ret = -EFAULT;
1982 goto exit;
1983 }
1984 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001985#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301986#ifdef WLAN_FEATURE_PACKET_FILTERING
1987 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1988 {
1989 tANI_U8 filterType = 0;
1990 tANI_U8 *value = command;
1991
1992 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1993 value = value + 22;
1994
1995 /* Convert the value from ascii to integer */
1996 ret = kstrtou8(value, 10, &filterType);
1997 if (ret < 0)
1998 {
1999 /* If the input value is greater than max value of datatype,
2000 * then also kstrtou8 fails
2001 */
2002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2003 "%s: kstrtou8 failed range ", __func__);
2004 ret = -EINVAL;
2005 goto exit;
2006 }
2007
2008 if (filterType != 0 && filterType != 1)
2009 {
2010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2011 "%s: Accepted Values are 0 and 1 ", __func__);
2012 ret = -EINVAL;
2013 goto exit;
2014 }
2015 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2016 pAdapter->sessionId);
2017 }
2018#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302019 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2020 {
2021 char *dhcpPhase;
2022 dhcpPhase = command + 12;
2023 if ('1' == *dhcpPhase)
2024 {
2025 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2026 pAdapter->macAddressCurrent.bytes);
2027 }
2028 else if ('2' == *dhcpPhase)
2029 {
2030 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2031 pAdapter->macAddressCurrent.bytes);
2032 }
2033 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002034 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2035 {
2036 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2037 }
2038 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2039 {
2040 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2041 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302042 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2043 {
2044 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2045 char extra[32];
2046 tANI_U8 len = 0;
2047
2048 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
2049 (int)pCfg->nActiveMaxChnTime);
2050 if (copy_to_user(priv_data.buf, &extra, len + 1))
2051 {
2052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2053 "%s: failed to copy data to user buffer", __func__);
2054 ret = -EFAULT;
2055 goto exit;
2056 }
2057 ret = len;
2058 }
2059 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2060 {
2061 tANI_U8 *value = command;
2062 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2063 int val = 0, temp;
2064
2065 value = value + 13;
2066 temp = kstrtou32(value, 10, &val);
2067 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2068 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2069 {
2070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2071 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2072 ret = -EFAULT;
2073 goto exit;
2074 }
2075 pCfg->nActiveMaxChnTime = val;
2076 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002077 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2078 {
2079 tANI_U8 filterType = 0;
2080 tANI_U8 *value;
2081 value = command + 9;
2082
2083 /* Convert the value from ascii to integer */
2084 ret = kstrtou8(value, 10, &filterType);
2085 if (ret < 0)
2086 {
2087 /* If the input value is greater than max value of datatype,
2088 * then also kstrtou8 fails
2089 */
2090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2091 "%s: kstrtou8 failed range ", __func__);
2092 ret = -EINVAL;
2093 goto exit;
2094 }
2095 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2096 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2097 {
2098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2099 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2100 " 2-Sink ", __func__);
2101 ret = -EINVAL;
2102 goto exit;
2103 }
2104 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2105 pHddCtx->drvr_miracast = filterType;
2106 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2107 }
Leo Chang614d2072013-08-22 14:59:44 -07002108 else if (strncmp(command, "SETMCRATE", 9) == 0)
2109 {
2110 int rc;
2111 tANI_U8 *value = command;
2112 int targetRate;
2113
2114 /* Only valid for SAP mode */
2115 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2116 {
2117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2118 "%s: SAP mode is not running", __func__);
2119 ret = -EFAULT;
2120 goto exit;
2121 }
2122
2123 /* Move pointer to ahead of SETMCRATE<delimiter> */
2124 /* input value is in units of hundred kbps */
2125 value = value + 10;
2126 /* Convert the value from ascii to integer, decimal base */
2127 ret = kstrtouint(value, 10, &targetRate);
2128
2129 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2130 if (rc)
2131 {
2132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2133 "%s: Set MC Rate Fail %d", __func__, rc);
2134 ret = -EFAULT;
2135 goto exit;
2136 }
2137 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002138 else {
2139 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2140 __func__, command);
2141 }
2142
Jeff Johnson295189b2012-06-20 16:38:30 -07002143 }
2144exit:
2145 if (command)
2146 {
2147 kfree(command);
2148 }
2149 return ret;
2150}
2151
Srinivas Girigowdade697412013-02-14 16:31:48 -08002152#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2153void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2154{
2155 eCsrBand band = -1;
2156 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2157 switch (band)
2158 {
2159 case eCSR_BAND_ALL:
2160 *pBand = WLAN_HDD_UI_BAND_AUTO;
2161 break;
2162
2163 case eCSR_BAND_24:
2164 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2165 break;
2166
2167 case eCSR_BAND_5G:
2168 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2169 break;
2170
2171 default:
2172 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2173 *pBand = -1;
2174 break;
2175 }
2176}
2177
2178/**---------------------------------------------------------------------------
2179
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002180 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2181
2182 This function parses the send action frame data passed in the format
2183 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2184
Srinivas Girigowda56076852013-08-20 14:00:50 -07002185 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002186 \param - pTargetApBssid Pointer to target Ap bssid
2187 \param - pChannel Pointer to the Target AP channel
2188 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2189 \param - pBuf Pointer to data
2190 \param - pBufLen Pointer to data length
2191
2192 \return - 0 for success non-zero for failure
2193
2194 --------------------------------------------------------------------------*/
2195VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2196 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2197{
2198 tANI_U8 *inPtr = pValue;
2199 tANI_U8 *dataEnd;
2200 int tempInt;
2201 int j = 0;
2202 int i = 0;
2203 int v = 0;
2204 tANI_U8 tempBuf[32];
2205 tANI_U8 tempByte = 0;
2206
2207 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2208 /*no argument after the command*/
2209 if (NULL == inPtr)
2210 {
2211 return -EINVAL;
2212 }
2213
2214 /*no space after the command*/
2215 else if (SPACE_ASCII_VALUE != *inPtr)
2216 {
2217 return -EINVAL;
2218 }
2219
2220 /*removing empty spaces*/
2221 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2222
2223 /*no argument followed by spaces*/
2224 if ('\0' == *inPtr)
2225 {
2226 return -EINVAL;
2227 }
2228
2229 /*getting the first argument ie the target AP bssid */
2230 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2231 {
2232 return -EINVAL;
2233 }
2234 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2235 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2236 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2237
2238 /* point to the next argument */
2239 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2240 /*no argument after the command*/
2241 if (NULL == inPtr) return -EINVAL;
2242
2243 /*removing empty spaces*/
2244 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2245
2246 /*no argument followed by spaces*/
2247 if ('\0' == *inPtr)
2248 {
2249 return -EINVAL;
2250 }
2251
2252 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002253 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002254 v = kstrtos32(tempBuf, 10, &tempInt);
2255 if ( v < 0) return -EINVAL;
2256
2257 *pChannel = tempInt;
2258
2259 /* point to the next argument */
2260 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2261 /*no argument after the command*/
2262 if (NULL == inPtr) return -EINVAL;
2263 /*removing empty spaces*/
2264 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2265
2266 /*no argument followed by spaces*/
2267 if ('\0' == *inPtr)
2268 {
2269 return -EINVAL;
2270 }
2271
2272 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002273 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002274 v = kstrtos32(tempBuf, 10, &tempInt);
2275 if ( v < 0) return -EINVAL;
2276
2277 *pDwellTime = tempInt;
2278
2279 /* point to the next argument */
2280 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2281 /*no argument after the command*/
2282 if (NULL == inPtr) return -EINVAL;
2283 /*removing empty spaces*/
2284 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2285
2286 /*no argument followed by spaces*/
2287 if ('\0' == *inPtr)
2288 {
2289 return -EINVAL;
2290 }
2291
2292 /* find the length of data */
2293 dataEnd = inPtr;
2294 while(('\0' != *dataEnd) )
2295 {
2296 dataEnd++;
2297 ++(*pBufLen);
2298 }
2299 if ( *pBufLen <= 0) return -EINVAL;
2300
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002301 /* Allocate the number of bytes based on the number of input characters
2302 whether it is even or odd.
2303 if the number of input characters are even, then we need N/2 byte.
2304 if the number of input characters are odd, then we need do (N+1)/2 to
2305 compensate rounding off.
2306 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2307 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2308 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002309 if (NULL == *pBuf)
2310 {
2311 hddLog(VOS_TRACE_LEVEL_FATAL,
2312 "%s: vos_mem_alloc failed ", __func__);
2313 return -EINVAL;
2314 }
2315
2316 /* the buffer received from the upper layer is character buffer,
2317 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2318 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2319 and f0 in 3rd location */
2320 for (i = 0, j = 0; j < *pBufLen; j += 2)
2321 {
2322 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2323 (*pBuf)[i++] = tempByte;
2324 }
2325 *pBufLen = i;
2326 return VOS_STATUS_SUCCESS;
2327}
2328
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002329/**---------------------------------------------------------------------------
2330
Srinivas Girigowdade697412013-02-14 16:31:48 -08002331 \brief hdd_parse_channellist() - HDD Parse channel list
2332
2333 This function parses the channel list passed in the format
2334 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002335 if the Number of channels (N) does not match with the actual number of channels passed
2336 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2337 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2338 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2339 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002340
2341 \param - pValue Pointer to input channel list
2342 \param - ChannelList Pointer to local output array to record channel list
2343 \param - pNumChannels Pointer to number of roam scan channels
2344
2345 \return - 0 for success non-zero for failure
2346
2347 --------------------------------------------------------------------------*/
2348VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2349{
2350 tANI_U8 *inPtr = pValue;
2351 int tempInt;
2352 int j = 0;
2353 int v = 0;
2354 char buf[32];
2355
2356 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2357 /*no argument after the command*/
2358 if (NULL == inPtr)
2359 {
2360 return -EINVAL;
2361 }
2362
2363 /*no space after the command*/
2364 else if (SPACE_ASCII_VALUE != *inPtr)
2365 {
2366 return -EINVAL;
2367 }
2368
2369 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002370 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002371
2372 /*no argument followed by spaces*/
2373 if ('\0' == *inPtr)
2374 {
2375 return -EINVAL;
2376 }
2377
2378 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002379 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002380 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002381 if ((v < 0) ||
2382 (tempInt <= 0) ||
2383 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2384 {
2385 return -EINVAL;
2386 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002387
2388 *pNumChannels = tempInt;
2389
2390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2391 "Number of channels are: %d", *pNumChannels);
2392
2393 for (j = 0; j < (*pNumChannels); j++)
2394 {
2395 /*inPtr pointing to the beginning of first space after number of channels*/
2396 inPtr = strpbrk( inPtr, " " );
2397 /*no channel list after the number of channels argument*/
2398 if (NULL == inPtr)
2399 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002400 if (0 != j)
2401 {
2402 *pNumChannels = j;
2403 return VOS_STATUS_SUCCESS;
2404 }
2405 else
2406 {
2407 return -EINVAL;
2408 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002409 }
2410
2411 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002412 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002413
2414 /*no channel list after the number of channels argument and spaces*/
2415 if ( '\0' == *inPtr )
2416 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002417 if (0 != j)
2418 {
2419 *pNumChannels = j;
2420 return VOS_STATUS_SUCCESS;
2421 }
2422 else
2423 {
2424 return -EINVAL;
2425 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002426 }
2427
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002428 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002429 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002430 if ((v < 0) ||
2431 (tempInt <= 0) ||
2432 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2433 {
2434 return -EINVAL;
2435 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002436 pChannelList[j] = tempInt;
2437
2438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2439 "Channel %d added to preferred channel list",
2440 pChannelList[j] );
2441 }
2442
Srinivas Girigowdade697412013-02-14 16:31:48 -08002443 return VOS_STATUS_SUCCESS;
2444}
2445
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002446
2447/**---------------------------------------------------------------------------
2448
2449 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2450
2451 This function parses the reasoc command data passed in the format
2452 REASSOC<space><bssid><space><channel>
2453
Srinivas Girigowda56076852013-08-20 14:00:50 -07002454 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002455 \param - pTargetApBssid Pointer to target Ap bssid
2456 \param - pChannel Pointer to the Target AP channel
2457
2458 \return - 0 for success non-zero for failure
2459
2460 --------------------------------------------------------------------------*/
2461VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2462{
2463 tANI_U8 *inPtr = pValue;
2464 int tempInt;
2465 int v = 0;
2466 tANI_U8 tempBuf[32];
2467
2468 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2469 /*no argument after the command*/
2470 if (NULL == inPtr)
2471 {
2472 return -EINVAL;
2473 }
2474
2475 /*no space after the command*/
2476 else if (SPACE_ASCII_VALUE != *inPtr)
2477 {
2478 return -EINVAL;
2479 }
2480
2481 /*removing empty spaces*/
2482 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2483
2484 /*no argument followed by spaces*/
2485 if ('\0' == *inPtr)
2486 {
2487 return -EINVAL;
2488 }
2489
2490 /*getting the first argument ie the target AP bssid */
2491 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2492 {
2493 return -EINVAL;
2494 }
2495 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2496 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2497 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2498
2499 /* point to the next argument */
2500 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2501 /*no argument after the command*/
2502 if (NULL == inPtr) return -EINVAL;
2503
2504 /*removing empty spaces*/
2505 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2506
2507 /*no argument followed by spaces*/
2508 if ('\0' == *inPtr)
2509 {
2510 return -EINVAL;
2511 }
2512
2513 /*getting the next argument ie the channel number */
2514 sscanf(inPtr, "%s ", tempBuf);
2515 v = kstrtos32(tempBuf, 10, &tempInt);
2516 if ( v < 0) return -EINVAL;
2517
2518 *pChannel = tempInt;
2519 return VOS_STATUS_SUCCESS;
2520}
2521
2522#endif
2523
Jeff Johnson295189b2012-06-20 16:38:30 -07002524/**---------------------------------------------------------------------------
2525
2526 \brief hdd_open() - HDD Open function
2527
2528 This is called in response to ifconfig up
2529
2530 \param - dev Pointer to net_device structure
2531
2532 \return - 0 for success non-zero for failure
2533
2534 --------------------------------------------------------------------------*/
2535int hdd_open (struct net_device *dev)
2536{
2537 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2538 hdd_context_t *pHddCtx;
2539 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2540 VOS_STATUS status;
2541 v_BOOL_t in_standby = TRUE;
2542
2543 if (NULL == pAdapter)
2544 {
2545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002546 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002547 return -ENODEV;
2548 }
2549
2550 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2551 if (NULL == pHddCtx)
2552 {
2553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002554 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 return -ENODEV;
2556 }
2557
2558 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2559 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2560 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002561 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2562 {
2563 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302564 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002565 in_standby = FALSE;
2566 break;
2567 }
2568 else
2569 {
2570 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2571 pAdapterNode = pNext;
2572 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002573 }
2574
2575 if (TRUE == in_standby)
2576 {
2577 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2578 {
2579 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2580 "wlan out of power save", __func__);
2581 return -EINVAL;
2582 }
2583 }
2584
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002585 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2587 {
2588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002589 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 /* Enable TX queues only when we are connected */
2591 netif_tx_start_all_queues(dev);
2592 }
2593
2594 return 0;
2595}
2596
2597int hdd_mon_open (struct net_device *dev)
2598{
2599 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2600
2601 if(pAdapter == NULL) {
2602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002603 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002604 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002605 }
2606
2607 netif_start_queue(dev);
2608
2609 return 0;
2610}
2611/**---------------------------------------------------------------------------
2612
2613 \brief hdd_stop() - HDD stop function
2614
2615 This is called in response to ifconfig down
2616
2617 \param - dev Pointer to net_device structure
2618
2619 \return - 0 for success non-zero for failure
2620
2621 --------------------------------------------------------------------------*/
2622
2623int hdd_stop (struct net_device *dev)
2624{
2625 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2626 hdd_context_t *pHddCtx;
2627 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2628 VOS_STATUS status;
2629 v_BOOL_t enter_standby = TRUE;
2630
2631 ENTER();
2632
2633 if (NULL == pAdapter)
2634 {
2635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002636 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002637 return -ENODEV;
2638 }
2639
2640 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2641 if (NULL == pHddCtx)
2642 {
2643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002644 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002645 return -ENODEV;
2646 }
2647
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002648 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002649 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2650 netif_tx_disable(pAdapter->dev);
2651 netif_carrier_off(pAdapter->dev);
2652
2653
2654 /* SoftAP ifaces should never go in power save mode
2655 making sure same here. */
2656 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2657 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002658 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002659 )
2660 {
2661 /* SoftAP mode, so return from here */
2662 EXIT();
2663 return 0;
2664 }
2665
2666 /* Find if any iface is up then
2667 if any iface is up then can't put device to sleep/ power save mode. */
2668 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2669 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2670 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002671 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2672 {
2673 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302674 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002675 enter_standby = FALSE;
2676 break;
2677 }
2678 else
2679 {
2680 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2681 pAdapterNode = pNext;
2682 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002683 }
2684
2685 if (TRUE == enter_standby)
2686 {
2687 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2688 "entering standby", __func__);
2689 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2690 {
2691 /*log and return success*/
2692 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2693 "wlan in power save", __func__);
2694 }
2695 }
2696
2697 EXIT();
2698 return 0;
2699}
2700
2701/**---------------------------------------------------------------------------
2702
2703 \brief hdd_uninit() - HDD uninit function
2704
2705 This is called during the netdev unregister to uninitialize all data
2706associated with the device
2707
2708 \param - dev Pointer to net_device structure
2709
2710 \return - void
2711
2712 --------------------------------------------------------------------------*/
2713static void hdd_uninit (struct net_device *dev)
2714{
2715 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2716
2717 ENTER();
2718
2719 do
2720 {
2721 if (NULL == pAdapter)
2722 {
2723 hddLog(VOS_TRACE_LEVEL_FATAL,
2724 "%s: NULL pAdapter", __func__);
2725 break;
2726 }
2727
2728 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2729 {
2730 hddLog(VOS_TRACE_LEVEL_FATAL,
2731 "%s: Invalid magic", __func__);
2732 break;
2733 }
2734
2735 if (NULL == pAdapter->pHddCtx)
2736 {
2737 hddLog(VOS_TRACE_LEVEL_FATAL,
2738 "%s: NULL pHddCtx", __func__);
2739 break;
2740 }
2741
2742 if (dev != pAdapter->dev)
2743 {
2744 hddLog(VOS_TRACE_LEVEL_FATAL,
2745 "%s: Invalid device reference", __func__);
2746 /* we haven't validated all cases so let this go for now */
2747 }
2748
2749 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2750
2751 /* after uninit our adapter structure will no longer be valid */
2752 pAdapter->dev = NULL;
2753 pAdapter->magic = 0;
2754 } while (0);
2755
2756 EXIT();
2757}
2758
2759/**---------------------------------------------------------------------------
2760
2761 \brief hdd_release_firmware() -
2762
2763 This function calls the release firmware API to free the firmware buffer.
2764
2765 \param - pFileName Pointer to the File Name.
2766 pCtx - Pointer to the adapter .
2767
2768
2769 \return - 0 for success, non zero for failure
2770
2771 --------------------------------------------------------------------------*/
2772
2773VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2774{
2775 VOS_STATUS status = VOS_STATUS_SUCCESS;
2776 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2777 ENTER();
2778
2779
2780 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2781
2782 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2783
2784 if(pHddCtx->fw) {
2785 release_firmware(pHddCtx->fw);
2786 pHddCtx->fw = NULL;
2787 }
2788 else
2789 status = VOS_STATUS_E_FAILURE;
2790 }
2791 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2792 if(pHddCtx->nv) {
2793 release_firmware(pHddCtx->nv);
2794 pHddCtx->nv = NULL;
2795 }
2796 else
2797 status = VOS_STATUS_E_FAILURE;
2798
2799 }
2800
2801 EXIT();
2802 return status;
2803}
2804
2805/**---------------------------------------------------------------------------
2806
2807 \brief hdd_request_firmware() -
2808
2809 This function reads the firmware file using the request firmware
2810 API and returns the the firmware data and the firmware file size.
2811
2812 \param - pfileName - Pointer to the file name.
2813 - pCtx - Pointer to the adapter .
2814 - ppfw_data - Pointer to the pointer of the firmware data.
2815 - pSize - Pointer to the file size.
2816
2817 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2818
2819 --------------------------------------------------------------------------*/
2820
2821
2822VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2823{
2824 int status;
2825 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2826 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2827 ENTER();
2828
2829 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2830
2831 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2832
2833 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2834 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2835 __func__, pfileName);
2836 retval = VOS_STATUS_E_FAILURE;
2837 }
2838
2839 else {
2840 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2841 *pSize = pHddCtx->fw->size;
2842 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2843 __func__, *pSize);
2844 }
2845 }
2846 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2847
2848 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2849
2850 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2852 __func__, pfileName);
2853 retval = VOS_STATUS_E_FAILURE;
2854 }
2855
2856 else {
2857 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2858 *pSize = pHddCtx->nv->size;
2859 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2860 __func__, *pSize);
2861 }
2862 }
2863
2864 EXIT();
2865 return retval;
2866}
2867/**---------------------------------------------------------------------------
2868 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2869
2870 This is the function invoked by SME to inform the result of a full power
2871 request issued by HDD
2872
2873 \param - callbackcontext - Pointer to cookie
2874 status - result of request
2875
2876 \return - None
2877
2878--------------------------------------------------------------------------*/
2879void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2880{
2881 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2882
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002883 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002884 if(&pHddCtx->full_pwr_comp_var)
2885 {
2886 complete(&pHddCtx->full_pwr_comp_var);
2887 }
2888}
2889
2890/**---------------------------------------------------------------------------
2891
2892 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2893
2894 This is the function invoked by SME to inform the result of BMPS
2895 request issued by HDD
2896
2897 \param - callbackcontext - Pointer to cookie
2898 status - result of request
2899
2900 \return - None
2901
2902--------------------------------------------------------------------------*/
2903void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2904{
2905
2906 struct completion *completion_var = (struct completion*) callbackContext;
2907
2908 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2909 if(completion_var != NULL)
2910 {
2911 complete(completion_var);
2912 }
2913}
2914
2915/**---------------------------------------------------------------------------
2916
2917 \brief hdd_get_cfg_file_size() -
2918
2919 This function reads the configuration file using the request firmware
2920 API and returns the configuration file size.
2921
2922 \param - pCtx - Pointer to the adapter .
2923 - pFileName - Pointer to the file name.
2924 - pBufSize - Pointer to the buffer size.
2925
2926 \return - 0 for success, non zero for failure
2927
2928 --------------------------------------------------------------------------*/
2929
2930VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2931{
2932 int status;
2933 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2934
2935 ENTER();
2936
2937 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2938
2939 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2940 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2941 status = VOS_STATUS_E_FAILURE;
2942 }
2943 else {
2944 *pBufSize = pHddCtx->fw->size;
2945 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2946 release_firmware(pHddCtx->fw);
2947 pHddCtx->fw = NULL;
2948 }
2949
2950 EXIT();
2951 return VOS_STATUS_SUCCESS;
2952}
2953
2954/**---------------------------------------------------------------------------
2955
2956 \brief hdd_read_cfg_file() -
2957
2958 This function reads the configuration file using the request firmware
2959 API and returns the cfg data and the buffer size of the configuration file.
2960
2961 \param - pCtx - Pointer to the adapter .
2962 - pFileName - Pointer to the file name.
2963 - pBuffer - Pointer to the data buffer.
2964 - pBufSize - Pointer to the buffer size.
2965
2966 \return - 0 for success, non zero for failure
2967
2968 --------------------------------------------------------------------------*/
2969
2970VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2971 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2972{
2973 int status;
2974 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2975
2976 ENTER();
2977
2978 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2979
2980 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2982 return VOS_STATUS_E_FAILURE;
2983 }
2984 else {
2985 if(*pBufSize != pHddCtx->fw->size) {
2986 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2987 "file size", __func__);
2988 release_firmware(pHddCtx->fw);
2989 pHddCtx->fw = NULL;
2990 return VOS_STATUS_E_FAILURE;
2991 }
2992 else {
2993 if(pBuffer) {
2994 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2995 }
2996 release_firmware(pHddCtx->fw);
2997 pHddCtx->fw = NULL;
2998 }
2999 }
3000
3001 EXIT();
3002
3003 return VOS_STATUS_SUCCESS;
3004}
3005
3006/**---------------------------------------------------------------------------
3007
Jeff Johnson295189b2012-06-20 16:38:30 -07003008 \brief hdd_set_mac_address() -
3009
3010 This function sets the user specified mac address using
3011 the command ifconfig wlanX hw ether <mac adress>.
3012
3013 \param - dev - Pointer to the net device.
3014 - addr - Pointer to the sockaddr.
3015 \return - 0 for success, non zero for failure
3016
3017 --------------------------------------------------------------------------*/
3018
3019static int hdd_set_mac_address(struct net_device *dev, void *addr)
3020{
3021 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3022 struct sockaddr *psta_mac_addr = addr;
3023 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3024
3025 ENTER();
3026
3027 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3028
3029#ifdef HDD_SESSIONIZE
3030 // set the MAC address though the STA ID CFG.
3031 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3032 (v_U8_t *)&pAdapter->macAddressCurrent,
3033 sizeof( pAdapter->macAddressCurrent ),
3034 hdd_set_mac_addr_cb, VOS_FALSE );
3035#endif
3036
3037 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3038
3039 EXIT();
3040 return halStatus;
3041}
3042
3043tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3044{
3045 int i;
3046 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3047 {
3048 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3049 break;
3050 }
3051
3052 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3053 return NULL;
3054
3055 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3056 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3057}
3058
3059void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3060{
3061 int i;
3062 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3063 {
3064 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3065 {
3066 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3067 break;
3068 }
3069 }
3070 return;
3071}
3072
3073#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3074 static struct net_device_ops wlan_drv_ops = {
3075 .ndo_open = hdd_open,
3076 .ndo_stop = hdd_stop,
3077 .ndo_uninit = hdd_uninit,
3078 .ndo_start_xmit = hdd_hard_start_xmit,
3079 .ndo_tx_timeout = hdd_tx_timeout,
3080 .ndo_get_stats = hdd_stats,
3081 .ndo_do_ioctl = hdd_ioctl,
3082 .ndo_set_mac_address = hdd_set_mac_address,
3083 .ndo_select_queue = hdd_select_queue,
3084#ifdef WLAN_FEATURE_PACKET_FILTERING
3085#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3086 .ndo_set_rx_mode = hdd_set_multicast_list,
3087#else
3088 .ndo_set_multicast_list = hdd_set_multicast_list,
3089#endif //LINUX_VERSION_CODE
3090#endif
3091 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 static struct net_device_ops wlan_mon_drv_ops = {
3093 .ndo_open = hdd_mon_open,
3094 .ndo_stop = hdd_stop,
3095 .ndo_uninit = hdd_uninit,
3096 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3097 .ndo_tx_timeout = hdd_tx_timeout,
3098 .ndo_get_stats = hdd_stats,
3099 .ndo_do_ioctl = hdd_ioctl,
3100 .ndo_set_mac_address = hdd_set_mac_address,
3101 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003102
3103#endif
3104
3105void hdd_set_station_ops( struct net_device *pWlanDev )
3106{
3107#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3108 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3109 pWlanDev->netdev_ops = &wlan_drv_ops;
3110#else
3111 pWlanDev->open = hdd_open;
3112 pWlanDev->stop = hdd_stop;
3113 pWlanDev->uninit = hdd_uninit;
3114 pWlanDev->hard_start_xmit = NULL;
3115 pWlanDev->tx_timeout = hdd_tx_timeout;
3116 pWlanDev->get_stats = hdd_stats;
3117 pWlanDev->do_ioctl = hdd_ioctl;
3118 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3119 pWlanDev->set_mac_address = hdd_set_mac_address;
3120#endif
3121}
3122
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003123static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003124{
3125 struct net_device *pWlanDev = NULL;
3126 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003127 /*
3128 * cfg80211 initialization and registration....
3129 */
3130 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3131
Jeff Johnson295189b2012-06-20 16:38:30 -07003132 if(pWlanDev != NULL)
3133 {
3134
3135 //Save the pointer to the net_device in the HDD adapter
3136 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3137
Jeff Johnson295189b2012-06-20 16:38:30 -07003138 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3139
3140 pAdapter->dev = pWlanDev;
3141 pAdapter->pHddCtx = pHddCtx;
3142 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3143
3144 init_completion(&pAdapter->session_open_comp_var);
3145 init_completion(&pAdapter->session_close_comp_var);
3146 init_completion(&pAdapter->disconnect_comp_var);
3147 init_completion(&pAdapter->linkup_event_var);
3148 init_completion(&pAdapter->cancel_rem_on_chan_var);
3149 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3151 init_completion(&pAdapter->offchannel_tx_event);
3152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003154#ifdef FEATURE_WLAN_TDLS
3155 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003156 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003157 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303158 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003159#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 init_completion(&pHddCtx->mc_sus_event_var);
3161 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303162 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003163 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003164 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07003165
Jeff Johnson295189b2012-06-20 16:38:30 -07003166 pAdapter->isLinkUpSvcNeeded = FALSE;
3167 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3168 //Init the net_device structure
3169 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3170
3171 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3172 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3173 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3174 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3175
3176 hdd_set_station_ops( pAdapter->dev );
3177
3178 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003179 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3180 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3181 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003182 /* set pWlanDev's parent to underlying device */
3183 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3184 }
3185
3186 return pAdapter;
3187}
3188
3189VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3190{
3191 struct net_device *pWlanDev = pAdapter->dev;
3192 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3193 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3194 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3195
3196 if( rtnl_lock_held )
3197 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003198 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003199 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3200 {
3201 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3202 return VOS_STATUS_E_FAILURE;
3203 }
3204 }
3205 if (register_netdevice(pWlanDev))
3206 {
3207 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3208 return VOS_STATUS_E_FAILURE;
3209 }
3210 }
3211 else
3212 {
3213 if(register_netdev(pWlanDev))
3214 {
3215 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3216 return VOS_STATUS_E_FAILURE;
3217 }
3218 }
3219 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3220
3221 return VOS_STATUS_SUCCESS;
3222}
3223
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003224static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003225{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003226 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003227
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003228 if (NULL == pAdapter)
3229 {
3230 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3231 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003232 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003233
3234 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3235 {
3236 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3237 return eHAL_STATUS_NOT_INITIALIZED;
3238 }
3239
3240 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3241
3242 /* need to make sure all of our scheduled work has completed.
3243 * This callback is called from MC thread context, so it is safe to
3244 * to call below flush workqueue API from here.
3245 */
3246 flush_scheduled_work();
3247
3248 /* We can be blocked while waiting for scheduled work to be
3249 * flushed, and the adapter structure can potentially be freed, in
3250 * which case the magic will have been reset. So make sure the
3251 * magic is still good, and hence the adapter structure is still
3252 * valid, before signaling completion */
3253 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3254 {
3255 complete(&pAdapter->session_close_comp_var);
3256 }
3257
Jeff Johnson295189b2012-06-20 16:38:30 -07003258 return eHAL_STATUS_SUCCESS;
3259}
3260
3261VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3262{
3263 struct net_device *pWlanDev = pAdapter->dev;
3264 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3265 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3266 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3267 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3268 int rc = 0;
3269
3270 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003271 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003272 //Open a SME session for future operation
3273 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003274 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003275 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3276 {
3277 hddLog(VOS_TRACE_LEVEL_FATAL,
3278 "sme_OpenSession() failed with status code %08d [x%08lx]",
3279 halStatus, halStatus );
3280 status = VOS_STATUS_E_FAILURE;
3281 goto error_sme_open;
3282 }
3283
3284 //Block on a completion variable. Can't wait forever though.
3285 rc = wait_for_completion_interruptible_timeout(
3286 &pAdapter->session_open_comp_var,
3287 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3288 if (!rc)
3289 {
3290 hddLog(VOS_TRACE_LEVEL_FATAL,
3291 "Session is not opened within timeout period code %08d", rc );
3292 status = VOS_STATUS_E_FAILURE;
3293 goto error_sme_open;
3294 }
3295
3296 // Register wireless extensions
3297 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3298 {
3299 hddLog(VOS_TRACE_LEVEL_FATAL,
3300 "hdd_register_wext() failed with status code %08d [x%08lx]",
3301 halStatus, halStatus );
3302 status = VOS_STATUS_E_FAILURE;
3303 goto error_register_wext;
3304 }
3305 //Safe to register the hard_start_xmit function again
3306#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3307 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3308#else
3309 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3310#endif
3311
3312 //Set the Connection State to Not Connected
3313 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3314
3315 //Set the default operation channel
3316 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3317
3318 /* Make the default Auth Type as OPEN*/
3319 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3320
3321 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3322 {
3323 hddLog(VOS_TRACE_LEVEL_FATAL,
3324 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3325 status, status );
3326 goto error_init_txrx;
3327 }
3328
3329 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3330
3331 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3332 {
3333 hddLog(VOS_TRACE_LEVEL_FATAL,
3334 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3335 status, status );
3336 goto error_wmm_init;
3337 }
3338
3339 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3340
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003341#ifdef FEATURE_WLAN_TDLS
3342 if(0 != wlan_hdd_tdls_init(pAdapter))
3343 {
3344 status = VOS_STATUS_E_FAILURE;
3345 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3346 goto error_tdls_init;
3347 }
3348 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3349#endif
3350
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 return VOS_STATUS_SUCCESS;
3352
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003353#ifdef FEATURE_WLAN_TDLS
3354error_tdls_init:
3355 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3356 hdd_wmm_adapter_close(pAdapter);
3357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003358error_wmm_init:
3359 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3360 hdd_deinit_tx_rx(pAdapter);
3361error_init_txrx:
3362 hdd_UnregisterWext(pWlanDev);
3363error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003364 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003365 {
3366 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003367 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003368 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003369 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003370 {
3371 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003372 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003373 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003374 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003375 }
3376}
3377error_sme_open:
3378 return status;
3379}
3380
Jeff Johnson295189b2012-06-20 16:38:30 -07003381void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3382{
3383 hdd_cfg80211_state_t *cfgState;
3384
3385 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3386
3387 if( NULL != cfgState->buf )
3388 {
3389 int rc;
3390 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3391 rc = wait_for_completion_interruptible_timeout(
3392 &pAdapter->tx_action_cnf_event,
3393 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3394 if(!rc)
3395 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003396 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003397 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3398 }
3399 }
3400 return;
3401}
Jeff Johnson295189b2012-06-20 16:38:30 -07003402
3403void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3404{
3405 ENTER();
3406 switch ( pAdapter->device_mode )
3407 {
3408 case WLAN_HDD_INFRA_STATION:
3409 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003410 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003411 {
3412 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3413 {
3414 hdd_deinit_tx_rx( pAdapter );
3415 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3416 }
3417
3418 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3419 {
3420 hdd_wmm_adapter_close( pAdapter );
3421 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3422 }
3423
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003425#ifdef FEATURE_WLAN_TDLS
3426 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3427 {
3428 wlan_hdd_tdls_exit(pAdapter);
3429 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3430 }
3431#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003432
3433 break;
3434 }
3435
3436 case WLAN_HDD_SOFTAP:
3437 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003438 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05303439
3440 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3441 {
3442 hdd_wmm_adapter_close( pAdapter );
3443 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3444 }
3445
Jeff Johnson295189b2012-06-20 16:38:30 -07003446 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003447
3448 hdd_unregister_hostapd(pAdapter);
3449 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003450 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003451 break;
3452 }
3453
3454 case WLAN_HDD_MONITOR:
3455 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003456 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003457 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3458 {
3459 hdd_deinit_tx_rx( pAdapter );
3460 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3461 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003462 if(NULL != pAdapterforTx)
3463 {
3464 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003466 break;
3467 }
3468
3469
3470 default:
3471 break;
3472 }
3473
3474 EXIT();
3475}
3476
3477void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3478{
3479 struct net_device *pWlanDev = pAdapter->dev;
3480
3481 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3482 if( rtnl_held )
3483 {
3484 unregister_netdevice(pWlanDev);
3485 }
3486 else
3487 {
3488 unregister_netdev(pWlanDev);
3489 }
3490 // note that the pAdapter is no longer valid at this point
3491 // since the memory has been reclaimed
3492 }
3493
3494}
3495
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003496void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3497{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303498 VOS_STATUS status;
3499 hdd_adapter_t *pAdapter = NULL;
3500 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003501
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003503
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303504 /*loop through all adapters.*/
3505 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003506 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303507 pAdapter = pAdapterNode->pAdapter;
3508 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3509 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003510
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303511 { // we skip this registration for modes other than STA and P2P client modes.
3512 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3513 pAdapterNode = pNext;
3514 continue;
3515 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003516
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303517 //Apply Dynamic DTIM For P2P
3518 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3519 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3520 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3521 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3522 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3523 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3524 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3525 (eConnectionState_Associated ==
3526 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3527 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3528 {
3529 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003530
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303531 powerRequest.uIgnoreDTIM = 1;
3532 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3533
3534 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3535 {
3536 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3537 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3538 }
3539 else
3540 {
3541 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3542 }
3543
3544 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3545 * specified during Enter/Exit BMPS when LCD off*/
3546 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3547 NULL, eANI_BOOLEAN_FALSE);
3548 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3549 NULL, eANI_BOOLEAN_FALSE);
3550
3551 /* switch to the DTIM specified in cfg.ini */
3552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3553 "Switch to DTIM %d", powerRequest.uListenInterval);
3554 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3555 break;
3556
3557 }
3558
3559 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3560 pAdapterNode = pNext;
3561 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003562}
3563
3564void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3565{
3566 /*Switch back to DTIM 1*/
3567 tSirSetPowerParamsReq powerRequest = { 0 };
3568
3569 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3570 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003571 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003572
3573 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3574 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3575 NULL, eANI_BOOLEAN_FALSE);
3576 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3577 NULL, eANI_BOOLEAN_FALSE);
3578
3579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3580 "Switch to DTIM%d",powerRequest.uListenInterval);
3581 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3582
3583}
3584
Jeff Johnson295189b2012-06-20 16:38:30 -07003585VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3586{
3587 VOS_STATUS status = VOS_STATUS_SUCCESS;
3588
3589 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3590 {
3591 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3592 }
3593
3594 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3595 {
3596 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3597 }
3598
3599 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3600 {
3601 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3602 }
3603
3604 return status;
3605}
3606
3607VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3608{
3609 hdd_adapter_t *pAdapter = NULL;
3610 eHalStatus halStatus;
3611 VOS_STATUS status = VOS_STATUS_E_INVAL;
3612 v_BOOL_t disableBmps = FALSE;
3613 v_BOOL_t disableImps = FALSE;
3614
3615 switch(session_type)
3616 {
3617 case WLAN_HDD_INFRA_STATION:
3618 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 case WLAN_HDD_P2P_CLIENT:
3620 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003621 //Exit BMPS -> Is Sta/P2P Client is already connected
3622 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3623 if((NULL != pAdapter)&&
3624 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3625 {
3626 disableBmps = TRUE;
3627 }
3628
3629 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3630 if((NULL != pAdapter)&&
3631 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3632 {
3633 disableBmps = TRUE;
3634 }
3635
3636 //Exit both Bmps and Imps incase of Go/SAP Mode
3637 if((WLAN_HDD_SOFTAP == session_type) ||
3638 (WLAN_HDD_P2P_GO == session_type))
3639 {
3640 disableBmps = TRUE;
3641 disableImps = TRUE;
3642 }
3643
3644 if(TRUE == disableImps)
3645 {
3646 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3647 {
3648 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3649 }
3650 }
3651
3652 if(TRUE == disableBmps)
3653 {
3654 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3655 {
3656 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3657
3658 if(eHAL_STATUS_SUCCESS != halStatus)
3659 {
3660 status = VOS_STATUS_E_FAILURE;
3661 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3662 VOS_ASSERT(0);
3663 return status;
3664 }
3665 }
3666
3667 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3668 {
3669 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3670
3671 if(eHAL_STATUS_SUCCESS != halStatus)
3672 {
3673 status = VOS_STATUS_E_FAILURE;
3674 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3675 VOS_ASSERT(0);
3676 return status;
3677 }
3678 }
3679 }
3680
3681 if((TRUE == disableBmps) ||
3682 (TRUE == disableImps))
3683 {
3684 /* Now, get the chip into Full Power now */
3685 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3686 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3687 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3688
3689 if(halStatus != eHAL_STATUS_SUCCESS)
3690 {
3691 if(halStatus == eHAL_STATUS_PMC_PENDING)
3692 {
3693 //Block on a completion variable. Can't wait forever though
3694 wait_for_completion_interruptible_timeout(
3695 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3696 }
3697 else
3698 {
3699 status = VOS_STATUS_E_FAILURE;
3700 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3701 VOS_ASSERT(0);
3702 return status;
3703 }
3704 }
3705
3706 status = VOS_STATUS_SUCCESS;
3707 }
3708
3709 break;
3710 }
3711 return status;
3712}
3713
3714hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003715 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003716 tANI_U8 rtnl_held )
3717{
3718 hdd_adapter_t *pAdapter = NULL;
3719 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3720 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3721 VOS_STATUS exitbmpsStatus;
3722
3723 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3724
3725 //Disable BMPS incase of Concurrency
3726 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3727
3728 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3729 {
3730 //Fail to Exit BMPS
3731 VOS_ASSERT(0);
3732 return NULL;
3733 }
3734
3735 switch(session_type)
3736 {
3737 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003738 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003739 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003740 {
3741 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3742
3743 if( NULL == pAdapter )
3744 return NULL;
3745
Jeff Johnsone7245742012-09-05 17:12:55 -07003746 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3747 NL80211_IFTYPE_P2P_CLIENT:
3748 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003749
Jeff Johnson295189b2012-06-20 16:38:30 -07003750 pAdapter->device_mode = session_type;
3751
3752 status = hdd_init_station_mode( pAdapter );
3753 if( VOS_STATUS_SUCCESS != status )
3754 goto err_free_netdev;
3755
3756 status = hdd_register_interface( pAdapter, rtnl_held );
3757 if( VOS_STATUS_SUCCESS != status )
3758 {
3759 hdd_deinit_adapter(pHddCtx, pAdapter);
3760 goto err_free_netdev;
3761 }
3762 //Stop the Interface TX queue.
3763 netif_tx_disable(pAdapter->dev);
3764 //netif_tx_disable(pWlanDev);
3765 netif_carrier_off(pAdapter->dev);
3766
3767 break;
3768 }
3769
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003771 case WLAN_HDD_SOFTAP:
3772 {
3773 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3774 if( NULL == pAdapter )
3775 return NULL;
3776
Jeff Johnson295189b2012-06-20 16:38:30 -07003777 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3778 NL80211_IFTYPE_AP:
3779 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 pAdapter->device_mode = session_type;
3781
3782 status = hdd_init_ap_mode(pAdapter);
3783 if( VOS_STATUS_SUCCESS != status )
3784 goto err_free_netdev;
3785
3786 status = hdd_register_hostapd( pAdapter, rtnl_held );
3787 if( VOS_STATUS_SUCCESS != status )
3788 {
3789 hdd_deinit_adapter(pHddCtx, pAdapter);
3790 goto err_free_netdev;
3791 }
3792
3793 netif_tx_disable(pAdapter->dev);
3794 netif_carrier_off(pAdapter->dev);
3795
3796 hdd_set_conparam( 1 );
3797 break;
3798 }
3799 case WLAN_HDD_MONITOR:
3800 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3802 if( NULL == pAdapter )
3803 return NULL;
3804
3805 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3806 pAdapter->device_mode = session_type;
3807 status = hdd_register_interface( pAdapter, rtnl_held );
3808#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3809 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3810#else
3811 pAdapter->dev->open = hdd_mon_open;
3812 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3813#endif
3814 hdd_init_tx_rx( pAdapter );
3815 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3816 //Set adapter to be used for data tx. It will use either GO or softap.
3817 pAdapter->sessionCtx.monitor.pAdapterForTx =
3818 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3820 {
3821 pAdapter->sessionCtx.monitor.pAdapterForTx =
3822 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3823 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 /* This workqueue will be used to transmit management packet over
3825 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003826 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3827 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3828 return NULL;
3829 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003830
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3832 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003833 }
3834 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003835 case WLAN_HDD_FTM:
3836 {
3837 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3838
3839 if( NULL == pAdapter )
3840 return NULL;
3841 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3842 * message while loading driver in FTM mode. */
3843 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3844 pAdapter->device_mode = session_type;
3845 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05303846
3847 hdd_init_tx_rx( pAdapter );
3848
3849 //Stop the Interface TX queue.
3850 netif_tx_disable(pAdapter->dev);
3851 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003852 }
3853 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003854 default:
3855 {
3856 VOS_ASSERT(0);
3857 return NULL;
3858 }
3859 }
3860
3861
3862 if( VOS_STATUS_SUCCESS == status )
3863 {
3864 //Add it to the hdd's session list.
3865 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3866 if( NULL == pHddAdapterNode )
3867 {
3868 status = VOS_STATUS_E_NOMEM;
3869 }
3870 else
3871 {
3872 pHddAdapterNode->pAdapter = pAdapter;
3873 status = hdd_add_adapter_back ( pHddCtx,
3874 pHddAdapterNode );
3875 }
3876 }
3877
3878 if( VOS_STATUS_SUCCESS != status )
3879 {
3880 if( NULL != pAdapter )
3881 {
3882 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3883 pAdapter = NULL;
3884 }
3885 if( NULL != pHddAdapterNode )
3886 {
3887 vos_mem_free( pHddAdapterNode );
3888 }
3889
3890 goto resume_bmps;
3891 }
3892
3893 if(VOS_STATUS_SUCCESS == status)
3894 {
3895 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3896
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003897 //Initialize the WoWL service
3898 if(!hdd_init_wowl(pAdapter))
3899 {
3900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3901 goto err_free_netdev;
3902 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 return pAdapter;
3905
3906err_free_netdev:
3907 free_netdev(pAdapter->dev);
3908 wlan_hdd_release_intf_addr( pHddCtx,
3909 pAdapter->macAddressCurrent.bytes );
3910
3911resume_bmps:
3912 //If bmps disabled enable it
3913 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3914 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303915 if (pHddCtx->hdd_wlan_suspended)
3916 {
3917 hdd_set_pwrparams(pHddCtx);
3918 }
3919 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 }
3921 return NULL;
3922}
3923
3924VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3925 tANI_U8 rtnl_held )
3926{
3927 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3928 VOS_STATUS status;
3929
3930 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3931 if( VOS_STATUS_SUCCESS != status )
3932 return status;
3933
3934 while ( pCurrent->pAdapter != pAdapter )
3935 {
3936 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3937 if( VOS_STATUS_SUCCESS != status )
3938 break;
3939
3940 pCurrent = pNext;
3941 }
3942 pAdapterNode = pCurrent;
3943 if( VOS_STATUS_SUCCESS == status )
3944 {
3945 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3946 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3947 hdd_remove_adapter( pHddCtx, pAdapterNode );
3948 vos_mem_free( pAdapterNode );
3949
Jeff Johnson295189b2012-06-20 16:38:30 -07003950
3951 /* If there is a single session of STA/P2P client, re-enable BMPS */
3952 if ((!vos_concurrent_sessions_running()) &&
3953 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3954 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3955 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303956 if (pHddCtx->hdd_wlan_suspended)
3957 {
3958 hdd_set_pwrparams(pHddCtx);
3959 }
3960 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 }
3962
3963 return VOS_STATUS_SUCCESS;
3964 }
3965
3966 return VOS_STATUS_E_FAILURE;
3967}
3968
3969VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3970{
3971 hdd_adapter_list_node_t *pHddAdapterNode;
3972 VOS_STATUS status;
3973
3974 ENTER();
3975
3976 do
3977 {
3978 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3979 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3980 {
3981 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3982 vos_mem_free( pHddAdapterNode );
3983 }
3984 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3985
3986 EXIT();
3987
3988 return VOS_STATUS_SUCCESS;
3989}
3990
3991void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3992{
3993 v_U8_t addIE[1] = {0};
3994
3995 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3996 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3997 eANI_BOOLEAN_FALSE) )
3998 {
3999 hddLog(LOGE,
4000 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
4001 }
4002
4003 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4004 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
4005 eANI_BOOLEAN_FALSE) )
4006 {
4007 hddLog(LOGE,
4008 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
4009 }
4010
4011 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4012 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4013 eANI_BOOLEAN_FALSE) )
4014 {
4015 hddLog(LOGE,
4016 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4017 }
4018}
4019
4020VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4021{
4022 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4023 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4024 union iwreq_data wrqu;
4025
4026 ENTER();
4027
4028 switch(pAdapter->device_mode)
4029 {
4030 case WLAN_HDD_INFRA_STATION:
4031 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004032 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004033 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4034 {
4035 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4036 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4037 pAdapter->sessionId,
4038 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4039 else
4040 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4041 pAdapter->sessionId,
4042 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4043 //success implies disconnect command got queued up successfully
4044 if(halStatus == eHAL_STATUS_SUCCESS)
4045 {
4046 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4047 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4048 }
4049 memset(&wrqu, '\0', sizeof(wrqu));
4050 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4051 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4052 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4053 }
4054 else
4055 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304056 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004057 }
4058
4059 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4060 {
4061 INIT_COMPLETION(pAdapter->session_close_comp_var);
4062 if (eHAL_STATUS_SUCCESS ==
4063 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4064 hdd_smeCloseSessionCallback, pAdapter))
4065 {
4066 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004067 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004068 &pAdapter->session_close_comp_var,
4069 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4070 }
4071 }
4072
4073 break;
4074
4075 case WLAN_HDD_SOFTAP:
4076 case WLAN_HDD_P2P_GO:
4077 //Any softap specific cleanup here...
4078 mutex_lock(&pHddCtx->sap_lock);
4079 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4080 {
4081 VOS_STATUS status;
4082 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4083
4084 //Stop Bss.
4085 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4086 if (VOS_IS_STATUS_SUCCESS(status))
4087 {
4088 hdd_hostapd_state_t *pHostapdState =
4089 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4090
4091 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4092
4093 if (!VOS_IS_STATUS_SUCCESS(status))
4094 {
4095 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004096 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004097 }
4098 }
4099 else
4100 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004101 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004102 }
4103 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4104
4105 if (eHAL_STATUS_FAILURE ==
4106 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4107 0, NULL, eANI_BOOLEAN_FALSE))
4108 {
4109 hddLog(LOGE,
4110 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004111 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004112 }
4113
4114 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4115 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4116 eANI_BOOLEAN_FALSE) )
4117 {
4118 hddLog(LOGE,
4119 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4120 }
4121
4122 // Reset WNI_CFG_PROBE_RSP Flags
4123 wlan_hdd_reset_prob_rspies(pAdapter);
4124 kfree(pAdapter->sessionCtx.ap.beacon);
4125 pAdapter->sessionCtx.ap.beacon = NULL;
4126 }
4127 mutex_unlock(&pHddCtx->sap_lock);
4128 break;
4129 case WLAN_HDD_MONITOR:
4130 break;
4131 default:
4132 break;
4133 }
4134
4135 EXIT();
4136 return VOS_STATUS_SUCCESS;
4137}
4138
4139VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4140{
4141 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4142 VOS_STATUS status;
4143 hdd_adapter_t *pAdapter;
4144
4145 ENTER();
4146
4147 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4148
4149 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4150 {
4151 pAdapter = pAdapterNode->pAdapter;
4152 netif_tx_disable(pAdapter->dev);
4153 netif_carrier_off(pAdapter->dev);
4154
4155 hdd_stop_adapter( pHddCtx, pAdapter );
4156
4157 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4158 pAdapterNode = pNext;
4159 }
4160
4161 EXIT();
4162
4163 return VOS_STATUS_SUCCESS;
4164}
4165
4166VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4167{
4168 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4169 VOS_STATUS status;
4170 hdd_adapter_t *pAdapter;
4171
4172 ENTER();
4173
4174 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4175
4176 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4177 {
4178 pAdapter = pAdapterNode->pAdapter;
4179 netif_tx_disable(pAdapter->dev);
4180 netif_carrier_off(pAdapter->dev);
4181
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004182 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4183
Jeff Johnson295189b2012-06-20 16:38:30 -07004184 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304185 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4186 {
4187 hdd_wmm_adapter_close( pAdapter );
4188 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004190
4191 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4192 pAdapterNode = pNext;
4193 }
4194
4195 EXIT();
4196
4197 return VOS_STATUS_SUCCESS;
4198}
4199
4200VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4201{
4202 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4203 VOS_STATUS status;
4204 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304205 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004206
4207 ENTER();
4208
4209 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4210
4211 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4212 {
4213 pAdapter = pAdapterNode->pAdapter;
4214
4215 switch(pAdapter->device_mode)
4216 {
4217 case WLAN_HDD_INFRA_STATION:
4218 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004219 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304220
4221 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4222
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 hdd_init_station_mode(pAdapter);
4224 /* Open the gates for HDD to receive Wext commands */
4225 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004226 pHddCtx->scan_info.mScanPending = FALSE;
4227 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004228
4229 //Trigger the initial scan
4230 hdd_wlan_initial_scan(pAdapter);
4231
4232 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304233 if (eConnectionState_Associated == connState ||
4234 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 {
4236 union iwreq_data wrqu;
4237 memset(&wrqu, '\0', sizeof(wrqu));
4238 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4239 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4240 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004241 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004242
Jeff Johnson295189b2012-06-20 16:38:30 -07004243 /* indicate disconnected event to nl80211 */
4244 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4245 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004246 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304247 else if (eConnectionState_Connecting == connState)
4248 {
4249 /*
4250 * Indicate connect failure to supplicant if we were in the
4251 * process of connecting
4252 */
4253 cfg80211_connect_result(pAdapter->dev, NULL,
4254 NULL, 0, NULL, 0,
4255 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4256 GFP_KERNEL);
4257 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 break;
4259
4260 case WLAN_HDD_SOFTAP:
4261 /* softAP can handle SSR */
4262 break;
4263
4264 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004265 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07004266 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004267 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004268 break;
4269
4270 case WLAN_HDD_MONITOR:
4271 /* monitor interface start */
4272 break;
4273 default:
4274 break;
4275 }
4276
4277 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4278 pAdapterNode = pNext;
4279 }
4280
4281 EXIT();
4282
4283 return VOS_STATUS_SUCCESS;
4284}
4285
4286VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4287{
4288 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4289 hdd_adapter_t *pAdapter;
4290 VOS_STATUS status;
4291 v_U32_t roamId;
4292
4293 ENTER();
4294
4295 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4296
4297 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4298 {
4299 pAdapter = pAdapterNode->pAdapter;
4300
4301 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4302 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4303 {
4304 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4305 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4306
4307 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4308 init_completion(&pAdapter->disconnect_comp_var);
4309 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4310 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4311
4312 wait_for_completion_interruptible_timeout(
4313 &pAdapter->disconnect_comp_var,
4314 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4315
4316 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4317 pHddCtx->isAmpAllowed = VOS_FALSE;
4318 sme_RoamConnect(pHddCtx->hHal,
4319 pAdapter->sessionId, &(pWextState->roamProfile),
4320 &roamId);
4321 }
4322
4323 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4324 pAdapterNode = pNext;
4325 }
4326
4327 EXIT();
4328
4329 return VOS_STATUS_SUCCESS;
4330}
4331
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004332void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4333{
4334 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4335 VOS_STATUS status;
4336 hdd_adapter_t *pAdapter;
4337 hdd_station_ctx_t *pHddStaCtx;
4338 hdd_ap_ctx_t *pHddApCtx;
4339 hdd_hostapd_state_t * pHostapdState;
4340 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4341 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4342 const char *p2pMode = "DEV";
4343 const char *ccMode = "Standalone";
4344 int n;
4345
4346 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4347 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4348 {
4349 pAdapter = pAdapterNode->pAdapter;
4350 switch (pAdapter->device_mode) {
4351 case WLAN_HDD_INFRA_STATION:
4352 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4353 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4354 staChannel = pHddStaCtx->conn_info.operationChannel;
4355 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4356 }
4357 break;
4358 case WLAN_HDD_P2P_CLIENT:
4359 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4360 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4361 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4362 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4363 p2pMode = "CLI";
4364 }
4365 break;
4366 case WLAN_HDD_P2P_GO:
4367 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4368 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4369 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4370 p2pChannel = pHddApCtx->operatingChannel;
4371 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4372 }
4373 p2pMode = "GO";
4374 break;
4375 case WLAN_HDD_SOFTAP:
4376 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4377 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4378 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4379 apChannel = pHddApCtx->operatingChannel;
4380 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4381 }
4382 break;
4383 default:
4384 break;
4385 }
4386 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4387 pAdapterNode = pNext;
4388 }
4389 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4390 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4391 }
4392 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4393 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4394 if (p2pChannel > 0) {
4395 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4396 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4397 }
4398 if (apChannel > 0) {
4399 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4400 apChannel, MAC_ADDR_ARRAY(apBssid));
4401 }
4402
4403 if (p2pChannel > 0 && apChannel > 0) {
4404 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4405 }
4406}
4407
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004408bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004409{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004410 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004411}
4412
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004413/* Once SSR is disabled then it cannot be set. */
4414void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004415{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004416 if (HDD_SSR_DISABLED == isSsrRequired)
4417 return;
4418
Jeff Johnson295189b2012-06-20 16:38:30 -07004419 isSsrRequired = value;
4420}
4421
4422VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4423 hdd_adapter_list_node_t** ppAdapterNode)
4424{
4425 VOS_STATUS status;
4426 spin_lock(&pHddCtx->hddAdapters.lock);
4427 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4428 (hdd_list_node_t**) ppAdapterNode );
4429 spin_unlock(&pHddCtx->hddAdapters.lock);
4430 return status;
4431}
4432
4433VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4434 hdd_adapter_list_node_t* pAdapterNode,
4435 hdd_adapter_list_node_t** pNextAdapterNode)
4436{
4437 VOS_STATUS status;
4438 spin_lock(&pHddCtx->hddAdapters.lock);
4439 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4440 (hdd_list_node_t*) pAdapterNode,
4441 (hdd_list_node_t**)pNextAdapterNode );
4442
4443 spin_unlock(&pHddCtx->hddAdapters.lock);
4444 return status;
4445}
4446
4447VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4448 hdd_adapter_list_node_t* pAdapterNode)
4449{
4450 VOS_STATUS status;
4451 spin_lock(&pHddCtx->hddAdapters.lock);
4452 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4453 &pAdapterNode->node );
4454 spin_unlock(&pHddCtx->hddAdapters.lock);
4455 return status;
4456}
4457
4458VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4459 hdd_adapter_list_node_t** ppAdapterNode)
4460{
4461 VOS_STATUS status;
4462 spin_lock(&pHddCtx->hddAdapters.lock);
4463 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4464 (hdd_list_node_t**) ppAdapterNode );
4465 spin_unlock(&pHddCtx->hddAdapters.lock);
4466 return status;
4467}
4468
4469VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4470 hdd_adapter_list_node_t* pAdapterNode)
4471{
4472 VOS_STATUS status;
4473 spin_lock(&pHddCtx->hddAdapters.lock);
4474 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4475 (hdd_list_node_t*) pAdapterNode );
4476 spin_unlock(&pHddCtx->hddAdapters.lock);
4477 return status;
4478}
4479
4480VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4481 hdd_adapter_list_node_t* pAdapterNode)
4482{
4483 VOS_STATUS status;
4484 spin_lock(&pHddCtx->hddAdapters.lock);
4485 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4486 (hdd_list_node_t*) pAdapterNode );
4487 spin_unlock(&pHddCtx->hddAdapters.lock);
4488 return status;
4489}
4490
4491hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4492 tSirMacAddr macAddr )
4493{
4494 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4495 hdd_adapter_t *pAdapter;
4496 VOS_STATUS status;
4497
4498 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4499
4500 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4501 {
4502 pAdapter = pAdapterNode->pAdapter;
4503
4504 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4505 macAddr, sizeof(tSirMacAddr) ) )
4506 {
4507 return pAdapter;
4508 }
4509 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4510 pAdapterNode = pNext;
4511 }
4512
4513 return NULL;
4514
4515}
4516
4517hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4518{
4519 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4520 hdd_adapter_t *pAdapter;
4521 VOS_STATUS status;
4522
4523 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4524
4525 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4526 {
4527 pAdapter = pAdapterNode->pAdapter;
4528
4529 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4530 IFNAMSIZ ) )
4531 {
4532 return pAdapter;
4533 }
4534 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4535 pAdapterNode = pNext;
4536 }
4537
4538 return NULL;
4539
4540}
4541
4542hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4543{
4544 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4545 hdd_adapter_t *pAdapter;
4546 VOS_STATUS status;
4547
4548 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4549
4550 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4551 {
4552 pAdapter = pAdapterNode->pAdapter;
4553
4554 if( pAdapter && (mode == pAdapter->device_mode) )
4555 {
4556 return pAdapter;
4557 }
4558 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4559 pAdapterNode = pNext;
4560 }
4561
4562 return NULL;
4563
4564}
4565
4566//Remove this function later
4567hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4568{
4569 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4570 hdd_adapter_t *pAdapter;
4571 VOS_STATUS status;
4572
4573 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4574
4575 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4576 {
4577 pAdapter = pAdapterNode->pAdapter;
4578
4579 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4580 {
4581 return pAdapter;
4582 }
4583
4584 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4585 pAdapterNode = pNext;
4586 }
4587
4588 return NULL;
4589
4590}
4591
Jeff Johnson295189b2012-06-20 16:38:30 -07004592/**---------------------------------------------------------------------------
4593
4594 \brief hdd_set_monitor_tx_adapter() -
4595
4596 This API initializes the adapter to be used while transmitting on monitor
4597 adapter.
4598
4599 \param - pHddCtx - Pointer to the HDD context.
4600 pAdapter - Adapter that will used for TX. This can be NULL.
4601 \return - None.
4602 --------------------------------------------------------------------------*/
4603void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4604{
4605 hdd_adapter_t *pMonAdapter;
4606
4607 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4608
4609 if( NULL != pMonAdapter )
4610 {
4611 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4612 }
4613}
Jeff Johnson295189b2012-06-20 16:38:30 -07004614/**---------------------------------------------------------------------------
4615
4616 \brief hdd_select_queue() -
4617
4618 This API returns the operating channel of the requested device mode
4619
4620 \param - pHddCtx - Pointer to the HDD context.
4621 - mode - Device mode for which operating channel is required
4622 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4623 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4624 \return - channel number. "0" id the requested device is not found OR it is not connected.
4625 --------------------------------------------------------------------------*/
4626v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4627{
4628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4629 VOS_STATUS status;
4630 hdd_adapter_t *pAdapter;
4631 v_U8_t operatingChannel = 0;
4632
4633 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4634
4635 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4636 {
4637 pAdapter = pAdapterNode->pAdapter;
4638
4639 if( mode == pAdapter->device_mode )
4640 {
4641 switch(pAdapter->device_mode)
4642 {
4643 case WLAN_HDD_INFRA_STATION:
4644 case WLAN_HDD_P2P_CLIENT:
4645 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4646 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4647 break;
4648 case WLAN_HDD_SOFTAP:
4649 case WLAN_HDD_P2P_GO:
4650 /*softap connection info */
4651 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4652 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4653 break;
4654 default:
4655 break;
4656 }
4657
4658 break; //Found the device of interest. break the loop
4659 }
4660
4661 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4662 pAdapterNode = pNext;
4663 }
4664 return operatingChannel;
4665}
4666
4667#ifdef WLAN_FEATURE_PACKET_FILTERING
4668/**---------------------------------------------------------------------------
4669
4670 \brief hdd_set_multicast_list() -
4671
4672 This used to set the multicast address list.
4673
4674 \param - dev - Pointer to the WLAN device.
4675 - skb - Pointer to OS packet (sk_buff).
4676 \return - success/fail
4677
4678 --------------------------------------------------------------------------*/
4679static void hdd_set_multicast_list(struct net_device *dev)
4680{
4681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004682 int mc_count;
4683 int i = 0;
4684 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304685
4686 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004687 {
4688 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304689 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004690 return;
4691 }
4692
4693 if (dev->flags & IFF_ALLMULTI)
4694 {
4695 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004696 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304697 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004698 }
4699 else
4700 {
4701 mc_count = netdev_mc_count(dev);
4702 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004703 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004704 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4705 {
4706 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004707 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304708 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004709 return;
4710 }
4711
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304712 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004713
4714 netdev_for_each_mc_addr(ha, dev) {
4715 if (i == mc_count)
4716 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304717 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4718 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4719 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304721 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004722 i++;
4723 }
4724 }
4725 return;
4726}
4727#endif
4728
4729/**---------------------------------------------------------------------------
4730
4731 \brief hdd_select_queue() -
4732
4733 This function is registered with the Linux OS for network
4734 core to decide which queue to use first.
4735
4736 \param - dev - Pointer to the WLAN device.
4737 - skb - Pointer to OS packet (sk_buff).
4738 \return - ac, Queue Index/access category corresponding to UP in IP header
4739
4740 --------------------------------------------------------------------------*/
4741v_U16_t hdd_select_queue(struct net_device *dev,
4742 struct sk_buff *skb)
4743{
4744 return hdd_wmm_select_queue(dev, skb);
4745}
4746
4747
4748/**---------------------------------------------------------------------------
4749
4750 \brief hdd_wlan_initial_scan() -
4751
4752 This function triggers the initial scan
4753
4754 \param - pAdapter - Pointer to the HDD adapter.
4755
4756 --------------------------------------------------------------------------*/
4757void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4758{
4759 tCsrScanRequest scanReq;
4760 tCsrChannelInfo channelInfo;
4761 eHalStatus halStatus;
4762 unsigned long scanId;
4763 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4764
4765 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4766 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4767 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4768
4769 if(sme_Is11dSupported(pHddCtx->hHal))
4770 {
4771 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4772 if ( HAL_STATUS_SUCCESS( halStatus ) )
4773 {
4774 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4775 if( !scanReq.ChannelInfo.ChannelList )
4776 {
4777 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4778 vos_mem_free(channelInfo.ChannelList);
4779 return;
4780 }
4781 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4782 channelInfo.numOfChannels);
4783 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4784 vos_mem_free(channelInfo.ChannelList);
4785 }
4786
4787 scanReq.scanType = eSIR_PASSIVE_SCAN;
4788 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4789 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4790 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4791 }
4792 else
4793 {
4794 scanReq.scanType = eSIR_ACTIVE_SCAN;
4795 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4796 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4797 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4798 }
4799
4800 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4801 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4802 {
4803 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4804 __func__, halStatus );
4805 }
4806
4807 if(sme_Is11dSupported(pHddCtx->hHal))
4808 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4809}
4810
4811struct fullPowerContext
4812{
4813 struct completion completion;
4814 unsigned int magic;
4815};
4816#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4817
4818/**---------------------------------------------------------------------------
4819
4820 \brief hdd_full_power_callback() - HDD full power callback function
4821
4822 This is the function invoked by SME to inform the result of a full power
4823 request issued by HDD
4824
4825 \param - callbackcontext - Pointer to cookie
4826 \param - status - result of request
4827
4828 \return - None
4829
4830 --------------------------------------------------------------------------*/
4831static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4832{
4833 struct fullPowerContext *pContext = callbackContext;
4834
4835 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304836 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004837
4838 if (NULL == callbackContext)
4839 {
4840 hddLog(VOS_TRACE_LEVEL_ERROR,
4841 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004842 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 return;
4844 }
4845
4846 /* there is a race condition that exists between this callback function
4847 and the caller since the caller could time out either before or
4848 while this code is executing. we'll assume the timeout hasn't
4849 occurred, but we'll verify that right before we save our work */
4850
4851 if (POWER_CONTEXT_MAGIC != pContext->magic)
4852 {
4853 /* the caller presumably timed out so there is nothing we can do */
4854 hddLog(VOS_TRACE_LEVEL_WARN,
4855 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004856 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 return;
4858 }
4859
4860 /* the race is on. caller could have timed out immediately after
4861 we verified the magic, but if so, caller will wait a short time
4862 for us to notify the caller, so the context will stay valid */
4863 complete(&pContext->completion);
4864}
4865
4866/**---------------------------------------------------------------------------
4867
4868 \brief hdd_wlan_exit() - HDD WLAN exit function
4869
4870 This is the driver exit point (invoked during rmmod)
4871
4872 \param - pHddCtx - Pointer to the HDD Context
4873
4874 \return - None
4875
4876 --------------------------------------------------------------------------*/
4877void hdd_wlan_exit(hdd_context_t *pHddCtx)
4878{
4879 eHalStatus halStatus;
4880 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4881 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304882 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 struct fullPowerContext powerContext;
4885 long lrc;
4886
4887 ENTER();
4888
Jeff Johnson88ba7742013-02-27 14:36:02 -08004889 if (VOS_FTM_MODE != hdd_get_conparam())
4890 {
4891 // Unloading, restart logic is no more required.
4892 wlan_hdd_restart_deinit(pHddCtx);
4893 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004894
Jeff Johnson295189b2012-06-20 16:38:30 -07004895 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 {
4899 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4900 WLAN_HDD_INFRA_STATION);
4901 if (pAdapter == NULL)
4902 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4903
4904 if (pAdapter != NULL)
4905 {
4906 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4907 hdd_UnregisterWext(pAdapter->dev);
4908 }
4909 }
4910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
Jeff Johnson295189b2012-06-20 16:38:30 -07004912 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004913 {
4914 wlan_hdd_ftm_close(pHddCtx);
4915 goto free_hdd_ctx;
4916 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004917 //Stop the Interface TX queue.
4918 //netif_tx_disable(pWlanDev);
4919 //netif_carrier_off(pWlanDev);
4920
Jeff Johnson295189b2012-06-20 16:38:30 -07004921 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4922 {
4923 pAdapter = hdd_get_adapter(pHddCtx,
4924 WLAN_HDD_SOFTAP);
4925 }
4926 else
4927 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004928 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004929 {
4930 pAdapter = hdd_get_adapter(pHddCtx,
4931 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07004932 if (pAdapter == NULL)
4933 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07004934 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004935 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004936 /* DeRegister with platform driver as client for Suspend/Resume */
4937 vosStatus = hddDeregisterPmOps(pHddCtx);
4938 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4939 {
4940 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4941 VOS_ASSERT(0);
4942 }
4943
4944 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4945 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4946 {
4947 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004949
4950 // Cancel any outstanding scan requests. We are about to close all
4951 // of our adapters, but an adapter structure is what SME passes back
4952 // to our callback function. Hence if there are any outstanding scan
4953 // requests then there is a race condition between when the adapter
4954 // is closed and when the callback is invoked. We try to resolve that
4955 // race condition here by canceling any outstanding scans before we
4956 // close the adapters.
4957 // Note that the scans may be cancelled in an asynchronous manner, so
4958 // ideally there needs to be some kind of synchronization. Rather than
4959 // introduce a new synchronization here, we will utilize the fact that
4960 // we are about to Request Full Power, and since that is synchronized,
4961 // the expectation is that by the time Request Full Power has completed,
4962 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07004963 if (NULL != pAdapter)
4964 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
4965 else
4966 hddLog(VOS_TRACE_LEVEL_ERROR,
4967 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004968
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004969 //Stop the traffic monitor timer
4970 if ( VOS_TIMER_STATE_RUNNING ==
4971 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4972 {
4973 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4974 }
4975
4976 // Destroy the traffic monitor timer
4977 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4978 &pHddCtx->tx_rx_trafficTmr)))
4979 {
4980 hddLog(VOS_TRACE_LEVEL_ERROR,
4981 "%s: Cannot deallocate Traffic monitor timer", __func__);
4982 }
4983
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 //Disable IMPS/BMPS as we do not want the device to enter any power
4985 //save mode during shutdown
4986 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4987 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4988 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4989
4990 //Ensure that device is in full power as we will touch H/W during vos_Stop
4991 init_completion(&powerContext.completion);
4992 powerContext.magic = POWER_CONTEXT_MAGIC;
4993
4994 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4995 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4996
4997 if (eHAL_STATUS_SUCCESS != halStatus)
4998 {
4999 if (eHAL_STATUS_PMC_PENDING == halStatus)
5000 {
5001 /* request was sent -- wait for the response */
5002 lrc = wait_for_completion_interruptible_timeout(
5003 &powerContext.completion,
5004 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
5005 /* either we have a response or we timed out
5006 either way, first invalidate our magic */
5007 powerContext.magic = 0;
5008 if (lrc <= 0)
5009 {
5010 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005011 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07005012 /* there is a race condition such that the callback
5013 function could be executing at the same time we are. of
5014 primary concern is if the callback function had already
5015 verified the "magic" but hasn't yet set the completion
5016 variable. Since the completion variable is on our
5017 stack, we'll delay just a bit to make sure the data is
5018 still valid if that is the case */
5019 msleep(50);
5020 }
5021 }
5022 else
5023 {
5024 hddLog(VOS_TRACE_LEVEL_ERROR,
5025 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005026 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 VOS_ASSERT(0);
5028 /* continue -- need to clean up as much as possible */
5029 }
5030 }
5031
Yue Ma0d4891e2013-08-06 17:01:45 -07005032 hdd_debugfs_exit(pHddCtx);
5033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 // Unregister the Net Device Notifier
5035 unregister_netdevice_notifier(&hdd_netdev_notifier);
5036
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 hdd_stop_all_adapters( pHddCtx );
5038
Jeff Johnson295189b2012-06-20 16:38:30 -07005039#ifdef WLAN_BTAMP_FEATURE
5040 vosStatus = WLANBAP_Stop(pVosContext);
5041 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5042 {
5043 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5044 "%s: Failed to stop BAP",__func__);
5045 }
5046#endif //WLAN_BTAMP_FEATURE
5047
5048 //Stop all the modules
5049 vosStatus = vos_stop( pVosContext );
5050 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5051 {
5052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5053 "%s: Failed to stop VOSS",__func__);
5054 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5055 }
5056
Jeff Johnson295189b2012-06-20 16:38:30 -07005057 //Assert Deep sleep signal now to put Libra HW in lowest power state
5058 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5059 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5060
5061 //Vote off any PMIC voltage supplies
5062 vos_chipPowerDown(NULL, NULL, NULL);
5063
5064 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5065
Leo Chang59cdc7e2013-07-10 10:08:21 -07005066
Jeff Johnson295189b2012-06-20 16:38:30 -07005067 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005068 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005069
5070 //Close the scheduler before calling vos_close to make sure no thread is
5071 // scheduled after the each module close is called i.e after all the data
5072 // structures are freed.
5073 vosStatus = vos_sched_close( pVosContext );
5074 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5075 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5076 "%s: Failed to close VOSS Scheduler",__func__);
5077 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5078 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005079#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005080#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5081 /* Destroy the wake lock */
5082 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5083#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005084 /* Destroy the wake lock */
5085 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005086#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005087
5088 //Close VOSS
5089 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5090 vos_close(pVosContext);
5091
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 //Close Watchdog
5093 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5094 vos_watchdog_close(pVosContext);
5095
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305096 //Clean up HDD Nlink Service
5097 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005098#ifdef WLAN_KD_READY_NOTIFIER
5099 nl_srv_exit(pHddCtx->ptt_pid);
5100#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305101 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005102#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305103
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 /* Cancel the vote for XO Core ON.
5105 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5106 * exited at this point
5107 */
5108 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5109 " when WLAN is turned OFF\n");
5110 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5111 {
5112 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5113 " Not returning failure."
5114 " Power consumed will be high\n");
5115 }
5116
5117 hdd_close_all_adapters( pHddCtx );
5118
5119
5120 //Free up dynamically allocated members inside HDD Adapter
5121 kfree(pHddCtx->cfg_ini);
5122 pHddCtx->cfg_ini= NULL;
5123
5124 /* free the power on lock from platform driver */
5125 if (free_riva_power_on_lock("wlan"))
5126 {
5127 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5128 __func__);
5129 }
5130
Jeff Johnson88ba7742013-02-27 14:36:02 -08005131free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07005132 /* FTM mode, WIPHY did not registered
5133 If un-register here, system crash will happen */
5134 if (VOS_FTM_MODE != hdd_get_conparam())
5135 {
5136 wiphy_unregister(wiphy) ;
5137 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 if (hdd_is_ssr_required())
5140 {
5141 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005142 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 msleep(5000);
5144 }
5145 hdd_set_ssr_required (VOS_FALSE);
5146}
5147
5148
5149/**---------------------------------------------------------------------------
5150
5151 \brief hdd_update_config_from_nv() - Function to update the contents of
5152 the running configuration with parameters taken from NV storage
5153
5154 \param - pHddCtx - Pointer to the HDD global context
5155
5156 \return - VOS_STATUS_SUCCESS if successful
5157
5158 --------------------------------------------------------------------------*/
5159static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5160{
Jeff Johnson295189b2012-06-20 16:38:30 -07005161 v_BOOL_t itemIsValid = VOS_FALSE;
5162 VOS_STATUS status;
5163 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5164 v_U8_t macLoop;
5165
5166 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5167 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5168 if(status != VOS_STATUS_SUCCESS)
5169 {
5170 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5171 return VOS_STATUS_E_FAILURE;
5172 }
5173
5174 if (itemIsValid == VOS_TRUE)
5175 {
5176 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5177 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5178 VOS_MAX_CONCURRENCY_PERSONA);
5179 if(status != VOS_STATUS_SUCCESS)
5180 {
5181 /* Get MAC from NV fail, not update CFG info
5182 * INI MAC value will be used for MAC setting */
5183 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5184 return VOS_STATUS_E_FAILURE;
5185 }
5186
5187 /* If first MAC is not valid, treat all others are not valid
5188 * Then all MACs will be got from ini file */
5189 if(vos_is_macaddr_zero(&macFromNV[0]))
5190 {
5191 /* MAC address in NV file is not configured yet */
5192 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5193 return VOS_STATUS_E_INVAL;
5194 }
5195
5196 /* Get MAC address from NV, update CFG info */
5197 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5198 {
5199 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5200 {
5201 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5202 /* This MAC is not valid, skip it
5203 * This MAC will be got from ini file */
5204 }
5205 else
5206 {
5207 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5208 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5209 VOS_MAC_ADDR_SIZE);
5210 }
5211 }
5212 }
5213 else
5214 {
5215 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5216 return VOS_STATUS_E_FAILURE;
5217 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005218
Jeff Johnson295189b2012-06-20 16:38:30 -07005219
5220 return VOS_STATUS_SUCCESS;
5221}
5222
5223/**---------------------------------------------------------------------------
5224
5225 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5226
5227 \param - pAdapter - Pointer to the HDD
5228
5229 \return - None
5230
5231 --------------------------------------------------------------------------*/
5232VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5233{
5234 eHalStatus halStatus;
5235 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305236 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005237
Jeff Johnson295189b2012-06-20 16:38:30 -07005238
5239 // Send ready indication to the HDD. This will kick off the MAC
5240 // into a 'running' state and should kick off an initial scan.
5241 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5242 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5243 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 "code %08d [x%08x]",__func__, halStatus, halStatus );
5246 return VOS_STATUS_E_FAILURE;
5247 }
5248
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305249 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5251 // And RIVA will crash
5252 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5253 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305254 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5255 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5256
5257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 return VOS_STATUS_SUCCESS;
5259}
5260
Jeff Johnson295189b2012-06-20 16:38:30 -07005261/* wake lock APIs for HDD */
5262void hdd_prevent_suspend(void)
5263{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005264#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005265 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005266#else
5267 wcnss_prevent_suspend();
5268#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005269}
5270
5271void hdd_allow_suspend(void)
5272{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005273#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005275#else
5276 wcnss_allow_suspend();
5277#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005278}
5279
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005280void hdd_allow_suspend_timeout(v_U32_t timeout)
5281{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005282#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005283 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005284#else
5285 /* Do nothing as there is no API in wcnss for timeout*/
5286#endif
5287}
5288
Jeff Johnson295189b2012-06-20 16:38:30 -07005289/**---------------------------------------------------------------------------
5290
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005291 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5292 information between Host and Riva
5293
5294 This function gets reported version of FW
5295 It also finds the version of Riva headers used to compile the host
5296 It compares the above two and prints a warning if they are different
5297 It gets the SW and HW version string
5298 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5299 indicating the features they support through a bitmap
5300
5301 \param - pHddCtx - Pointer to HDD context
5302
5303 \return - void
5304
5305 --------------------------------------------------------------------------*/
5306
5307void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5308{
5309
5310 tSirVersionType versionCompiled;
5311 tSirVersionType versionReported;
5312 tSirVersionString versionString;
5313 tANI_U8 fwFeatCapsMsgSupported = 0;
5314 VOS_STATUS vstatus;
5315
5316 /* retrieve and display WCNSS version information */
5317 do {
5318
5319 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5320 &versionCompiled);
5321 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5322 {
5323 hddLog(VOS_TRACE_LEVEL_FATAL,
5324 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005325 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005326 break;
5327 }
5328
5329 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5330 &versionReported);
5331 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5332 {
5333 hddLog(VOS_TRACE_LEVEL_FATAL,
5334 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005335 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005336 break;
5337 }
5338
5339 if ((versionCompiled.major != versionReported.major) ||
5340 (versionCompiled.minor != versionReported.minor) ||
5341 (versionCompiled.version != versionReported.version) ||
5342 (versionCompiled.revision != versionReported.revision))
5343 {
5344 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5345 "Host expected %u.%u.%u.%u\n",
5346 WLAN_MODULE_NAME,
5347 (int)versionReported.major,
5348 (int)versionReported.minor,
5349 (int)versionReported.version,
5350 (int)versionReported.revision,
5351 (int)versionCompiled.major,
5352 (int)versionCompiled.minor,
5353 (int)versionCompiled.version,
5354 (int)versionCompiled.revision);
5355 }
5356 else
5357 {
5358 pr_info("%s: WCNSS WLAN version %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 }
5365
5366 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5367 versionString,
5368 sizeof(versionString));
5369 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5370 {
5371 hddLog(VOS_TRACE_LEVEL_FATAL,
5372 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005373 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005374 break;
5375 }
5376
5377 pr_info("%s: WCNSS software version %s\n",
5378 WLAN_MODULE_NAME, versionString);
5379
5380 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5381 versionString,
5382 sizeof(versionString));
5383 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5384 {
5385 hddLog(VOS_TRACE_LEVEL_FATAL,
5386 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005387 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005388 break;
5389 }
5390
5391 pr_info("%s: WCNSS hardware version %s\n",
5392 WLAN_MODULE_NAME, versionString);
5393
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005394 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5395 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005396 send the message only if it the riva is 1.1
5397 minor numbers for different riva branches:
5398 0 -> (1.0)Mainline Build
5399 1 -> (1.1)Mainline Build
5400 2->(1.04) Stability Build
5401 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005402 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005403 ((versionReported.minor>=1) && (versionReported.version>=1)))
5404 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5405 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005406
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005407 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005408 {
5409#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5410 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5411 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5412#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005413 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5414 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5415 {
5416 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5417 }
5418
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005419 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005420 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005421
5422 } while (0);
5423
5424}
5425
5426/**---------------------------------------------------------------------------
5427
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305428 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5429
5430 \param - pHddCtx - Pointer to the hdd context
5431
5432 \return - true if hardware supports 5GHz
5433
5434 --------------------------------------------------------------------------*/
5435static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5436{
5437 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5438 * then hardware support 5Ghz.
5439 */
5440 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5441 {
5442 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5443 return true;
5444 }
5445 else
5446 {
5447 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5448 __func__);
5449 return false;
5450 }
5451}
5452
5453
5454/**---------------------------------------------------------------------------
5455
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 \brief hdd_wlan_startup() - HDD init function
5457
5458 This is the driver startup code executed once a WLAN device has been detected
5459
5460 \param - dev - Pointer to the underlying device
5461
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005462 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005463
5464 --------------------------------------------------------------------------*/
5465
5466int hdd_wlan_startup(struct device *dev )
5467{
5468 VOS_STATUS status;
5469 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005470 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 hdd_context_t *pHddCtx = NULL;
5472 v_CONTEXT_t pVosContext= NULL;
5473#ifdef WLAN_BTAMP_FEATURE
5474 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5475 WLANBAP_ConfigType btAmpConfig;
5476 hdd_config_t *pConfig;
5477#endif
5478 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005479 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005480
5481 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005482 /*
5483 * cfg80211: wiphy allocation
5484 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305485 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005486
5487 if(wiphy == NULL)
5488 {
5489 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005490 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005491 }
5492
5493 pHddCtx = wiphy_priv(wiphy);
5494
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 //Initialize the adapter context to zeros.
5496 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5497
Jeff Johnson295189b2012-06-20 16:38:30 -07005498 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 hdd_prevent_suspend();
5500 pHddCtx->isLoadUnloadInProgress = TRUE;
5501
5502 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5503
5504 /*Get vos context here bcoz vos_open requires it*/
5505 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5506
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005507 if(pVosContext == NULL)
5508 {
5509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5510 goto err_free_hdd_context;
5511 }
5512
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 //Save the Global VOSS context in adapter context for future.
5514 pHddCtx->pvosContext = pVosContext;
5515
5516 //Save the adapter context in global context for future.
5517 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5518
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 pHddCtx->parent_dev = dev;
5520
5521 init_completion(&pHddCtx->full_pwr_comp_var);
5522 init_completion(&pHddCtx->standby_comp_var);
5523 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005524 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005525 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhalfddc28c2013-09-05 13:03:40 -07005526 init_completion(&pHddCtx->linux_reg_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005527
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305528 spin_lock_init(&pHddCtx->schedScan_lock);
5529
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5531
5532 // Load all config first as TL config is needed during vos_open
5533 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5534 if(pHddCtx->cfg_ini == NULL)
5535 {
5536 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5537 goto err_free_hdd_context;
5538 }
5539
5540 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5541
5542 // Read and parse the qcom_cfg.ini file
5543 status = hdd_parse_config_ini( pHddCtx );
5544 if ( VOS_STATUS_SUCCESS != status )
5545 {
5546 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5547 __func__, WLAN_INI_FILE);
5548 goto err_config;
5549 }
5550
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305551 /* INI has been read, initialise the configuredMcastBcastFilter with
5552 * INI value as this will serve as the default value
5553 */
5554 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5555 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5556 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305557
5558 if (false == hdd_is_5g_supported(pHddCtx))
5559 {
5560 //5Ghz is not supported.
5561 if (1 != pHddCtx->cfg_ini->nBandCapability)
5562 {
5563 hddLog(VOS_TRACE_LEVEL_INFO,
5564 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5565 pHddCtx->cfg_ini->nBandCapability = 1;
5566 }
5567 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305568
5569 /* If SNR Monitoring is enabled, FW has to parse all beacons
5570 * for calcaluting and storing the average SNR, so set Nth beacon
5571 * filter to 1 to enable FW to parse all the beaocons
5572 */
5573 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5574 {
5575 /* The log level is deliberately set to WARN as overriding
5576 * nthBeaconFilter to 1 will increase power cosumption and this
5577 * might just prove helpful to detect the power issue.
5578 */
5579 hddLog(VOS_TRACE_LEVEL_WARN,
5580 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5581 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5582 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005583 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305584 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305586 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 {
5588 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305589 "%s: wlan_hdd_cfg80211_init return failure", __func__);
5590 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005592
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005593 // Update VOS trace levels based upon the cfg.ini
5594 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5595 pHddCtx->cfg_ini->vosTraceEnableBAP);
5596 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5597 pHddCtx->cfg_ini->vosTraceEnableTL);
5598 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5599 pHddCtx->cfg_ini->vosTraceEnableWDI);
5600 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5601 pHddCtx->cfg_ini->vosTraceEnableHDD);
5602 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5603 pHddCtx->cfg_ini->vosTraceEnableSME);
5604 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5605 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05305606 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
5607 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005608 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5609 pHddCtx->cfg_ini->vosTraceEnableWDA);
5610 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5611 pHddCtx->cfg_ini->vosTraceEnableSYS);
5612 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5613 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005614 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5615 pHddCtx->cfg_ini->vosTraceEnableSAP);
5616 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5617 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005618
Jeff Johnson295189b2012-06-20 16:38:30 -07005619 // Update WDI trace levels based upon the cfg.ini
5620 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5621 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5622 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5623 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5624 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5625 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5626 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5627 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005628
Jeff Johnson88ba7742013-02-27 14:36:02 -08005629 if (VOS_FTM_MODE == hdd_get_conparam())
5630 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005631 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5632 {
5633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5634 goto err_free_hdd_context;
5635 }
5636 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5637 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005638 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005639
Jeff Johnson88ba7742013-02-27 14:36:02 -08005640 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005641 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5642 {
5643 status = vos_watchdog_open(pVosContext,
5644 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5645
5646 if(!VOS_IS_STATUS_SUCCESS( status ))
5647 {
5648 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305649 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005650 }
5651 }
5652
5653 pHddCtx->isLogpInProgress = FALSE;
5654 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5655
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5657 if(!VOS_IS_STATUS_SUCCESS(status))
5658 {
5659 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005660 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 }
5662
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 status = vos_open( &pVosContext, 0);
5664 if ( !VOS_IS_STATUS_SUCCESS( status ))
5665 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005666 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5667 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 }
5669
Jeff Johnson295189b2012-06-20 16:38:30 -07005670 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5671
5672 if ( NULL == pHddCtx->hHal )
5673 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005674 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005675 goto err_vosclose;
5676 }
5677
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005678 status = vos_preStart( pHddCtx->pvosContext );
5679 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5680 {
5681 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5682 goto err_vosclose;
5683 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005684
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005685 /* Note that the vos_preStart() sequence triggers the cfg download.
5686 The cfg download must occur before we update the SME config
5687 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 status = hdd_set_sme_config( pHddCtx );
5689
5690 if ( VOS_STATUS_SUCCESS != status )
5691 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005692 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5693 goto err_vosclose;
5694 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005695
5696 //Initialize the WMM module
5697 status = hdd_wmm_init(pHddCtx);
5698 if (!VOS_IS_STATUS_SUCCESS(status))
5699 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005700 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005701 goto err_vosclose;
5702 }
5703
Jeff Johnson295189b2012-06-20 16:38:30 -07005704 /* In the integrated architecture we update the configuration from
5705 the INI file and from NV before vOSS has been started so that
5706 the final contents are available to send down to the cCPU */
5707
5708 // Apply the cfg.ini to cfg.dat
5709 if (FALSE == hdd_update_config_dat(pHddCtx))
5710 {
5711 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5712 goto err_vosclose;
5713 }
5714
5715 // Apply the NV to cfg.dat
5716 /* Prima Update MAC address only at here */
5717 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5718 {
5719#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5720 /* There was not a valid set of MAC Addresses in NV. See if the
5721 default addresses were modified by the cfg.ini settings. If so,
5722 we'll use them, but if not, we'll autogenerate a set of MAC
5723 addresses based upon the device serial number */
5724
5725 static const v_MACADDR_t default_address =
5726 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5727 unsigned int serialno;
5728 int i;
5729
5730 serialno = wcnss_get_serial_number();
5731 if ((0 != serialno) &&
5732 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5733 sizeof(default_address))))
5734 {
5735 /* cfg.ini has the default address, invoke autogen logic */
5736
5737 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5738 bytes of the serial number that can be used to generate
5739 the other 3 bytes of the MAC address. Mask off all but
5740 the lower 3 bytes (this will also make sure we don't
5741 overflow in the next step) */
5742 serialno &= 0x00FFFFFF;
5743
5744 /* we need a unique address for each session */
5745 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5746
5747 /* autogen all addresses */
5748 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5749 {
5750 /* start with the entire default address */
5751 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5752 /* then replace the lower 3 bytes */
5753 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5754 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5755 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5756
5757 serialno++;
5758 }
5759
5760 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5761 MAC_ADDRESS_STR,
5762 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5763 }
5764 else
5765#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5766 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005767 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005768 "%s: Invalid MAC address in NV, using MAC from ini file "
5769 MAC_ADDRESS_STR, __func__,
5770 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5771 }
5772 }
5773 {
5774 eHalStatus halStatus;
5775 // Set the MAC Address
5776 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5777 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5778 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5779 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5780
5781 if (!HAL_STATUS_SUCCESS( halStatus ))
5782 {
5783 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5784 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005785 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 }
5787 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005788
5789 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5790 Note: Firmware image will be read and downloaded inside vos_start API */
5791 status = vos_start( pHddCtx->pvosContext );
5792 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5793 {
5794 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5795 goto err_vosclose;
5796 }
5797
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005798 /* Exchange capability info between Host and FW and also get versioning info from FW */
5799 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005800
5801 status = hdd_post_voss_start_config( pHddCtx );
5802 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5803 {
5804 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5805 __func__);
5806 goto err_vosstop;
5807 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305808 wlan_hdd_cfg80211_update_reg_info( wiphy );
5809
5810 /* registration of wiphy dev with cfg80211 */
5811 if (0 > wlan_hdd_cfg80211_register(wiphy))
5812 {
5813 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5814 goto err_vosstop;
5815 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005816
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5818 {
5819 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5820 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5821 }
5822 else
5823 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5825 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5826 if (pAdapter != NULL)
5827 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305828 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305830 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5831 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5832 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005833
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305834 /* Generate the P2P Device Address. This consists of the device's
5835 * primary MAC address with the locally administered bit set.
5836 */
5837 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005838 }
5839 else
5840 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305841 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5842 if (p2p_dev_addr != NULL)
5843 {
5844 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5845 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5846 }
5847 else
5848 {
5849 hddLog(VOS_TRACE_LEVEL_FATAL,
5850 "%s: Failed to allocate mac_address for p2p_device",
5851 __func__);
5852 goto err_close_adapter;
5853 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005855
5856 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5857 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5858 if ( NULL == pP2pAdapter )
5859 {
5860 hddLog(VOS_TRACE_LEVEL_FATAL,
5861 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005862 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005863 goto err_close_adapter;
5864 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005867
5868 if( pAdapter == NULL )
5869 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005870 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5871 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005873
Jeff Johnson295189b2012-06-20 16:38:30 -07005874#ifdef WLAN_BTAMP_FEATURE
5875 vStatus = WLANBAP_Open(pVosContext);
5876 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5877 {
5878 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5879 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005880 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 }
5882
5883 vStatus = BSL_Init(pVosContext);
5884 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5885 {
5886 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5887 "%s: Failed to Init BSL",__func__);
5888 goto err_bap_close;
5889 }
5890 vStatus = WLANBAP_Start(pVosContext);
5891 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5892 {
5893 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5894 "%s: Failed to start TL",__func__);
5895 goto err_bap_close;
5896 }
5897
5898 pConfig = pHddCtx->cfg_ini;
5899 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5900 status = WLANBAP_SetConfig(&btAmpConfig);
5901
5902#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005903
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005904#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5905 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5906 {
5907 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5908 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5909 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5910 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5911 }
5912#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005913#ifdef FEATURE_WLAN_SCAN_PNO
5914 /*SME must send channel update configuration to RIVA*/
5915 sme_UpdateChannelConfig(pHddCtx->hHal);
5916#endif
5917
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 /* Register with platform driver as client for Suspend/Resume */
5919 status = hddRegisterPmOps(pHddCtx);
5920 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5921 {
5922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5923#ifdef WLAN_BTAMP_FEATURE
5924 goto err_bap_stop;
5925#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005926 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005927#endif //WLAN_BTAMP_FEATURE
5928 }
5929
Yue Ma0d4891e2013-08-06 17:01:45 -07005930 /* Open debugfs interface */
5931 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5932 {
5933 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5934 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07005935 }
5936
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 /* Register TM level change handler function to the platform */
5938 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5939 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5940 {
5941 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5942 goto err_unregister_pmops;
5943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005944
5945 /* register for riva power on lock to platform driver */
5946 if (req_riva_power_on_lock("wlan"))
5947 {
5948 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5949 __func__);
5950 goto err_unregister_pmops;
5951 }
5952
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 // register net device notifier for device change notification
5954 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5955
5956 if(ret < 0)
5957 {
5958 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5959 goto err_free_power_on_lock;
5960 }
5961
5962 //Initialize the nlink service
5963 if(nl_srv_init() != 0)
5964 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305965 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 goto err_reg_netdev;
5967 }
5968
5969 //Initialize the BTC service
5970 if(btc_activate_service(pHddCtx) != 0)
5971 {
5972 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5973 goto err_nl_srv;
5974 }
5975
5976#ifdef PTT_SOCK_SVC_ENABLE
5977 //Initialize the PTT service
5978 if(ptt_sock_activate_svc(pHddCtx) != 0)
5979 {
5980 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5981 goto err_nl_srv;
5982 }
5983#endif
5984
Jeff Johnson295189b2012-06-20 16:38:30 -07005985 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005986 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005988 /* Action frame registered in one adapter which will
5989 * applicable to all interfaces
5990 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005991 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005993
5994 mutex_init(&pHddCtx->sap_lock);
5995
5996 pHddCtx->isLoadUnloadInProgress = FALSE;
5997
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005998#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005999#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6000 /* Initialize the wake lcok */
6001 wake_lock_init(&pHddCtx->rx_wake_lock,
6002 WAKE_LOCK_SUSPEND,
6003 "qcom_rx_wakelock");
6004#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006005 /* Initialize the wake lcok */
6006 wake_lock_init(&pHddCtx->sap_wake_lock,
6007 WAKE_LOCK_SUSPEND,
6008 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006009#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07006010
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006011 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
6012 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006013
6014 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6015 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306016
Jeff Johnsone7245742012-09-05 17:12:55 -07006017 // Initialize the restart logic
6018 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05306019
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006020 //Register the traffic monitor timer now
6021 if ( pHddCtx->cfg_ini->dynSplitscan)
6022 {
6023 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
6024 VOS_TIMER_TYPE_SW,
6025 hdd_tx_rx_pkt_cnt_stat_timer_handler,
6026 (void *)pHddCtx);
6027 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006028 goto success;
6029
6030err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07006031#ifdef WLAN_KD_READY_NOTIFIER
6032 nl_srv_exit(pHddCtx->ptt_pid);
6033#else
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006035#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07006036err_reg_netdev:
6037 unregister_netdevice_notifier(&hdd_netdev_notifier);
6038
6039err_free_power_on_lock:
6040 free_riva_power_on_lock("wlan");
6041
6042err_unregister_pmops:
6043 hddDevTmUnregisterNotifyCallback(pHddCtx);
6044 hddDeregisterPmOps(pHddCtx);
6045
Yue Ma0d4891e2013-08-06 17:01:45 -07006046 hdd_debugfs_exit(pHddCtx);
6047
Jeff Johnson295189b2012-06-20 16:38:30 -07006048#ifdef WLAN_BTAMP_FEATURE
6049err_bap_stop:
6050 WLANBAP_Stop(pVosContext);
6051#endif
6052
6053#ifdef WLAN_BTAMP_FEATURE
6054err_bap_close:
6055 WLANBAP_Close(pVosContext);
6056#endif
6057
Jeff Johnson295189b2012-06-20 16:38:30 -07006058err_close_adapter:
6059 hdd_close_all_adapters( pHddCtx );
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306060 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006061
6062err_vosstop:
6063 vos_stop(pVosContext);
6064
6065err_vosclose:
6066 status = vos_sched_close( pVosContext );
6067 if (!VOS_IS_STATUS_SUCCESS(status)) {
6068 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6069 "%s: Failed to close VOSS Scheduler", __func__);
6070 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6071 }
6072 vos_close(pVosContext );
6073
Jeff Johnson295189b2012-06-20 16:38:30 -07006074err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006075 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006076
6077err_wdclose:
6078 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6079 vos_watchdog_close(pVosContext);
6080
Jeff Johnson295189b2012-06-20 16:38:30 -07006081err_config:
6082 kfree(pHddCtx->cfg_ini);
6083 pHddCtx->cfg_ini= NULL;
6084
6085err_free_hdd_context:
6086 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 wiphy_free(wiphy) ;
6088 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 VOS_BUG(1);
6090
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006091 if (hdd_is_ssr_required())
6092 {
6093 /* WDI timeout had happened during load, so SSR is needed here */
6094 subsystem_restart("wcnss");
6095 msleep(5000);
6096 }
6097 hdd_set_ssr_required (VOS_FALSE);
6098
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006099 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006100
6101success:
6102 EXIT();
6103 return 0;
6104}
6105
6106/**---------------------------------------------------------------------------
6107
Jeff Johnson32d95a32012-09-10 13:15:23 -07006108 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006109
Jeff Johnson32d95a32012-09-10 13:15:23 -07006110 This is the driver entry point - called in different timeline depending
6111 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006112
6113 \param - None
6114
6115 \return - 0 for success, non zero for failure
6116
6117 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006118static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006119{
6120 VOS_STATUS status;
6121 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 struct device *dev = NULL;
6123 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006124#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6125 int max_retries = 0;
6126#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006127
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306128#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6129 vos_wconn_trace_init();
6130#endif
6131
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 ENTER();
6133
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006134#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006137
6138 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6139 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6140
6141 //Power Up Libra WLAN card first if not already powered up
6142 status = vos_chipPowerUp(NULL,NULL,NULL);
6143 if (!VOS_IS_STATUS_SUCCESS(status))
6144 {
6145 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6146 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306147#ifdef WLAN_OPEN_SOURCE
6148 wake_lock_destroy(&wlan_wake_lock);
6149#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006150 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 }
6152
Jeff Johnson295189b2012-06-20 16:38:30 -07006153#ifdef ANI_BUS_TYPE_PCI
6154
6155 dev = wcnss_wlan_get_device();
6156
6157#endif // ANI_BUS_TYPE_PCI
6158
6159#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006160
6161#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6162 /* wait until WCNSS driver downloads NV */
6163 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6164 msleep(1000);
6165 }
6166 if (max_retries >= 5) {
6167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306168#ifdef WLAN_OPEN_SOURCE
6169 wake_lock_destroy(&wlan_wake_lock);
6170#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006171 return -ENODEV;
6172 }
6173#endif
6174
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 dev = wcnss_wlan_get_device();
6176#endif // ANI_BUS_TYPE_PLATFORM
6177
6178
6179 do {
6180 if (NULL == dev) {
6181 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6182 ret_status = -1;
6183 break;
6184 }
6185
6186#ifdef MEMORY_DEBUG
6187 vos_mem_init();
6188#endif
6189
6190#ifdef TIMER_MANAGER
6191 vos_timer_manager_init();
6192#endif
6193
6194 /* Preopen VOSS so that it is ready to start at least SAL */
6195 status = vos_preOpen(&pVosContext);
6196
6197 if (!VOS_IS_STATUS_SUCCESS(status))
6198 {
6199 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6200 ret_status = -1;
6201 break;
6202 }
6203
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006204#ifndef MODULE
6205 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6206 */
6207 hdd_set_conparam((v_UINT_t)con_mode);
6208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006209
6210 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006211 if (hdd_wlan_startup(dev))
6212 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006213 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006214 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 vos_preClose( &pVosContext );
6216 ret_status = -1;
6217 break;
6218 }
6219
6220 /* Cancel the vote for XO Core ON
6221 * This is done here for safety purposes in case we re-initialize without turning
6222 * it OFF in any error scenario.
6223 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006224 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006225 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006226 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6228 {
6229 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6230 " Power consumed will be high\n");
6231 }
6232 } while (0);
6233
6234 if (0 != ret_status)
6235 {
6236 //Assert Deep sleep signal now to put Libra HW in lowest power state
6237 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6238 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6239
6240 //Vote off any PMIC voltage supplies
6241 vos_chipPowerDown(NULL, NULL, NULL);
6242#ifdef TIMER_MANAGER
6243 vos_timer_exit();
6244#endif
6245#ifdef MEMORY_DEBUG
6246 vos_mem_exit();
6247#endif
6248
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006249#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006251#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6253 }
6254 else
6255 {
6256 //Send WLAN UP indication to Nlink Service
6257 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6258
6259 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 }
6261
6262 EXIT();
6263
6264 return ret_status;
6265}
6266
Jeff Johnson32d95a32012-09-10 13:15:23 -07006267/**---------------------------------------------------------------------------
6268
6269 \brief hdd_module_init() - Init Function
6270
6271 This is the driver entry point (invoked when module is loaded using insmod)
6272
6273 \param - None
6274
6275 \return - 0 for success, non zero for failure
6276
6277 --------------------------------------------------------------------------*/
6278#ifdef MODULE
6279static int __init hdd_module_init ( void)
6280{
6281 return hdd_driver_init();
6282}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006283#else /* #ifdef MODULE */
6284static int __init hdd_module_init ( void)
6285{
6286 /* Driver initialization is delayed to fwpath_changed_handler */
6287 return 0;
6288}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006289#endif /* #ifdef MODULE */
6290
Jeff Johnson295189b2012-06-20 16:38:30 -07006291
6292/**---------------------------------------------------------------------------
6293
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006294 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006295
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006296 This is the driver exit point (invoked when module is unloaded using rmmod
6297 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
6299 \param - None
6300
6301 \return - None
6302
6303 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006304static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006305{
6306 hdd_context_t *pHddCtx = NULL;
6307 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006308 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006309
6310 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6311
6312 //Get the global vos context
6313 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6314
6315 if(!pVosContext)
6316 {
6317 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6318 goto done;
6319 }
6320
6321 //Get the HDD context.
6322 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6323
6324 if(!pHddCtx)
6325 {
6326 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6327 }
6328 else
6329 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006330 while(isWDresetInProgress()) {
6331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6332 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006333 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006334
6335 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6336 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6337 "%s:SSR never completed, fatal error", __func__);
6338 VOS_BUG(0);
6339 }
6340 }
6341
Jeff Johnson295189b2012-06-20 16:38:30 -07006342
6343 pHddCtx->isLoadUnloadInProgress = TRUE;
6344 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6345
6346 //Do all the cleanup before deregistering the driver
6347 hdd_wlan_exit(pHddCtx);
6348 }
6349
Jeff Johnson295189b2012-06-20 16:38:30 -07006350 vos_preClose( &pVosContext );
6351
6352#ifdef TIMER_MANAGER
6353 vos_timer_exit();
6354#endif
6355#ifdef MEMORY_DEBUG
6356 vos_mem_exit();
6357#endif
6358
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306359#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6360 vos_wconn_trace_exit();
6361#endif
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006364#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006365 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006366#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006367 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6368}
6369
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006370/**---------------------------------------------------------------------------
6371
6372 \brief hdd_module_exit() - Exit function
6373
6374 This is the driver exit point (invoked when module is unloaded using rmmod)
6375
6376 \param - None
6377
6378 \return - None
6379
6380 --------------------------------------------------------------------------*/
6381static void __exit hdd_module_exit(void)
6382{
6383 hdd_driver_exit();
6384}
6385
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006386#ifdef MODULE
6387static int fwpath_changed_handler(const char *kmessage,
6388 struct kernel_param *kp)
6389{
Jeff Johnson76052702013-04-16 13:55:05 -07006390 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006391}
6392
6393static int con_mode_handler(const char *kmessage,
6394 struct kernel_param *kp)
6395{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006396 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006397}
6398#else /* #ifdef MODULE */
6399/**---------------------------------------------------------------------------
6400
Jeff Johnson76052702013-04-16 13:55:05 -07006401 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006402
Jeff Johnson76052702013-04-16 13:55:05 -07006403 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006404 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006405 - invoked when module parameter fwpath is modified from userspace to signal
6406 initializing the WLAN driver or when con_mode is modified from userspace
6407 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006408
6409 \return - 0 for success, non zero for failure
6410
6411 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006412static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006413{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006414 int ret_status;
6415
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006416 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006417 ret_status = hdd_driver_init();
6418 wlan_hdd_inited = ret_status ? 0 : 1;
6419 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006420 }
6421
6422 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006423
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006424 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006425
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006426 ret_status = hdd_driver_init();
6427 wlan_hdd_inited = ret_status ? 0 : 1;
6428 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006429}
6430
Jeff Johnson295189b2012-06-20 16:38:30 -07006431/**---------------------------------------------------------------------------
6432
Jeff Johnson76052702013-04-16 13:55:05 -07006433 \brief fwpath_changed_handler() - Handler Function
6434
6435 Handle changes to the fwpath parameter
6436
6437 \return - 0 for success, non zero for failure
6438
6439 --------------------------------------------------------------------------*/
6440static int fwpath_changed_handler(const char *kmessage,
6441 struct kernel_param *kp)
6442{
6443 int ret;
6444
6445 ret = param_set_copystring(kmessage, kp);
6446 if (0 == ret)
6447 ret = kickstart_driver();
6448 return ret;
6449}
6450
6451/**---------------------------------------------------------------------------
6452
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006453 \brief con_mode_handler() -
6454
6455 Handler function for module param con_mode when it is changed by userspace
6456 Dynamically linked - do nothing
6457 Statically linked - exit and init driver, as in rmmod and insmod
6458
Jeff Johnson76052702013-04-16 13:55:05 -07006459 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006460
Jeff Johnson76052702013-04-16 13:55:05 -07006461 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006462
6463 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006464static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006465{
Jeff Johnson76052702013-04-16 13:55:05 -07006466 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006467
Jeff Johnson76052702013-04-16 13:55:05 -07006468 ret = param_set_int(kmessage, kp);
6469 if (0 == ret)
6470 ret = kickstart_driver();
6471 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006472}
6473#endif /* #ifdef MODULE */
6474
6475/**---------------------------------------------------------------------------
6476
Jeff Johnson295189b2012-06-20 16:38:30 -07006477 \brief hdd_get_conparam() -
6478
6479 This is the driver exit point (invoked when module is unloaded using rmmod)
6480
6481 \param - None
6482
6483 \return - tVOS_CON_MODE
6484
6485 --------------------------------------------------------------------------*/
6486tVOS_CON_MODE hdd_get_conparam ( void )
6487{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006488#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006489 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006490#else
6491 return (tVOS_CON_MODE)curr_con_mode;
6492#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006493}
6494void hdd_set_conparam ( v_UINT_t newParam )
6495{
6496 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006497#ifndef MODULE
6498 curr_con_mode = con_mode;
6499#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006500}
6501/**---------------------------------------------------------------------------
6502
6503 \brief hdd_softap_sta_deauth() - function
6504
6505 This to take counter measure to handle deauth req from HDD
6506
6507 \param - pAdapter - Pointer to the HDD
6508
6509 \param - enable - boolean value
6510
6511 \return - None
6512
6513 --------------------------------------------------------------------------*/
6514
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006515VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006516{
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006518 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006519
6520 ENTER();
6521
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006522 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6523 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006524
6525 //Ignore request to deauth bcmc station
6526 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006527 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006528
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006529 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006530
6531 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006532 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006533}
6534
6535/**---------------------------------------------------------------------------
6536
6537 \brief hdd_softap_sta_disassoc() - function
6538
6539 This to take counter measure to handle deauth req from HDD
6540
6541 \param - pAdapter - Pointer to the HDD
6542
6543 \param - enable - boolean value
6544
6545 \return - None
6546
6547 --------------------------------------------------------------------------*/
6548
6549void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6550{
6551 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6552
6553 ENTER();
6554
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306555 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006556
6557 //Ignore request to disassoc bcmc station
6558 if( pDestMacAddress[0] & 0x1 )
6559 return;
6560
6561 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6562}
6563
6564void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6565{
6566 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6567
6568 ENTER();
6569
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306570 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006571
6572 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6573}
6574
Jeff Johnson295189b2012-06-20 16:38:30 -07006575/**---------------------------------------------------------------------------
6576 *
6577 * \brief hdd_get__concurrency_mode() -
6578 *
6579 *
6580 * \param - None
6581 *
6582 * \return - CONCURRENCY MODE
6583 *
6584 * --------------------------------------------------------------------------*/
6585tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6586{
6587 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6588 hdd_context_t *pHddCtx;
6589
6590 if (NULL != pVosContext)
6591 {
6592 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6593 if (NULL != pHddCtx)
6594 {
6595 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6596 }
6597 }
6598
6599 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006600 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006601 return VOS_STA;
6602}
6603
6604/* Decide whether to allow/not the apps power collapse.
6605 * Allow apps power collapse if we are in connected state.
6606 * if not, allow only if we are in IMPS */
6607v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6608{
6609 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006610 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006611 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006612 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6613 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6614 hdd_adapter_t *pAdapter = NULL;
6615 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006616 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006617
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6619 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006620
Yathish9f22e662012-12-10 14:21:35 -08006621 concurrent_state = hdd_get_concurrency_mode();
6622
6623#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6624 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6625 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6626 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6627 return TRUE;
6628#endif
6629
Jeff Johnson295189b2012-06-20 16:38:30 -07006630 /*loop through all adapters. TBD fix for Concurrency */
6631 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6632 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6633 {
6634 pAdapter = pAdapterNode->pAdapter;
6635 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6636 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6637 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006638 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006639 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006640 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006641 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6642 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006643 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006644 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006645 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6646 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006647 return FALSE;
6648 }
6649 }
6650 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6651 pAdapterNode = pNext;
6652 }
6653 return TRUE;
6654}
6655
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006656/* Decides whether to send suspend notification to Riva
6657 * if any adapter is in BMPS; then it is required */
6658v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6659{
6660 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6661 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6662
6663 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6664 {
6665 return TRUE;
6666 }
6667 return FALSE;
6668}
6669
Jeff Johnson295189b2012-06-20 16:38:30 -07006670void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6671{
6672 switch(mode)
6673 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006674 case VOS_STA_MODE:
6675 case VOS_P2P_CLIENT_MODE:
6676 case VOS_P2P_GO_MODE:
6677 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006678 pHddCtx->concurrency_mode |= (1 << mode);
6679 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006680 break;
6681 default:
6682 break;
6683
6684 }
6685 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6686 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6687}
6688
6689
6690void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6691{
6692 switch(mode)
6693 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006694 case VOS_STA_MODE:
6695 case VOS_P2P_CLIENT_MODE:
6696 case VOS_P2P_GO_MODE:
6697 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006698 pHddCtx->no_of_sessions[mode]--;
6699 if (!(pHddCtx->no_of_sessions[mode]))
6700 pHddCtx->concurrency_mode &= (~(1 << mode));
6701 break;
6702 default:
6703 break;
6704 }
6705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6706 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6707}
6708
Jeff Johnsone7245742012-09-05 17:12:55 -07006709/**---------------------------------------------------------------------------
6710 *
6711 * \brief wlan_hdd_restart_init
6712 *
6713 * This function initalizes restart timer/flag. An internal function.
6714 *
6715 * \param - pHddCtx
6716 *
6717 * \return - None
6718 *
6719 * --------------------------------------------------------------------------*/
6720
6721static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6722{
6723 /* Initialize */
6724 pHddCtx->hdd_restart_retries = 0;
6725 atomic_set(&pHddCtx->isRestartInProgress, 0);
6726 vos_timer_init(&pHddCtx->hdd_restart_timer,
6727 VOS_TIMER_TYPE_SW,
6728 wlan_hdd_restart_timer_cb,
6729 pHddCtx);
6730}
6731/**---------------------------------------------------------------------------
6732 *
6733 * \brief wlan_hdd_restart_deinit
6734 *
6735 * This function cleans up the resources used. An internal function.
6736 *
6737 * \param - pHddCtx
6738 *
6739 * \return - None
6740 *
6741 * --------------------------------------------------------------------------*/
6742
6743static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6744{
6745
6746 VOS_STATUS vos_status;
6747 /* Block any further calls */
6748 atomic_set(&pHddCtx->isRestartInProgress, 1);
6749 /* Cleanup */
6750 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6751 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006752 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006753 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6754 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006755 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006756
6757}
6758
6759/**---------------------------------------------------------------------------
6760 *
6761 * \brief wlan_hdd_framework_restart
6762 *
6763 * This function uses a cfg80211 API to start a framework initiated WLAN
6764 * driver module unload/load.
6765 *
6766 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6767 *
6768 *
6769 * \param - pHddCtx
6770 *
6771 * \return - VOS_STATUS_SUCCESS: Success
6772 * VOS_STATUS_E_EMPTY: Adapter is Empty
6773 * VOS_STATUS_E_NOMEM: No memory
6774
6775 * --------------------------------------------------------------------------*/
6776
6777static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6778{
6779 VOS_STATUS status = VOS_STATUS_SUCCESS;
6780 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006781 int len = (sizeof (struct ieee80211_mgmt));
6782 struct ieee80211_mgmt *mgmt = NULL;
6783
6784 /* Prepare the DEAUTH managment frame with reason code */
6785 mgmt = kzalloc(len, GFP_KERNEL);
6786 if(mgmt == NULL)
6787 {
6788 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6789 "%s: memory allocation failed (%d bytes)", __func__, len);
6790 return VOS_STATUS_E_NOMEM;
6791 }
6792 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006793
6794 /* Iterate over all adapters/devices */
6795 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6796 do
6797 {
6798 if( (status == VOS_STATUS_SUCCESS) &&
6799 pAdapterNode &&
6800 pAdapterNode->pAdapter)
6801 {
6802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6803 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6804 pAdapterNode->pAdapter->dev->name,
6805 pAdapterNode->pAdapter->device_mode,
6806 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006807 /*
6808 * CFG80211 event to restart the driver
6809 *
6810 * 'cfg80211_send_unprot_deauth' sends a
6811 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6812 * of SME(Linux Kernel) state machine.
6813 *
6814 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6815 * the driver.
6816 *
6817 */
6818
6819 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006820 }
6821 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6822 pAdapterNode = pNext;
6823 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6824
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006825
6826 /* Free the allocated management frame */
6827 kfree(mgmt);
6828
Jeff Johnsone7245742012-09-05 17:12:55 -07006829 /* Retry until we unload or reach max count */
6830 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6831 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6832
6833 return status;
6834
6835}
6836/**---------------------------------------------------------------------------
6837 *
6838 * \brief wlan_hdd_restart_timer_cb
6839 *
6840 * Restart timer callback. An internal function.
6841 *
6842 * \param - User data:
6843 *
6844 * \return - None
6845 *
6846 * --------------------------------------------------------------------------*/
6847
6848void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6849{
6850 hdd_context_t *pHddCtx = usrDataForCallback;
6851 wlan_hdd_framework_restart(pHddCtx);
6852 return;
6853
6854}
6855
6856
6857/**---------------------------------------------------------------------------
6858 *
6859 * \brief wlan_hdd_restart_driver
6860 *
6861 * This function sends an event to supplicant to restart the WLAN driver.
6862 *
6863 * This function is called from vos_wlanRestart.
6864 *
6865 * \param - pHddCtx
6866 *
6867 * \return - VOS_STATUS_SUCCESS: Success
6868 * VOS_STATUS_E_EMPTY: Adapter is Empty
6869 * VOS_STATUS_E_ALREADY: Request already in progress
6870
6871 * --------------------------------------------------------------------------*/
6872VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6873{
6874 VOS_STATUS status = VOS_STATUS_SUCCESS;
6875
6876 /* A tight check to make sure reentrancy */
6877 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6878 {
6879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6880 "%s: WLAN restart is already in progress", __func__);
6881
6882 return VOS_STATUS_E_ALREADY;
6883 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006884 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006885#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006886 wcnss_reset_intr();
6887#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006888
Jeff Johnsone7245742012-09-05 17:12:55 -07006889 return status;
6890}
6891
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006892/*
6893 * API to find if there is any STA or P2P-Client is connected
6894 */
6895VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6896{
6897 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6898}
Jeff Johnsone7245742012-09-05 17:12:55 -07006899
Jeff Johnson295189b2012-06-20 16:38:30 -07006900//Register the module init/exit functions
6901module_init(hdd_module_init);
6902module_exit(hdd_module_exit);
6903
6904MODULE_LICENSE("Dual BSD/GPL");
6905MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6906MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6907
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006908module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6909 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006910
Jeff Johnson76052702013-04-16 13:55:05 -07006911module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006912 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);