blob: 4af2a1fc02a626b7c0f23db75c22751a03fcb965 [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
641 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700643 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530644 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700645 if( 0 != ret )
646 {
647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
648 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
649
650 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700651 }
652 /*
653 command should be a string having format
654 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
655 */
Amar Singhal0974e402013-02-12 14:27:46 -0800656 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700657 {
Amar Singhal0974e402013-02-12 14:27:46 -0800658 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700659
660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700661 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700662
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800663 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700664 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800665 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
666 {
667 int suspend = 0;
668 tANI_U8 *ptr = (tANI_U8*)command + 15;
669
670 suspend = *ptr - '0';
671 hdd_set_wlan_suspend_mode(suspend);
672 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800673#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
674 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
675 {
676 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700677 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800678 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
679 eHalStatus status = eHAL_STATUS_SUCCESS;
680
681 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
682 value = value + 15;
683
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700684 /* Convert the value from ascii to integer */
685 ret = kstrtos8(value, 10, &rssi);
686 if (ret < 0)
687 {
688 /* If the input value is greater than max value of datatype, then also
689 kstrtou8 fails */
690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
691 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
692 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
693 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
694 ret = -EINVAL;
695 goto exit;
696 }
697
Srinivas Girigowdade697412013-02-14 16:31:48 -0800698 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700699
Srinivas Girigowdade697412013-02-14 16:31:48 -0800700 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
701 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
702 {
703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
704 "Neighbor lookup threshold value %d is out of range"
705 " (Min: %d Max: %d)", lookUpThreshold,
706 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
707 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
708 ret = -EINVAL;
709 goto exit;
710 }
711
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
713 "%s: Received Command to Set Roam trigger"
714 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
715
716 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
717 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
718 if (eHAL_STATUS_SUCCESS != status)
719 {
720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
721 "%s: Failed to set roam trigger, try again", __func__);
722 ret = -EPERM;
723 goto exit;
724 }
725
726 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
727 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
728 }
729 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
730 {
731 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
732 int rssi = (-1) * lookUpThreshold;
733 char extra[32];
734 tANI_U8 len = 0;
735
736 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
737 if (copy_to_user(priv_data.buf, &extra, len + 1))
738 {
739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
740 "%s: failed to copy data to user buffer", __func__);
741 ret = -EFAULT;
742 goto exit;
743 }
744 }
745 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
746 {
747 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700748 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700749 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700750
Srinivas Girigowdade697412013-02-14 16:31:48 -0800751 /* input refresh period is in terms of seconds */
752 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
753 value = value + 18;
754 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if (ret < 0)
757 {
758 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700759 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700761 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800762 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700763 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
764 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800765 ret = -EINVAL;
766 goto exit;
767 }
768
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700769 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
770 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800771 {
772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700773 "Roam scan period value %d is out of range"
774 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700775 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
776 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800777 ret = -EINVAL;
778 goto exit;
779 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700780 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800781
782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
783 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700784 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700786 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
787 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800788 }
789 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
790 {
791 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
792 char extra[32];
793 tANI_U8 len = 0;
794
795 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
796 /* Returned value is in units of seconds */
797 if (copy_to_user(priv_data.buf, &extra, len + 1))
798 {
799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
800 "%s: failed to copy data to user buffer", __func__);
801 ret = -EFAULT;
802 goto exit;
803 }
804 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
806 {
807 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700808 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700809 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700810
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700811 /* input refresh period is in terms of seconds */
812 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
813 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700814
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700816 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700817 if (ret < 0)
818 {
819 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700820 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700822 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700823 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
825 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
826 ret = -EINVAL;
827 goto exit;
828 }
829
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700830 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
831 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
832 {
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
834 "Neighbor scan results refresh period value %d is out of range"
835 " (Min: %d Max: %d)", roamScanRefreshPeriod,
836 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
837 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
838 ret = -EINVAL;
839 goto exit;
840 }
841 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
842
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
844 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700845 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846
847 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
848 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
849 }
850 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
851 {
852 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
853 char extra[32];
854 tANI_U8 len = 0;
855
856 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
857 /* Returned value is in units of seconds */
858 if (copy_to_user(priv_data.buf, &extra, len + 1))
859 {
860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
861 "%s: failed to copy data to user buffer", __func__);
862 ret = -EFAULT;
863 goto exit;
864 }
865 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700866#ifdef FEATURE_WLAN_LFR
867 /* SETROAMMODE */
868 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
869 {
870 tANI_U8 *value = command;
871 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
872
873 /* Move pointer to ahead of SETROAMMODE<delimiter> */
874 value = value + SIZE_OF_SETROAMMODE + 1;
875
876 /* Convert the value from ascii to integer */
877 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
878 if (ret < 0)
879 {
880 /* If the input value is greater than max value of datatype, then also
881 kstrtou8 fails */
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: kstrtou8 failed range [%d - %d]", __func__,
884 CFG_LFR_FEATURE_ENABLED_MIN,
885 CFG_LFR_FEATURE_ENABLED_MAX);
886 ret = -EINVAL;
887 goto exit;
888 }
889 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
890 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
891 {
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "Roam Mode value %d is out of range"
894 " (Min: %d Max: %d)", roamMode,
895 CFG_LFR_FEATURE_ENABLED_MIN,
896 CFG_LFR_FEATURE_ENABLED_MAX);
897 ret = -EINVAL;
898 goto exit;
899 }
900
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
902 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
903 /*
904 * Note that
905 * SETROAMMODE 0 is to enable LFR while
906 * SETROAMMODE 1 is to disable LFR, but
907 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
908 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
909 */
910 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
911 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
912 else
913 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
914
915 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
916 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
917 }
918 /* GETROAMMODE */
919 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
920 {
921 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
922 char extra[32];
923 tANI_U8 len = 0;
924
925 /*
926 * roamMode value shall be inverted because the sementics is different.
927 */
928 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
929 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
930 else
931 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
932
933 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
934 if (copy_to_user(priv_data.buf, &extra, len + 1))
935 {
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
937 "%s: failed to copy data to user buffer", __func__);
938 ret = -EFAULT;
939 goto exit;
940 }
941 }
942#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800943#endif
944#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
945 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
946 {
947 tANI_U8 *value = command;
948 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
949
950 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
951 value = value + 13;
952 /* Convert the value from ascii to integer */
953 ret = kstrtou8(value, 10, &roamRssiDiff);
954 if (ret < 0)
955 {
956 /* If the input value is greater than max value of datatype, then also
957 kstrtou8 fails */
958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
959 "%s: kstrtou8 failed range [%d - %d]", __func__,
960 CFG_ROAM_RSSI_DIFF_MIN,
961 CFG_ROAM_RSSI_DIFF_MAX);
962 ret = -EINVAL;
963 goto exit;
964 }
965
966 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
967 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
968 {
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
970 "Roam rssi diff value %d is out of range"
971 " (Min: %d Max: %d)", roamRssiDiff,
972 CFG_ROAM_RSSI_DIFF_MIN,
973 CFG_ROAM_RSSI_DIFF_MAX);
974 ret = -EINVAL;
975 goto exit;
976 }
977
978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
979 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
980
981 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
982 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
983 }
984 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
987 char extra[32];
988 tANI_U8 len = 0;
989
990 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
991 if (copy_to_user(priv_data.buf, &extra, len + 1))
992 {
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
994 "%s: failed to copy data to user buffer", __func__);
995 ret = -EFAULT;
996 goto exit;
997 }
998 }
999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "GETBAND", 7) == 0)
1002 {
1003 int band = -1;
1004 char extra[32];
1005 tANI_U8 len = 0;
1006 hdd_getBand_helper(pHddCtx, &band);
1007
1008 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1009 if (copy_to_user(priv_data.buf, &extra, len + 1))
1010 {
1011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1012 "%s: failed to copy data to user buffer", __func__);
1013 ret = -EFAULT;
1014 goto exit;
1015 }
1016 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001017 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1018 {
1019 tANI_U8 *value = command;
1020 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1021 tANI_U8 numChannels = 0;
1022 eHalStatus status = eHAL_STATUS_SUCCESS;
1023
1024 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1025 if (eHAL_STATUS_SUCCESS != status)
1026 {
1027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1028 "%s: Failed to parse channel list information", __func__);
1029 ret = -EINVAL;
1030 goto exit;
1031 }
1032
1033 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1034 {
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1036 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1037 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1038 ret = -EINVAL;
1039 goto exit;
1040 }
1041 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1042 numChannels);
1043 if (eHAL_STATUS_SUCCESS != status)
1044 {
1045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: Failed to update channel list information", __func__);
1047 ret = -EINVAL;
1048 goto exit;
1049 }
1050 }
1051 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1052 {
1053 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1054 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001055 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001056 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001057 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001058
1059 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1060 ChannelList, &numChannels ))
1061 {
1062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1063 "%s: failed to get roam scan channel list", __func__);
1064 ret = -EFAULT;
1065 goto exit;
1066 }
1067 /* output channel list is of the format
1068 [Number of roam scan channels][Channel1][Channel2]... */
1069 /* copy the number of channels in the 0th index */
1070 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1071 for (j = 0; (j < numChannels); j++)
1072 {
1073 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1074 }
1075
1076 if (copy_to_user(priv_data.buf, &extra, len + 1))
1077 {
1078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s: failed to copy data to user buffer", __func__);
1080 ret = -EFAULT;
1081 goto exit;
1082 }
1083 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001084 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1085 {
1086 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1087 char extra[32];
1088 tANI_U8 len = 0;
1089
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001090 /* Check if the features OKC/CCX/11R are supported simultaneously,
1091 then this operation is not permitted (return FAILURE) */
1092 if (ccxMode &&
1093 hdd_is_okc_mode_enabled(pHddCtx) &&
1094 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1095 {
1096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1097 "%s: OKC/CCX/11R are supported simultaneously"
1098 " hence this operation is not permitted!", __func__);
1099 ret = -EPERM;
1100 goto exit;
1101 }
1102
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001103 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1104 if (copy_to_user(priv_data.buf, &extra, len + 1))
1105 {
1106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1107 "%s: failed to copy data to user buffer", __func__);
1108 ret = -EFAULT;
1109 goto exit;
1110 }
1111 }
1112 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1113 {
1114 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1115 char extra[32];
1116 tANI_U8 len = 0;
1117
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001118 /* Check if the features OKC/CCX/11R are supported simultaneously,
1119 then this operation is not permitted (return FAILURE) */
1120 if (okcMode &&
1121 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1122 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1125 "%s: OKC/CCX/11R are supported simultaneously"
1126 " hence this operation is not permitted!", __func__);
1127 ret = -EPERM;
1128 goto exit;
1129 }
1130
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001131 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1132 if (copy_to_user(priv_data.buf, &extra, len + 1))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: failed to copy data to user buffer", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001140 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001141 {
1142 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1143 char extra[32];
1144 tANI_U8 len = 0;
1145
1146 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
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 }
1155 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1156 {
1157 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1158 char extra[32];
1159 tANI_U8 len = 0;
1160
1161 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
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, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1171 {
1172 tANI_U8 *value = command;
1173 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1174
1175 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1176 value = value + 26;
1177 /* Convert the value from ascii to integer */
1178 ret = kstrtou8(value, 10, &minTime);
1179 if (ret < 0)
1180 {
1181 /* If the input value is greater than max value of datatype, then also
1182 kstrtou8 fails */
1183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: kstrtou8 failed range [%d - %d]", __func__,
1185 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1186 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1187 ret = -EINVAL;
1188 goto exit;
1189 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001190 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1191 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1192 {
1193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "scan min channel time value %d is out of range"
1195 " (Min: %d Max: %d)", minTime,
1196 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1197 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1198 ret = -EINVAL;
1199 goto exit;
1200 }
1201
1202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1203 "%s: Received Command to change channel min time = %d", __func__, minTime);
1204
1205 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1206 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1207 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001208 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1209 {
1210 tANI_U8 *value = command;
1211 tANI_U8 channel = 0;
1212 tANI_U8 dwellTime = 0;
1213 tANI_U8 bufLen = 0;
1214 tANI_U8 *buf = NULL;
1215 tSirMacAddr targetApBssid;
1216 eHalStatus status = eHAL_STATUS_SUCCESS;
1217 struct ieee80211_channel chan;
1218 tANI_U8 finalLen = 0;
1219 tANI_U8 *finalBuf = NULL;
1220 tANI_U8 temp = 0;
1221 u64 cookie;
1222 hdd_station_ctx_t *pHddStaCtx = NULL;
1223 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1224
1225 /* if not associated, no need to send action frame */
1226 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1227 {
1228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1229 ret = -EINVAL;
1230 goto exit;
1231 }
1232
1233 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1234 &dwellTime, &buf, &bufLen);
1235 if (eHAL_STATUS_SUCCESS != status)
1236 {
1237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "%s: Failed to parse send action frame data", __func__);
1239 ret = -EINVAL;
1240 goto exit;
1241 }
1242
1243 /* if the target bssid is different from currently associated AP,
1244 then no need to send action frame */
1245 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1246 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1247 {
1248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1249 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001250 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001251 goto exit;
1252 }
1253
1254 /* if the channel number is different from operating channel then
1255 no need to send action frame */
1256 if (channel != pHddStaCtx->conn_info.operationChannel)
1257 {
1258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1259 "%s: channel(%d) is different from operating channel(%d)",
1260 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1261 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001262 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001263 goto exit;
1264 }
1265 chan.center_freq = sme_ChnToFreq(channel);
1266
1267 finalLen = bufLen + 24;
1268 finalBuf = vos_mem_malloc(finalLen);
1269 if (NULL == finalBuf)
1270 {
1271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1272 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001273 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001274 goto exit;
1275 }
1276 vos_mem_zero(finalBuf, finalLen);
1277
1278 /* Fill subtype */
1279 temp = SIR_MAC_MGMT_ACTION << 4;
1280 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1281
1282 /* Fill type */
1283 temp = SIR_MAC_MGMT_FRAME;
1284 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1285
1286 /* Fill destination address (bssid of the AP) */
1287 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1288
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001289 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001290 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1291
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001292 /* Fill BSSID (AP mac address) */
1293 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001294
1295 /* Fill received buffer from 24th address */
1296 vos_mem_copy(finalBuf + 24, buf, bufLen);
1297
Jeff Johnson11c33152013-04-16 17:52:40 -07001298 /* done with the parsed buffer */
1299 vos_mem_free(buf);
1300
Yue Maf49ba872013-08-19 12:04:25 -07001301 wlan_hdd_action( NULL,
1302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1303 &(pAdapter->wdev),
1304#else
1305 dev,
1306#endif
1307 &chan, 0,
1308#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1309 NL80211_CHAN_HT20, 1,
1310#endif
1311 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001312 1, &cookie );
1313 vos_mem_free(finalBuf);
1314 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001315 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1316 {
1317 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1318 char extra[32];
1319 tANI_U8 len = 0;
1320
1321 /* value is interms of msec */
1322 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1323 if (copy_to_user(priv_data.buf, &extra, len + 1))
1324 {
1325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1326 "%s: failed to copy data to user buffer", __func__);
1327 ret = -EFAULT;
1328 goto exit;
1329 }
1330 }
1331 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1332 {
1333 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001334 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001335 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001336
1337 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1338 value = value + 19;
1339 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001340 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001341 if (ret < 0)
1342 {
1343 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001344 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001346 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001347 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1348 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1349 ret = -EINVAL;
1350 goto exit;
1351 }
1352
1353 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1354 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1355 {
1356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1357 "lfr mode value %d is out of range"
1358 " (Min: %d Max: %d)", maxTime,
1359 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1360 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1361 ret = -EINVAL;
1362 goto exit;
1363 }
1364
1365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1366 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1367
1368 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001369
1370 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1371 * where RFS is the RF Switching time. It is twice RFS to consider the
1372 * time to go off channel and return to the home channel. */
1373 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1374 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1375 {
1376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1377 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1378 " Hence enforcing home away time to disable (0)",
1379 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1380 homeAwayTime = 0;
1381 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1382 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1383 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001384 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1385 }
1386 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1387 {
1388 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1389 char extra[32];
1390 tANI_U8 len = 0;
1391
1392 /* value is interms of msec */
1393 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1394 if (copy_to_user(priv_data.buf, &extra, len + 1))
1395 {
1396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1397 "%s: failed to copy data to user buffer", __func__);
1398 ret = -EFAULT;
1399 goto exit;
1400 }
1401 }
1402 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1403 {
1404 tANI_U8 *value = command;
1405 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1406
1407 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1408 value = value + 16;
1409 /* Convert the value from ascii to integer */
1410 ret = kstrtou16(value, 10, &val);
1411 if (ret < 0)
1412 {
1413 /* If the input value is greater than max value of datatype, then also
1414 kstrtou16 fails */
1415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1416 "%s: kstrtou16 failed range [%d - %d]", __func__,
1417 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1418 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1419 ret = -EINVAL;
1420 goto exit;
1421 }
1422
1423 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1424 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1425 {
1426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1427 "scan home time value %d is out of range"
1428 " (Min: %d Max: %d)", val,
1429 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1430 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1431 ret = -EINVAL;
1432 goto exit;
1433 }
1434
1435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1436 "%s: Received Command to change scan home time = %d", __func__, val);
1437
1438 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1439 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1440 }
1441 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1442 {
1443 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1444 char extra[32];
1445 tANI_U8 len = 0;
1446
1447 /* value is interms of msec */
1448 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1449 if (copy_to_user(priv_data.buf, &extra, len + 1))
1450 {
1451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1452 "%s: failed to copy data to user buffer", __func__);
1453 ret = -EFAULT;
1454 goto exit;
1455 }
1456 }
1457 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1458 {
1459 tANI_U8 *value = command;
1460 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1461
1462 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1463 value = value + 17;
1464 /* Convert the value from ascii to integer */
1465 ret = kstrtou8(value, 10, &val);
1466 if (ret < 0)
1467 {
1468 /* If the input value is greater than max value of datatype, then also
1469 kstrtou8 fails */
1470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1471 "%s: kstrtou8 failed range [%d - %d]", __func__,
1472 CFG_ROAM_INTRA_BAND_MIN,
1473 CFG_ROAM_INTRA_BAND_MAX);
1474 ret = -EINVAL;
1475 goto exit;
1476 }
1477
1478 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1479 (val > CFG_ROAM_INTRA_BAND_MAX))
1480 {
1481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1482 "intra band mode value %d is out of range"
1483 " (Min: %d Max: %d)", val,
1484 CFG_ROAM_INTRA_BAND_MIN,
1485 CFG_ROAM_INTRA_BAND_MAX);
1486 ret = -EINVAL;
1487 goto exit;
1488 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1490 "%s: Received Command to change intra band = %d", __func__, val);
1491
1492 pHddCtx->cfg_ini->nRoamIntraBand = val;
1493 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1494 }
1495 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1496 {
1497 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1498 char extra[32];
1499 tANI_U8 len = 0;
1500
1501 /* value is interms of msec */
1502 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1503 if (copy_to_user(priv_data.buf, &extra, len + 1))
1504 {
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: failed to copy data to user buffer", __func__);
1507 ret = -EFAULT;
1508 goto exit;
1509 }
1510 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001511 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1512 {
1513 tANI_U8 *value = command;
1514 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1515
1516 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1517 value = value + 15;
1518 /* Convert the value from ascii to integer */
1519 ret = kstrtou8(value, 10, &nProbes);
1520 if (ret < 0)
1521 {
1522 /* If the input value is greater than max value of datatype, then also
1523 kstrtou8 fails */
1524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1525 "%s: kstrtou8 failed range [%d - %d]", __func__,
1526 CFG_ROAM_SCAN_N_PROBES_MIN,
1527 CFG_ROAM_SCAN_N_PROBES_MAX);
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
1532 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1533 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1534 {
1535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1536 "NProbes value %d is out of range"
1537 " (Min: %d Max: %d)", nProbes,
1538 CFG_ROAM_SCAN_N_PROBES_MIN,
1539 CFG_ROAM_SCAN_N_PROBES_MAX);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
1543
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1545 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1546
1547 pHddCtx->cfg_ini->nProbes = nProbes;
1548 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1549 }
1550 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1551 {
1552 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1553 char extra[32];
1554 tANI_U8 len = 0;
1555
1556 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1557 if (copy_to_user(priv_data.buf, &extra, len + 1))
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1560 "%s: failed to copy data to user buffer", __func__);
1561 ret = -EFAULT;
1562 goto exit;
1563 }
1564 }
1565 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1566 {
1567 tANI_U8 *value = command;
1568 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001569 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001570
1571 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1572 /* input value is in units of msec */
1573 value = value + 20;
1574 /* Convert the value from ascii to integer */
1575 ret = kstrtou16(value, 10, &homeAwayTime);
1576 if (ret < 0)
1577 {
1578 /* If the input value is greater than max value of datatype, then also
1579 kstrtou8 fails */
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: kstrtou8 failed range [%d - %d]", __func__,
1582 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1583 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1584 ret = -EINVAL;
1585 goto exit;
1586 }
1587
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001588 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1589 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1590 {
1591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "homeAwayTime value %d is out of range"
1593 " (Min: %d Max: %d)", homeAwayTime,
1594 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1595 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1596 ret = -EINVAL;
1597 goto exit;
1598 }
1599
1600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1601 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1602
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001603 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1604 * where RFS is the RF Switching time. It is twice RFS to consider the
1605 * time to go off channel and return to the home channel. */
1606 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1607 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1610 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1611 " Hence enforcing home away time to disable (0)",
1612 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1613 homeAwayTime = 0;
1614 }
1615
1616 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1617 {
1618 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1619 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1620 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001621 }
1622 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1623 {
1624 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1625 char extra[32];
1626 tANI_U8 len = 0;
1627
1628 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1629 if (copy_to_user(priv_data.buf, &extra, len + 1))
1630 {
1631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s: failed to copy data to user buffer", __func__);
1633 ret = -EFAULT;
1634 goto exit;
1635 }
1636 }
1637 else if (strncmp(command, "REASSOC", 7) == 0)
1638 {
1639 tANI_U8 *value = command;
1640 tANI_U8 channel = 0;
1641 tSirMacAddr targetApBssid;
1642 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001643#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1644 tCsrHandoffRequest handoffInfo;
1645#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001646 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001647 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1648
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001649 /* if not associated, no need to proceed with reassoc */
1650 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1651 {
1652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1653 ret = -EINVAL;
1654 goto exit;
1655 }
1656
1657 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1658 if (eHAL_STATUS_SUCCESS != status)
1659 {
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: Failed to parse reassoc command data", __func__);
1662 ret = -EINVAL;
1663 goto exit;
1664 }
1665
1666 /* if the target bssid is same as currently associated AP,
1667 then no need to proceed with reassoc */
1668 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1669 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1670 {
1671 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1672 ret = -EINVAL;
1673 goto exit;
1674 }
1675
1676 /* Check channel number is a valid channel number */
1677 if(VOS_STATUS_SUCCESS !=
1678 wlan_hdd_validate_operation_channel(pAdapter, channel))
1679 {
1680 hddLog(VOS_TRACE_LEVEL_ERROR,
1681 "%s: Invalid Channel [%d] \n", __func__, channel);
1682 return -EINVAL;
1683 }
1684
1685 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001686#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1687 handoffInfo.channel = channel;
1688 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1689 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1690#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001691 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001692#endif
1693#ifdef FEATURE_WLAN_LFR
1694 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1695 {
1696 tANI_U8 *value = command;
1697 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1698
1699 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1700 value = value + 12;
1701 /* Convert the value from ascii to integer */
1702 ret = kstrtou8(value, 10, &lfrMode);
1703 if (ret < 0)
1704 {
1705 /* If the input value is greater than max value of datatype, then also
1706 kstrtou8 fails */
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: kstrtou8 failed range [%d - %d]", __func__,
1709 CFG_LFR_FEATURE_ENABLED_MIN,
1710 CFG_LFR_FEATURE_ENABLED_MAX);
1711 ret = -EINVAL;
1712 goto exit;
1713 }
1714
1715 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1716 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1717 {
1718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1719 "lfr mode value %d is out of range"
1720 " (Min: %d Max: %d)", lfrMode,
1721 CFG_LFR_FEATURE_ENABLED_MIN,
1722 CFG_LFR_FEATURE_ENABLED_MAX);
1723 ret = -EINVAL;
1724 goto exit;
1725 }
1726
1727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1728 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1729
1730 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1731 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1732 }
1733#endif
1734#ifdef WLAN_FEATURE_VOWIFI_11R
1735 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1736 {
1737 tANI_U8 *value = command;
1738 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1739
1740 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1741 value = value + 18;
1742 /* Convert the value from ascii to integer */
1743 ret = kstrtou8(value, 10, &ft);
1744 if (ret < 0)
1745 {
1746 /* If the input value is greater than max value of datatype, then also
1747 kstrtou8 fails */
1748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1749 "%s: kstrtou8 failed range [%d - %d]", __func__,
1750 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1751 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1757 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1758 {
1759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1760 "ft mode value %d is out of range"
1761 " (Min: %d Max: %d)", ft,
1762 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1763 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1764 ret = -EINVAL;
1765 goto exit;
1766 }
1767
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1769 "%s: Received Command to change ft mode = %d", __func__, ft);
1770
1771 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1772 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1773 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05301774
1775 else if (strncmp(command, "FASTREASSOC", 11) == 0)
1776 {
1777 tANI_U8 *value = command;
1778 tSirMacAddr targetApBssid;
1779 tANI_U8 trigger = 0;
1780 eHalStatus status = eHAL_STATUS_SUCCESS;
1781 hdd_station_ctx_t *pHddStaCtx = NULL;
1782 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1783
1784 /* if not associated, no need to proceed with reassoc */
1785 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1786 {
1787 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1788 ret = -EINVAL;
1789 goto exit;
1790 }
1791
1792 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
1793 if (eHAL_STATUS_SUCCESS != status)
1794 {
1795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1796 "%s: Failed to parse reassoc command data", __func__);
1797 ret = -EINVAL;
1798 goto exit;
1799 }
1800
1801 /* if the target bssid is same as currently associated AP,
1802 then no need to proceed with reassoc */
1803 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1804 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1805 {
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1807 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
1808 __func__);
1809 ret = -EINVAL;
1810 goto exit;
1811 }
1812
1813 /* Proceed with scan/roam */
1814 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
1815 &targetApBssid[0],
1816 (tSmeFastRoamTrigger)(trigger));
1817 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001818#endif
1819#ifdef FEATURE_WLAN_CCX
1820 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1821 {
1822 tANI_U8 *value = command;
1823 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1824
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001825 /* Check if the features OKC/CCX/11R are supported simultaneously,
1826 then this operation is not permitted (return FAILURE) */
1827 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1828 hdd_is_okc_mode_enabled(pHddCtx) &&
1829 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1830 {
1831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1832 "%s: OKC/CCX/11R are supported simultaneously"
1833 " hence this operation is not permitted!", __func__);
1834 ret = -EPERM;
1835 goto exit;
1836 }
1837
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001838 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1839 value = value + 11;
1840 /* Convert the value from ascii to integer */
1841 ret = kstrtou8(value, 10, &ccxMode);
1842 if (ret < 0)
1843 {
1844 /* If the input value is greater than max value of datatype, then also
1845 kstrtou8 fails */
1846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1847 "%s: kstrtou8 failed range [%d - %d]", __func__,
1848 CFG_CCX_FEATURE_ENABLED_MIN,
1849 CFG_CCX_FEATURE_ENABLED_MAX);
1850 ret = -EINVAL;
1851 goto exit;
1852 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001853 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1854 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1855 {
1856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1857 "Ccx mode value %d is out of range"
1858 " (Min: %d Max: %d)", ccxMode,
1859 CFG_CCX_FEATURE_ENABLED_MIN,
1860 CFG_CCX_FEATURE_ENABLED_MAX);
1861 ret = -EINVAL;
1862 goto exit;
1863 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1865 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1866
1867 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1868 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1869 }
1870#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001871 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1872 {
1873 tANI_U8 *value = command;
1874 tANI_BOOLEAN roamScanControl = 0;
1875
1876 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1877 value = value + 19;
1878 /* Convert the value from ascii to integer */
1879 ret = kstrtou8(value, 10, &roamScanControl);
1880 if (ret < 0)
1881 {
1882 /* If the input value is greater than max value of datatype, then also
1883 kstrtou8 fails */
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1885 "%s: kstrtou8 failed ", __func__);
1886 ret = -EINVAL;
1887 goto exit;
1888 }
1889
1890 if (0 != roamScanControl)
1891 {
1892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "roam scan control invalid value = %d",
1894 roamScanControl);
1895 ret = -EINVAL;
1896 goto exit;
1897 }
1898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1899 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1900
1901 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1902 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001903#ifdef FEATURE_WLAN_OKC
1904 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1905 {
1906 tANI_U8 *value = command;
1907 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1908
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001909 /* Check if the features OKC/CCX/11R are supported simultaneously,
1910 then this operation is not permitted (return FAILURE) */
1911 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1912 hdd_is_okc_mode_enabled(pHddCtx) &&
1913 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1914 {
1915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1916 "%s: OKC/CCX/11R are supported simultaneously"
1917 " hence this operation is not permitted!", __func__);
1918 ret = -EPERM;
1919 goto exit;
1920 }
1921
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001922 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1923 value = value + 11;
1924 /* Convert the value from ascii to integer */
1925 ret = kstrtou8(value, 10, &okcMode);
1926 if (ret < 0)
1927 {
1928 /* If the input value is greater than max value of datatype, then also
1929 kstrtou8 fails */
1930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1931 "%s: kstrtou8 failed range [%d - %d]", __func__,
1932 CFG_OKC_FEATURE_ENABLED_MIN,
1933 CFG_OKC_FEATURE_ENABLED_MAX);
1934 ret = -EINVAL;
1935 goto exit;
1936 }
1937
1938 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1939 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1940 {
1941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1942 "Okc mode value %d is out of range"
1943 " (Min: %d Max: %d)", okcMode,
1944 CFG_OKC_FEATURE_ENABLED_MIN,
1945 CFG_OKC_FEATURE_ENABLED_MAX);
1946 ret = -EINVAL;
1947 goto exit;
1948 }
1949
1950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1951 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1952
1953 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1954 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001955 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1956 {
1957 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1958 char extra[32];
1959 tANI_U8 len = 0;
1960
1961 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1962 if (copy_to_user(priv_data.buf, &extra, len + 1))
1963 {
1964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1965 "%s: failed to copy data to user buffer", __func__);
1966 ret = -EFAULT;
1967 goto exit;
1968 }
1969 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001970#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301971#ifdef WLAN_FEATURE_PACKET_FILTERING
1972 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1973 {
1974 tANI_U8 filterType = 0;
1975 tANI_U8 *value = command;
1976
1977 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1978 value = value + 22;
1979
1980 /* Convert the value from ascii to integer */
1981 ret = kstrtou8(value, 10, &filterType);
1982 if (ret < 0)
1983 {
1984 /* If the input value is greater than max value of datatype,
1985 * then also kstrtou8 fails
1986 */
1987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1988 "%s: kstrtou8 failed range ", __func__);
1989 ret = -EINVAL;
1990 goto exit;
1991 }
1992
1993 if (filterType != 0 && filterType != 1)
1994 {
1995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1996 "%s: Accepted Values are 0 and 1 ", __func__);
1997 ret = -EINVAL;
1998 goto exit;
1999 }
2000 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2001 pAdapter->sessionId);
2002 }
2003#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302004 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2005 {
2006 char *dhcpPhase;
2007 dhcpPhase = command + 12;
2008 if ('1' == *dhcpPhase)
2009 {
2010 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2011 pAdapter->macAddressCurrent.bytes);
2012 }
2013 else if ('2' == *dhcpPhase)
2014 {
2015 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2016 pAdapter->macAddressCurrent.bytes);
2017 }
2018 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002019 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2020 {
2021 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2022 }
2023 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2024 {
2025 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2026 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302027 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2028 {
2029 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2030 char extra[32];
2031 tANI_U8 len = 0;
2032
2033 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
2034 (int)pCfg->nActiveMaxChnTime);
2035 if (copy_to_user(priv_data.buf, &extra, len + 1))
2036 {
2037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2038 "%s: failed to copy data to user buffer", __func__);
2039 ret = -EFAULT;
2040 goto exit;
2041 }
2042 ret = len;
2043 }
2044 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2045 {
2046 tANI_U8 *value = command;
2047 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2048 int val = 0, temp;
2049
2050 value = value + 13;
2051 temp = kstrtou32(value, 10, &val);
2052 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2053 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2054 {
2055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2056 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2057 ret = -EFAULT;
2058 goto exit;
2059 }
2060 pCfg->nActiveMaxChnTime = val;
2061 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002062 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2063 {
2064 tANI_U8 filterType = 0;
2065 tANI_U8 *value;
2066 value = command + 9;
2067
2068 /* Convert the value from ascii to integer */
2069 ret = kstrtou8(value, 10, &filterType);
2070 if (ret < 0)
2071 {
2072 /* If the input value is greater than max value of datatype,
2073 * then also kstrtou8 fails
2074 */
2075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2076 "%s: kstrtou8 failed range ", __func__);
2077 ret = -EINVAL;
2078 goto exit;
2079 }
2080 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2081 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2082 {
2083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2084 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2085 " 2-Sink ", __func__);
2086 ret = -EINVAL;
2087 goto exit;
2088 }
2089 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2090 pHddCtx->drvr_miracast = filterType;
2091 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2092 }
Leo Chang614d2072013-08-22 14:59:44 -07002093 else if (strncmp(command, "SETMCRATE", 9) == 0)
2094 {
2095 int rc;
2096 tANI_U8 *value = command;
2097 int targetRate;
2098
2099 /* Only valid for SAP mode */
2100 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2101 {
2102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2103 "%s: SAP mode is not running", __func__);
2104 ret = -EFAULT;
2105 goto exit;
2106 }
2107
2108 /* Move pointer to ahead of SETMCRATE<delimiter> */
2109 /* input value is in units of hundred kbps */
2110 value = value + 10;
2111 /* Convert the value from ascii to integer, decimal base */
2112 ret = kstrtouint(value, 10, &targetRate);
2113
2114 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2115 if (rc)
2116 {
2117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2118 "%s: Set MC Rate Fail %d", __func__, rc);
2119 ret = -EFAULT;
2120 goto exit;
2121 }
2122 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002123 else {
2124 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2125 __func__, command);
2126 }
2127
Jeff Johnson295189b2012-06-20 16:38:30 -07002128 }
2129exit:
2130 if (command)
2131 {
2132 kfree(command);
2133 }
2134 return ret;
2135}
2136
Srinivas Girigowdade697412013-02-14 16:31:48 -08002137#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2138void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2139{
2140 eCsrBand band = -1;
2141 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2142 switch (band)
2143 {
2144 case eCSR_BAND_ALL:
2145 *pBand = WLAN_HDD_UI_BAND_AUTO;
2146 break;
2147
2148 case eCSR_BAND_24:
2149 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2150 break;
2151
2152 case eCSR_BAND_5G:
2153 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2154 break;
2155
2156 default:
2157 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2158 *pBand = -1;
2159 break;
2160 }
2161}
2162
2163/**---------------------------------------------------------------------------
2164
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002165 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2166
2167 This function parses the send action frame data passed in the format
2168 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2169
Srinivas Girigowda56076852013-08-20 14:00:50 -07002170 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002171 \param - pTargetApBssid Pointer to target Ap bssid
2172 \param - pChannel Pointer to the Target AP channel
2173 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2174 \param - pBuf Pointer to data
2175 \param - pBufLen Pointer to data length
2176
2177 \return - 0 for success non-zero for failure
2178
2179 --------------------------------------------------------------------------*/
2180VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2181 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2182{
2183 tANI_U8 *inPtr = pValue;
2184 tANI_U8 *dataEnd;
2185 int tempInt;
2186 int j = 0;
2187 int i = 0;
2188 int v = 0;
2189 tANI_U8 tempBuf[32];
2190 tANI_U8 tempByte = 0;
2191
2192 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2193 /*no argument after the command*/
2194 if (NULL == inPtr)
2195 {
2196 return -EINVAL;
2197 }
2198
2199 /*no space after the command*/
2200 else if (SPACE_ASCII_VALUE != *inPtr)
2201 {
2202 return -EINVAL;
2203 }
2204
2205 /*removing empty spaces*/
2206 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2207
2208 /*no argument followed by spaces*/
2209 if ('\0' == *inPtr)
2210 {
2211 return -EINVAL;
2212 }
2213
2214 /*getting the first argument ie the target AP bssid */
2215 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2216 {
2217 return -EINVAL;
2218 }
2219 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2220 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2221 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2222
2223 /* point to the next argument */
2224 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2225 /*no argument after the command*/
2226 if (NULL == inPtr) return -EINVAL;
2227
2228 /*removing empty spaces*/
2229 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2230
2231 /*no argument followed by spaces*/
2232 if ('\0' == *inPtr)
2233 {
2234 return -EINVAL;
2235 }
2236
2237 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002238 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002239 v = kstrtos32(tempBuf, 10, &tempInt);
2240 if ( v < 0) return -EINVAL;
2241
2242 *pChannel = tempInt;
2243
2244 /* point to the next argument */
2245 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2246 /*no argument after the command*/
2247 if (NULL == inPtr) return -EINVAL;
2248 /*removing empty spaces*/
2249 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2250
2251 /*no argument followed by spaces*/
2252 if ('\0' == *inPtr)
2253 {
2254 return -EINVAL;
2255 }
2256
2257 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002258 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002259 v = kstrtos32(tempBuf, 10, &tempInt);
2260 if ( v < 0) return -EINVAL;
2261
2262 *pDwellTime = tempInt;
2263
2264 /* point to the next argument */
2265 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2266 /*no argument after the command*/
2267 if (NULL == inPtr) return -EINVAL;
2268 /*removing empty spaces*/
2269 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2270
2271 /*no argument followed by spaces*/
2272 if ('\0' == *inPtr)
2273 {
2274 return -EINVAL;
2275 }
2276
2277 /* find the length of data */
2278 dataEnd = inPtr;
2279 while(('\0' != *dataEnd) )
2280 {
2281 dataEnd++;
2282 ++(*pBufLen);
2283 }
2284 if ( *pBufLen <= 0) return -EINVAL;
2285
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002286 /* Allocate the number of bytes based on the number of input characters
2287 whether it is even or odd.
2288 if the number of input characters are even, then we need N/2 byte.
2289 if the number of input characters are odd, then we need do (N+1)/2 to
2290 compensate rounding off.
2291 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2292 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2293 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002294 if (NULL == *pBuf)
2295 {
2296 hddLog(VOS_TRACE_LEVEL_FATAL,
2297 "%s: vos_mem_alloc failed ", __func__);
2298 return -EINVAL;
2299 }
2300
2301 /* the buffer received from the upper layer is character buffer,
2302 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2303 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2304 and f0 in 3rd location */
2305 for (i = 0, j = 0; j < *pBufLen; j += 2)
2306 {
2307 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2308 (*pBuf)[i++] = tempByte;
2309 }
2310 *pBufLen = i;
2311 return VOS_STATUS_SUCCESS;
2312}
2313
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002314/**---------------------------------------------------------------------------
2315
Srinivas Girigowdade697412013-02-14 16:31:48 -08002316 \brief hdd_parse_channellist() - HDD Parse channel list
2317
2318 This function parses the channel list passed in the format
2319 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002320 if the Number of channels (N) does not match with the actual number of channels passed
2321 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2322 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2323 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2324 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002325
2326 \param - pValue Pointer to input channel list
2327 \param - ChannelList Pointer to local output array to record channel list
2328 \param - pNumChannels Pointer to number of roam scan channels
2329
2330 \return - 0 for success non-zero for failure
2331
2332 --------------------------------------------------------------------------*/
2333VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2334{
2335 tANI_U8 *inPtr = pValue;
2336 int tempInt;
2337 int j = 0;
2338 int v = 0;
2339 char buf[32];
2340
2341 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2342 /*no argument after the command*/
2343 if (NULL == inPtr)
2344 {
2345 return -EINVAL;
2346 }
2347
2348 /*no space after the command*/
2349 else if (SPACE_ASCII_VALUE != *inPtr)
2350 {
2351 return -EINVAL;
2352 }
2353
2354 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002355 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002356
2357 /*no argument followed by spaces*/
2358 if ('\0' == *inPtr)
2359 {
2360 return -EINVAL;
2361 }
2362
2363 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002364 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002365 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002366 if ((v < 0) ||
2367 (tempInt <= 0) ||
2368 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2369 {
2370 return -EINVAL;
2371 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002372
2373 *pNumChannels = tempInt;
2374
2375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2376 "Number of channels are: %d", *pNumChannels);
2377
2378 for (j = 0; j < (*pNumChannels); j++)
2379 {
2380 /*inPtr pointing to the beginning of first space after number of channels*/
2381 inPtr = strpbrk( inPtr, " " );
2382 /*no channel list after the number of channels argument*/
2383 if (NULL == inPtr)
2384 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002385 if (0 != j)
2386 {
2387 *pNumChannels = j;
2388 return VOS_STATUS_SUCCESS;
2389 }
2390 else
2391 {
2392 return -EINVAL;
2393 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002394 }
2395
2396 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002397 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002398
2399 /*no channel list after the number of channels argument and spaces*/
2400 if ( '\0' == *inPtr )
2401 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002402 if (0 != j)
2403 {
2404 *pNumChannels = j;
2405 return VOS_STATUS_SUCCESS;
2406 }
2407 else
2408 {
2409 return -EINVAL;
2410 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002411 }
2412
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002413 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002414 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002415 if ((v < 0) ||
2416 (tempInt <= 0) ||
2417 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2418 {
2419 return -EINVAL;
2420 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002421 pChannelList[j] = tempInt;
2422
2423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2424 "Channel %d added to preferred channel list",
2425 pChannelList[j] );
2426 }
2427
Srinivas Girigowdade697412013-02-14 16:31:48 -08002428 return VOS_STATUS_SUCCESS;
2429}
2430
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002431
2432/**---------------------------------------------------------------------------
2433
2434 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2435
2436 This function parses the reasoc command data passed in the format
2437 REASSOC<space><bssid><space><channel>
2438
Srinivas Girigowda56076852013-08-20 14:00:50 -07002439 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002440 \param - pTargetApBssid Pointer to target Ap bssid
2441 \param - pChannel Pointer to the Target AP channel
2442
2443 \return - 0 for success non-zero for failure
2444
2445 --------------------------------------------------------------------------*/
2446VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2447{
2448 tANI_U8 *inPtr = pValue;
2449 int tempInt;
2450 int v = 0;
2451 tANI_U8 tempBuf[32];
2452
2453 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2454 /*no argument after the command*/
2455 if (NULL == inPtr)
2456 {
2457 return -EINVAL;
2458 }
2459
2460 /*no space after the command*/
2461 else if (SPACE_ASCII_VALUE != *inPtr)
2462 {
2463 return -EINVAL;
2464 }
2465
2466 /*removing empty spaces*/
2467 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2468
2469 /*no argument followed by spaces*/
2470 if ('\0' == *inPtr)
2471 {
2472 return -EINVAL;
2473 }
2474
2475 /*getting the first argument ie the target AP bssid */
2476 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2477 {
2478 return -EINVAL;
2479 }
2480 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2481 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2482 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2483
2484 /* point to the next argument */
2485 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2486 /*no argument after the command*/
2487 if (NULL == inPtr) return -EINVAL;
2488
2489 /*removing empty spaces*/
2490 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2491
2492 /*no argument followed by spaces*/
2493 if ('\0' == *inPtr)
2494 {
2495 return -EINVAL;
2496 }
2497
2498 /*getting the next argument ie the channel number */
2499 sscanf(inPtr, "%s ", tempBuf);
2500 v = kstrtos32(tempBuf, 10, &tempInt);
2501 if ( v < 0) return -EINVAL;
2502
2503 *pChannel = tempInt;
2504 return VOS_STATUS_SUCCESS;
2505}
2506
2507#endif
2508
Jeff Johnson295189b2012-06-20 16:38:30 -07002509/**---------------------------------------------------------------------------
2510
2511 \brief hdd_open() - HDD Open function
2512
2513 This is called in response to ifconfig up
2514
2515 \param - dev Pointer to net_device structure
2516
2517 \return - 0 for success non-zero for failure
2518
2519 --------------------------------------------------------------------------*/
2520int hdd_open (struct net_device *dev)
2521{
2522 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2523 hdd_context_t *pHddCtx;
2524 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2525 VOS_STATUS status;
2526 v_BOOL_t in_standby = TRUE;
2527
2528 if (NULL == pAdapter)
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002531 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002532 return -ENODEV;
2533 }
2534
2535 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2536 if (NULL == pHddCtx)
2537 {
2538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002539 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002540 return -ENODEV;
2541 }
2542
2543 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2544 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2545 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002546 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2547 {
2548 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302549 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002550 in_standby = FALSE;
2551 break;
2552 }
2553 else
2554 {
2555 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2556 pAdapterNode = pNext;
2557 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002558 }
2559
2560 if (TRUE == in_standby)
2561 {
2562 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2563 {
2564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2565 "wlan out of power save", __func__);
2566 return -EINVAL;
2567 }
2568 }
2569
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002570 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002571 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2572 {
2573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002574 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 /* Enable TX queues only when we are connected */
2576 netif_tx_start_all_queues(dev);
2577 }
2578
2579 return 0;
2580}
2581
2582int hdd_mon_open (struct net_device *dev)
2583{
2584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2585
2586 if(pAdapter == NULL) {
2587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002588 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002589 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 }
2591
2592 netif_start_queue(dev);
2593
2594 return 0;
2595}
2596/**---------------------------------------------------------------------------
2597
2598 \brief hdd_stop() - HDD stop function
2599
2600 This is called in response to ifconfig down
2601
2602 \param - dev Pointer to net_device structure
2603
2604 \return - 0 for success non-zero for failure
2605
2606 --------------------------------------------------------------------------*/
2607
2608int hdd_stop (struct net_device *dev)
2609{
2610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2611 hdd_context_t *pHddCtx;
2612 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2613 VOS_STATUS status;
2614 v_BOOL_t enter_standby = TRUE;
2615
2616 ENTER();
2617
2618 if (NULL == pAdapter)
2619 {
2620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002621 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002622 return -ENODEV;
2623 }
2624
2625 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2626 if (NULL == pHddCtx)
2627 {
2628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002629 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002630 return -ENODEV;
2631 }
2632
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002633 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002634 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2635 netif_tx_disable(pAdapter->dev);
2636 netif_carrier_off(pAdapter->dev);
2637
2638
2639 /* SoftAP ifaces should never go in power save mode
2640 making sure same here. */
2641 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2642 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002643 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002644 )
2645 {
2646 /* SoftAP mode, so return from here */
2647 EXIT();
2648 return 0;
2649 }
2650
2651 /* Find if any iface is up then
2652 if any iface is up then can't put device to sleep/ power save mode. */
2653 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2654 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2655 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002656 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2657 {
2658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302659 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002660 enter_standby = FALSE;
2661 break;
2662 }
2663 else
2664 {
2665 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2666 pAdapterNode = pNext;
2667 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 }
2669
2670 if (TRUE == enter_standby)
2671 {
2672 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2673 "entering standby", __func__);
2674 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2675 {
2676 /*log and return success*/
2677 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2678 "wlan in power save", __func__);
2679 }
2680 }
2681
2682 EXIT();
2683 return 0;
2684}
2685
2686/**---------------------------------------------------------------------------
2687
2688 \brief hdd_uninit() - HDD uninit function
2689
2690 This is called during the netdev unregister to uninitialize all data
2691associated with the device
2692
2693 \param - dev Pointer to net_device structure
2694
2695 \return - void
2696
2697 --------------------------------------------------------------------------*/
2698static void hdd_uninit (struct net_device *dev)
2699{
2700 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2701
2702 ENTER();
2703
2704 do
2705 {
2706 if (NULL == pAdapter)
2707 {
2708 hddLog(VOS_TRACE_LEVEL_FATAL,
2709 "%s: NULL pAdapter", __func__);
2710 break;
2711 }
2712
2713 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2714 {
2715 hddLog(VOS_TRACE_LEVEL_FATAL,
2716 "%s: Invalid magic", __func__);
2717 break;
2718 }
2719
2720 if (NULL == pAdapter->pHddCtx)
2721 {
2722 hddLog(VOS_TRACE_LEVEL_FATAL,
2723 "%s: NULL pHddCtx", __func__);
2724 break;
2725 }
2726
2727 if (dev != pAdapter->dev)
2728 {
2729 hddLog(VOS_TRACE_LEVEL_FATAL,
2730 "%s: Invalid device reference", __func__);
2731 /* we haven't validated all cases so let this go for now */
2732 }
2733
2734 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2735
2736 /* after uninit our adapter structure will no longer be valid */
2737 pAdapter->dev = NULL;
2738 pAdapter->magic = 0;
2739 } while (0);
2740
2741 EXIT();
2742}
2743
2744/**---------------------------------------------------------------------------
2745
2746 \brief hdd_release_firmware() -
2747
2748 This function calls the release firmware API to free the firmware buffer.
2749
2750 \param - pFileName Pointer to the File Name.
2751 pCtx - Pointer to the adapter .
2752
2753
2754 \return - 0 for success, non zero for failure
2755
2756 --------------------------------------------------------------------------*/
2757
2758VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2759{
2760 VOS_STATUS status = VOS_STATUS_SUCCESS;
2761 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2762 ENTER();
2763
2764
2765 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2766
2767 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2768
2769 if(pHddCtx->fw) {
2770 release_firmware(pHddCtx->fw);
2771 pHddCtx->fw = NULL;
2772 }
2773 else
2774 status = VOS_STATUS_E_FAILURE;
2775 }
2776 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2777 if(pHddCtx->nv) {
2778 release_firmware(pHddCtx->nv);
2779 pHddCtx->nv = NULL;
2780 }
2781 else
2782 status = VOS_STATUS_E_FAILURE;
2783
2784 }
2785
2786 EXIT();
2787 return status;
2788}
2789
2790/**---------------------------------------------------------------------------
2791
2792 \brief hdd_request_firmware() -
2793
2794 This function reads the firmware file using the request firmware
2795 API and returns the the firmware data and the firmware file size.
2796
2797 \param - pfileName - Pointer to the file name.
2798 - pCtx - Pointer to the adapter .
2799 - ppfw_data - Pointer to the pointer of the firmware data.
2800 - pSize - Pointer to the file size.
2801
2802 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2803
2804 --------------------------------------------------------------------------*/
2805
2806
2807VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2808{
2809 int status;
2810 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2811 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2812 ENTER();
2813
2814 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2815
2816 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2817
2818 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2819 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2820 __func__, pfileName);
2821 retval = VOS_STATUS_E_FAILURE;
2822 }
2823
2824 else {
2825 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2826 *pSize = pHddCtx->fw->size;
2827 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2828 __func__, *pSize);
2829 }
2830 }
2831 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2832
2833 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2834
2835 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2837 __func__, pfileName);
2838 retval = VOS_STATUS_E_FAILURE;
2839 }
2840
2841 else {
2842 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2843 *pSize = pHddCtx->nv->size;
2844 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2845 __func__, *pSize);
2846 }
2847 }
2848
2849 EXIT();
2850 return retval;
2851}
2852/**---------------------------------------------------------------------------
2853 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2854
2855 This is the function invoked by SME to inform the result of a full power
2856 request issued by HDD
2857
2858 \param - callbackcontext - Pointer to cookie
2859 status - result of request
2860
2861 \return - None
2862
2863--------------------------------------------------------------------------*/
2864void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2865{
2866 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2867
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002868 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002869 if(&pHddCtx->full_pwr_comp_var)
2870 {
2871 complete(&pHddCtx->full_pwr_comp_var);
2872 }
2873}
2874
2875/**---------------------------------------------------------------------------
2876
2877 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2878
2879 This is the function invoked by SME to inform the result of BMPS
2880 request issued by HDD
2881
2882 \param - callbackcontext - Pointer to cookie
2883 status - result of request
2884
2885 \return - None
2886
2887--------------------------------------------------------------------------*/
2888void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2889{
2890
2891 struct completion *completion_var = (struct completion*) callbackContext;
2892
2893 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2894 if(completion_var != NULL)
2895 {
2896 complete(completion_var);
2897 }
2898}
2899
2900/**---------------------------------------------------------------------------
2901
2902 \brief hdd_get_cfg_file_size() -
2903
2904 This function reads the configuration file using the request firmware
2905 API and returns the configuration file size.
2906
2907 \param - pCtx - Pointer to the adapter .
2908 - pFileName - Pointer to the file name.
2909 - pBufSize - Pointer to the buffer size.
2910
2911 \return - 0 for success, non zero for failure
2912
2913 --------------------------------------------------------------------------*/
2914
2915VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2916{
2917 int status;
2918 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2919
2920 ENTER();
2921
2922 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2923
2924 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2926 status = VOS_STATUS_E_FAILURE;
2927 }
2928 else {
2929 *pBufSize = pHddCtx->fw->size;
2930 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2931 release_firmware(pHddCtx->fw);
2932 pHddCtx->fw = NULL;
2933 }
2934
2935 EXIT();
2936 return VOS_STATUS_SUCCESS;
2937}
2938
2939/**---------------------------------------------------------------------------
2940
2941 \brief hdd_read_cfg_file() -
2942
2943 This function reads the configuration file using the request firmware
2944 API and returns the cfg data and the buffer size of the configuration file.
2945
2946 \param - pCtx - Pointer to the adapter .
2947 - pFileName - Pointer to the file name.
2948 - pBuffer - Pointer to the data buffer.
2949 - pBufSize - Pointer to the buffer size.
2950
2951 \return - 0 for success, non zero for failure
2952
2953 --------------------------------------------------------------------------*/
2954
2955VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2956 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2957{
2958 int status;
2959 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2960
2961 ENTER();
2962
2963 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2964
2965 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2967 return VOS_STATUS_E_FAILURE;
2968 }
2969 else {
2970 if(*pBufSize != pHddCtx->fw->size) {
2971 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2972 "file size", __func__);
2973 release_firmware(pHddCtx->fw);
2974 pHddCtx->fw = NULL;
2975 return VOS_STATUS_E_FAILURE;
2976 }
2977 else {
2978 if(pBuffer) {
2979 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2980 }
2981 release_firmware(pHddCtx->fw);
2982 pHddCtx->fw = NULL;
2983 }
2984 }
2985
2986 EXIT();
2987
2988 return VOS_STATUS_SUCCESS;
2989}
2990
2991/**---------------------------------------------------------------------------
2992
Jeff Johnson295189b2012-06-20 16:38:30 -07002993 \brief hdd_set_mac_address() -
2994
2995 This function sets the user specified mac address using
2996 the command ifconfig wlanX hw ether <mac adress>.
2997
2998 \param - dev - Pointer to the net device.
2999 - addr - Pointer to the sockaddr.
3000 \return - 0 for success, non zero for failure
3001
3002 --------------------------------------------------------------------------*/
3003
3004static int hdd_set_mac_address(struct net_device *dev, void *addr)
3005{
3006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3007 struct sockaddr *psta_mac_addr = addr;
3008 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3009
3010 ENTER();
3011
3012 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3013
3014#ifdef HDD_SESSIONIZE
3015 // set the MAC address though the STA ID CFG.
3016 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3017 (v_U8_t *)&pAdapter->macAddressCurrent,
3018 sizeof( pAdapter->macAddressCurrent ),
3019 hdd_set_mac_addr_cb, VOS_FALSE );
3020#endif
3021
3022 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3023
3024 EXIT();
3025 return halStatus;
3026}
3027
3028tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3029{
3030 int i;
3031 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3032 {
3033 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3034 break;
3035 }
3036
3037 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3038 return NULL;
3039
3040 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3041 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3042}
3043
3044void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3045{
3046 int i;
3047 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3048 {
3049 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3050 {
3051 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3052 break;
3053 }
3054 }
3055 return;
3056}
3057
3058#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3059 static struct net_device_ops wlan_drv_ops = {
3060 .ndo_open = hdd_open,
3061 .ndo_stop = hdd_stop,
3062 .ndo_uninit = hdd_uninit,
3063 .ndo_start_xmit = hdd_hard_start_xmit,
3064 .ndo_tx_timeout = hdd_tx_timeout,
3065 .ndo_get_stats = hdd_stats,
3066 .ndo_do_ioctl = hdd_ioctl,
3067 .ndo_set_mac_address = hdd_set_mac_address,
3068 .ndo_select_queue = hdd_select_queue,
3069#ifdef WLAN_FEATURE_PACKET_FILTERING
3070#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3071 .ndo_set_rx_mode = hdd_set_multicast_list,
3072#else
3073 .ndo_set_multicast_list = hdd_set_multicast_list,
3074#endif //LINUX_VERSION_CODE
3075#endif
3076 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003077 static struct net_device_ops wlan_mon_drv_ops = {
3078 .ndo_open = hdd_mon_open,
3079 .ndo_stop = hdd_stop,
3080 .ndo_uninit = hdd_uninit,
3081 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3082 .ndo_tx_timeout = hdd_tx_timeout,
3083 .ndo_get_stats = hdd_stats,
3084 .ndo_do_ioctl = hdd_ioctl,
3085 .ndo_set_mac_address = hdd_set_mac_address,
3086 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003087
3088#endif
3089
3090void hdd_set_station_ops( struct net_device *pWlanDev )
3091{
3092#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3093 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3094 pWlanDev->netdev_ops = &wlan_drv_ops;
3095#else
3096 pWlanDev->open = hdd_open;
3097 pWlanDev->stop = hdd_stop;
3098 pWlanDev->uninit = hdd_uninit;
3099 pWlanDev->hard_start_xmit = NULL;
3100 pWlanDev->tx_timeout = hdd_tx_timeout;
3101 pWlanDev->get_stats = hdd_stats;
3102 pWlanDev->do_ioctl = hdd_ioctl;
3103 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3104 pWlanDev->set_mac_address = hdd_set_mac_address;
3105#endif
3106}
3107
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003108static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003109{
3110 struct net_device *pWlanDev = NULL;
3111 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003112 /*
3113 * cfg80211 initialization and registration....
3114 */
3115 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3116
Jeff Johnson295189b2012-06-20 16:38:30 -07003117 if(pWlanDev != NULL)
3118 {
3119
3120 //Save the pointer to the net_device in the HDD adapter
3121 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3122
Jeff Johnson295189b2012-06-20 16:38:30 -07003123 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3124
3125 pAdapter->dev = pWlanDev;
3126 pAdapter->pHddCtx = pHddCtx;
3127 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3128
3129 init_completion(&pAdapter->session_open_comp_var);
3130 init_completion(&pAdapter->session_close_comp_var);
3131 init_completion(&pAdapter->disconnect_comp_var);
3132 init_completion(&pAdapter->linkup_event_var);
3133 init_completion(&pAdapter->cancel_rem_on_chan_var);
3134 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003135#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3136 init_completion(&pAdapter->offchannel_tx_event);
3137#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003138 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003139#ifdef FEATURE_WLAN_TDLS
3140 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003141 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003142 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303143 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003144#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 init_completion(&pHddCtx->mc_sus_event_var);
3146 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303147 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003148 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003149
Jeff Johnson295189b2012-06-20 16:38:30 -07003150 pAdapter->isLinkUpSvcNeeded = FALSE;
3151 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3152 //Init the net_device structure
3153 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3154
3155 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3156 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3157 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3158 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3159
3160 hdd_set_station_ops( pAdapter->dev );
3161
3162 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003163 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3164 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3165 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003166 /* set pWlanDev's parent to underlying device */
3167 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3168 }
3169
3170 return pAdapter;
3171}
3172
3173VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3174{
3175 struct net_device *pWlanDev = pAdapter->dev;
3176 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3177 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3178 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3179
3180 if( rtnl_lock_held )
3181 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003182 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3184 {
3185 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3186 return VOS_STATUS_E_FAILURE;
3187 }
3188 }
3189 if (register_netdevice(pWlanDev))
3190 {
3191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3192 return VOS_STATUS_E_FAILURE;
3193 }
3194 }
3195 else
3196 {
3197 if(register_netdev(pWlanDev))
3198 {
3199 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3200 return VOS_STATUS_E_FAILURE;
3201 }
3202 }
3203 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3204
3205 return VOS_STATUS_SUCCESS;
3206}
3207
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003208static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003209{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003210 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003211
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003212 if (NULL == pAdapter)
3213 {
3214 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3215 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003216 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003217
3218 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3219 {
3220 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3221 return eHAL_STATUS_NOT_INITIALIZED;
3222 }
3223
3224 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3225
3226 /* need to make sure all of our scheduled work has completed.
3227 * This callback is called from MC thread context, so it is safe to
3228 * to call below flush workqueue API from here.
3229 */
3230 flush_scheduled_work();
3231
3232 /* We can be blocked while waiting for scheduled work to be
3233 * flushed, and the adapter structure can potentially be freed, in
3234 * which case the magic will have been reset. So make sure the
3235 * magic is still good, and hence the adapter structure is still
3236 * valid, before signaling completion */
3237 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3238 {
3239 complete(&pAdapter->session_close_comp_var);
3240 }
3241
Jeff Johnson295189b2012-06-20 16:38:30 -07003242 return eHAL_STATUS_SUCCESS;
3243}
3244
3245VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3246{
3247 struct net_device *pWlanDev = pAdapter->dev;
3248 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3249 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3250 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3251 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3252 int rc = 0;
3253
3254 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003255 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 //Open a SME session for future operation
3257 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003258 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3260 {
3261 hddLog(VOS_TRACE_LEVEL_FATAL,
3262 "sme_OpenSession() failed with status code %08d [x%08lx]",
3263 halStatus, halStatus );
3264 status = VOS_STATUS_E_FAILURE;
3265 goto error_sme_open;
3266 }
3267
3268 //Block on a completion variable. Can't wait forever though.
3269 rc = wait_for_completion_interruptible_timeout(
3270 &pAdapter->session_open_comp_var,
3271 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3272 if (!rc)
3273 {
3274 hddLog(VOS_TRACE_LEVEL_FATAL,
3275 "Session is not opened within timeout period code %08d", rc );
3276 status = VOS_STATUS_E_FAILURE;
3277 goto error_sme_open;
3278 }
3279
3280 // Register wireless extensions
3281 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3282 {
3283 hddLog(VOS_TRACE_LEVEL_FATAL,
3284 "hdd_register_wext() failed with status code %08d [x%08lx]",
3285 halStatus, halStatus );
3286 status = VOS_STATUS_E_FAILURE;
3287 goto error_register_wext;
3288 }
3289 //Safe to register the hard_start_xmit function again
3290#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3291 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3292#else
3293 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3294#endif
3295
3296 //Set the Connection State to Not Connected
3297 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3298
3299 //Set the default operation channel
3300 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3301
3302 /* Make the default Auth Type as OPEN*/
3303 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3304
3305 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3306 {
3307 hddLog(VOS_TRACE_LEVEL_FATAL,
3308 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3309 status, status );
3310 goto error_init_txrx;
3311 }
3312
3313 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3314
3315 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3316 {
3317 hddLog(VOS_TRACE_LEVEL_FATAL,
3318 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3319 status, status );
3320 goto error_wmm_init;
3321 }
3322
3323 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3324
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003325#ifdef FEATURE_WLAN_TDLS
3326 if(0 != wlan_hdd_tdls_init(pAdapter))
3327 {
3328 status = VOS_STATUS_E_FAILURE;
3329 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3330 goto error_tdls_init;
3331 }
3332 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3333#endif
3334
Jeff Johnson295189b2012-06-20 16:38:30 -07003335 return VOS_STATUS_SUCCESS;
3336
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003337#ifdef FEATURE_WLAN_TDLS
3338error_tdls_init:
3339 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3340 hdd_wmm_adapter_close(pAdapter);
3341#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003342error_wmm_init:
3343 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3344 hdd_deinit_tx_rx(pAdapter);
3345error_init_txrx:
3346 hdd_UnregisterWext(pWlanDev);
3347error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003348 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003349 {
3350 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003351 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003352 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003353 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003354 {
3355 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003356 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003357 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003358 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003359 }
3360}
3361error_sme_open:
3362 return status;
3363}
3364
Jeff Johnson295189b2012-06-20 16:38:30 -07003365void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3366{
3367 hdd_cfg80211_state_t *cfgState;
3368
3369 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3370
3371 if( NULL != cfgState->buf )
3372 {
3373 int rc;
3374 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3375 rc = wait_for_completion_interruptible_timeout(
3376 &pAdapter->tx_action_cnf_event,
3377 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3378 if(!rc)
3379 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003380 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3382 }
3383 }
3384 return;
3385}
Jeff Johnson295189b2012-06-20 16:38:30 -07003386
3387void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3388{
3389 ENTER();
3390 switch ( pAdapter->device_mode )
3391 {
3392 case WLAN_HDD_INFRA_STATION:
3393 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003394 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003395 {
3396 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3397 {
3398 hdd_deinit_tx_rx( pAdapter );
3399 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3400 }
3401
3402 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3403 {
3404 hdd_wmm_adapter_close( pAdapter );
3405 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3406 }
3407
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003409#ifdef FEATURE_WLAN_TDLS
3410 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3411 {
3412 wlan_hdd_tdls_exit(pAdapter);
3413 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3414 }
3415#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003416
3417 break;
3418 }
3419
3420 case WLAN_HDD_SOFTAP:
3421 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003422 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003423 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003424
3425 hdd_unregister_hostapd(pAdapter);
3426 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003427 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003428 break;
3429 }
3430
3431 case WLAN_HDD_MONITOR:
3432 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003433 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3435 {
3436 hdd_deinit_tx_rx( pAdapter );
3437 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3438 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003439 if(NULL != pAdapterforTx)
3440 {
3441 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3442 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003443 break;
3444 }
3445
3446
3447 default:
3448 break;
3449 }
3450
3451 EXIT();
3452}
3453
3454void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3455{
3456 struct net_device *pWlanDev = pAdapter->dev;
3457
3458 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3459 if( rtnl_held )
3460 {
3461 unregister_netdevice(pWlanDev);
3462 }
3463 else
3464 {
3465 unregister_netdev(pWlanDev);
3466 }
3467 // note that the pAdapter is no longer valid at this point
3468 // since the memory has been reclaimed
3469 }
3470
3471}
3472
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003473void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3474{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303475 VOS_STATUS status;
3476 hdd_adapter_t *pAdapter = NULL;
3477 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003478
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303479 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003480
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303481 /*loop through all adapters.*/
3482 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003483 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303484 pAdapter = pAdapterNode->pAdapter;
3485 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3486 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003487
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303488 { // we skip this registration for modes other than STA and P2P client modes.
3489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3490 pAdapterNode = pNext;
3491 continue;
3492 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003493
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303494 //Apply Dynamic DTIM For P2P
3495 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3496 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3497 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3498 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3499 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3500 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3501 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3502 (eConnectionState_Associated ==
3503 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3504 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3505 {
3506 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003507
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303508 powerRequest.uIgnoreDTIM = 1;
3509 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3510
3511 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3512 {
3513 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3514 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3515 }
3516 else
3517 {
3518 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3519 }
3520
3521 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3522 * specified during Enter/Exit BMPS when LCD off*/
3523 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3524 NULL, eANI_BOOLEAN_FALSE);
3525 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3526 NULL, eANI_BOOLEAN_FALSE);
3527
3528 /* switch to the DTIM specified in cfg.ini */
3529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3530 "Switch to DTIM %d", powerRequest.uListenInterval);
3531 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3532 break;
3533
3534 }
3535
3536 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3537 pAdapterNode = pNext;
3538 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003539}
3540
3541void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3542{
3543 /*Switch back to DTIM 1*/
3544 tSirSetPowerParamsReq powerRequest = { 0 };
3545
3546 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3547 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003548 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003549
3550 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3551 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3552 NULL, eANI_BOOLEAN_FALSE);
3553 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3554 NULL, eANI_BOOLEAN_FALSE);
3555
3556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3557 "Switch to DTIM%d",powerRequest.uListenInterval);
3558 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3559
3560}
3561
Jeff Johnson295189b2012-06-20 16:38:30 -07003562VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3563{
3564 VOS_STATUS status = VOS_STATUS_SUCCESS;
3565
3566 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3567 {
3568 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3569 }
3570
3571 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3572 {
3573 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3574 }
3575
3576 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3577 {
3578 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3579 }
3580
3581 return status;
3582}
3583
3584VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3585{
3586 hdd_adapter_t *pAdapter = NULL;
3587 eHalStatus halStatus;
3588 VOS_STATUS status = VOS_STATUS_E_INVAL;
3589 v_BOOL_t disableBmps = FALSE;
3590 v_BOOL_t disableImps = FALSE;
3591
3592 switch(session_type)
3593 {
3594 case WLAN_HDD_INFRA_STATION:
3595 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003596 case WLAN_HDD_P2P_CLIENT:
3597 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003598 //Exit BMPS -> Is Sta/P2P Client is already connected
3599 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3600 if((NULL != pAdapter)&&
3601 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3602 {
3603 disableBmps = TRUE;
3604 }
3605
3606 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3607 if((NULL != pAdapter)&&
3608 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3609 {
3610 disableBmps = TRUE;
3611 }
3612
3613 //Exit both Bmps and Imps incase of Go/SAP Mode
3614 if((WLAN_HDD_SOFTAP == session_type) ||
3615 (WLAN_HDD_P2P_GO == session_type))
3616 {
3617 disableBmps = TRUE;
3618 disableImps = TRUE;
3619 }
3620
3621 if(TRUE == disableImps)
3622 {
3623 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3624 {
3625 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3626 }
3627 }
3628
3629 if(TRUE == disableBmps)
3630 {
3631 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3632 {
3633 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3634
3635 if(eHAL_STATUS_SUCCESS != halStatus)
3636 {
3637 status = VOS_STATUS_E_FAILURE;
3638 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3639 VOS_ASSERT(0);
3640 return status;
3641 }
3642 }
3643
3644 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3645 {
3646 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3647
3648 if(eHAL_STATUS_SUCCESS != halStatus)
3649 {
3650 status = VOS_STATUS_E_FAILURE;
3651 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3652 VOS_ASSERT(0);
3653 return status;
3654 }
3655 }
3656 }
3657
3658 if((TRUE == disableBmps) ||
3659 (TRUE == disableImps))
3660 {
3661 /* Now, get the chip into Full Power now */
3662 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3663 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3664 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3665
3666 if(halStatus != eHAL_STATUS_SUCCESS)
3667 {
3668 if(halStatus == eHAL_STATUS_PMC_PENDING)
3669 {
3670 //Block on a completion variable. Can't wait forever though
3671 wait_for_completion_interruptible_timeout(
3672 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3673 }
3674 else
3675 {
3676 status = VOS_STATUS_E_FAILURE;
3677 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3678 VOS_ASSERT(0);
3679 return status;
3680 }
3681 }
3682
3683 status = VOS_STATUS_SUCCESS;
3684 }
3685
3686 break;
3687 }
3688 return status;
3689}
3690
3691hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003692 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003693 tANI_U8 rtnl_held )
3694{
3695 hdd_adapter_t *pAdapter = NULL;
3696 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3697 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3698 VOS_STATUS exitbmpsStatus;
3699
3700 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3701
3702 //Disable BMPS incase of Concurrency
3703 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3704
3705 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3706 {
3707 //Fail to Exit BMPS
3708 VOS_ASSERT(0);
3709 return NULL;
3710 }
3711
3712 switch(session_type)
3713 {
3714 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003715 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003716 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003717 {
3718 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3719
3720 if( NULL == pAdapter )
3721 return NULL;
3722
Jeff Johnsone7245742012-09-05 17:12:55 -07003723 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3724 NL80211_IFTYPE_P2P_CLIENT:
3725 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003726
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 pAdapter->device_mode = session_type;
3728
3729 status = hdd_init_station_mode( pAdapter );
3730 if( VOS_STATUS_SUCCESS != status )
3731 goto err_free_netdev;
3732
3733 status = hdd_register_interface( pAdapter, rtnl_held );
3734 if( VOS_STATUS_SUCCESS != status )
3735 {
3736 hdd_deinit_adapter(pHddCtx, pAdapter);
3737 goto err_free_netdev;
3738 }
3739 //Stop the Interface TX queue.
3740 netif_tx_disable(pAdapter->dev);
3741 //netif_tx_disable(pWlanDev);
3742 netif_carrier_off(pAdapter->dev);
3743
3744 break;
3745 }
3746
Jeff Johnson295189b2012-06-20 16:38:30 -07003747 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 case WLAN_HDD_SOFTAP:
3749 {
3750 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3751 if( NULL == pAdapter )
3752 return NULL;
3753
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3755 NL80211_IFTYPE_AP:
3756 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 pAdapter->device_mode = session_type;
3758
3759 status = hdd_init_ap_mode(pAdapter);
3760 if( VOS_STATUS_SUCCESS != status )
3761 goto err_free_netdev;
3762
3763 status = hdd_register_hostapd( pAdapter, rtnl_held );
3764 if( VOS_STATUS_SUCCESS != status )
3765 {
3766 hdd_deinit_adapter(pHddCtx, pAdapter);
3767 goto err_free_netdev;
3768 }
3769
3770 netif_tx_disable(pAdapter->dev);
3771 netif_carrier_off(pAdapter->dev);
3772
3773 hdd_set_conparam( 1 );
3774 break;
3775 }
3776 case WLAN_HDD_MONITOR:
3777 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003778 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3779 if( NULL == pAdapter )
3780 return NULL;
3781
3782 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3783 pAdapter->device_mode = session_type;
3784 status = hdd_register_interface( pAdapter, rtnl_held );
3785#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3786 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3787#else
3788 pAdapter->dev->open = hdd_mon_open;
3789 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3790#endif
3791 hdd_init_tx_rx( pAdapter );
3792 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3793 //Set adapter to be used for data tx. It will use either GO or softap.
3794 pAdapter->sessionCtx.monitor.pAdapterForTx =
3795 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003796 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3797 {
3798 pAdapter->sessionCtx.monitor.pAdapterForTx =
3799 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 /* This workqueue will be used to transmit management packet over
3802 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003803 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3804 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3805 return NULL;
3806 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003807
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3809 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 }
3811 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 case WLAN_HDD_FTM:
3813 {
3814 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3815
3816 if( NULL == pAdapter )
3817 return NULL;
3818 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3819 * message while loading driver in FTM mode. */
3820 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3821 pAdapter->device_mode = session_type;
3822 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05303823
3824 hdd_init_tx_rx( pAdapter );
3825
3826 //Stop the Interface TX queue.
3827 netif_tx_disable(pAdapter->dev);
3828 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003829 }
3830 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 default:
3832 {
3833 VOS_ASSERT(0);
3834 return NULL;
3835 }
3836 }
3837
3838
3839 if( VOS_STATUS_SUCCESS == status )
3840 {
3841 //Add it to the hdd's session list.
3842 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3843 if( NULL == pHddAdapterNode )
3844 {
3845 status = VOS_STATUS_E_NOMEM;
3846 }
3847 else
3848 {
3849 pHddAdapterNode->pAdapter = pAdapter;
3850 status = hdd_add_adapter_back ( pHddCtx,
3851 pHddAdapterNode );
3852 }
3853 }
3854
3855 if( VOS_STATUS_SUCCESS != status )
3856 {
3857 if( NULL != pAdapter )
3858 {
3859 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3860 pAdapter = NULL;
3861 }
3862 if( NULL != pHddAdapterNode )
3863 {
3864 vos_mem_free( pHddAdapterNode );
3865 }
3866
3867 goto resume_bmps;
3868 }
3869
3870 if(VOS_STATUS_SUCCESS == status)
3871 {
3872 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3873
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003874 //Initialize the WoWL service
3875 if(!hdd_init_wowl(pAdapter))
3876 {
3877 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3878 goto err_free_netdev;
3879 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003881 return pAdapter;
3882
3883err_free_netdev:
3884 free_netdev(pAdapter->dev);
3885 wlan_hdd_release_intf_addr( pHddCtx,
3886 pAdapter->macAddressCurrent.bytes );
3887
3888resume_bmps:
3889 //If bmps disabled enable it
3890 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3891 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303892 if (pHddCtx->hdd_wlan_suspended)
3893 {
3894 hdd_set_pwrparams(pHddCtx);
3895 }
3896 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 }
3898 return NULL;
3899}
3900
3901VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3902 tANI_U8 rtnl_held )
3903{
3904 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3905 VOS_STATUS status;
3906
3907 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3908 if( VOS_STATUS_SUCCESS != status )
3909 return status;
3910
3911 while ( pCurrent->pAdapter != pAdapter )
3912 {
3913 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3914 if( VOS_STATUS_SUCCESS != status )
3915 break;
3916
3917 pCurrent = pNext;
3918 }
3919 pAdapterNode = pCurrent;
3920 if( VOS_STATUS_SUCCESS == status )
3921 {
3922 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3923 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3924 hdd_remove_adapter( pHddCtx, pAdapterNode );
3925 vos_mem_free( pAdapterNode );
3926
Jeff Johnson295189b2012-06-20 16:38:30 -07003927
3928 /* If there is a single session of STA/P2P client, re-enable BMPS */
3929 if ((!vos_concurrent_sessions_running()) &&
3930 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3931 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3932 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303933 if (pHddCtx->hdd_wlan_suspended)
3934 {
3935 hdd_set_pwrparams(pHddCtx);
3936 }
3937 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003938 }
3939
3940 return VOS_STATUS_SUCCESS;
3941 }
3942
3943 return VOS_STATUS_E_FAILURE;
3944}
3945
3946VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3947{
3948 hdd_adapter_list_node_t *pHddAdapterNode;
3949 VOS_STATUS status;
3950
3951 ENTER();
3952
3953 do
3954 {
3955 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3956 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3957 {
3958 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3959 vos_mem_free( pHddAdapterNode );
3960 }
3961 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3962
3963 EXIT();
3964
3965 return VOS_STATUS_SUCCESS;
3966}
3967
3968void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3969{
3970 v_U8_t addIE[1] = {0};
3971
3972 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3973 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3974 eANI_BOOLEAN_FALSE) )
3975 {
3976 hddLog(LOGE,
3977 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3978 }
3979
3980 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3981 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3982 eANI_BOOLEAN_FALSE) )
3983 {
3984 hddLog(LOGE,
3985 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3986 }
3987
3988 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3989 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3990 eANI_BOOLEAN_FALSE) )
3991 {
3992 hddLog(LOGE,
3993 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3994 }
3995}
3996
3997VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3998{
3999 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4000 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4001 union iwreq_data wrqu;
4002
4003 ENTER();
4004
4005 switch(pAdapter->device_mode)
4006 {
4007 case WLAN_HDD_INFRA_STATION:
4008 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004009 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004010 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4011 {
4012 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4013 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4014 pAdapter->sessionId,
4015 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4016 else
4017 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4018 pAdapter->sessionId,
4019 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4020 //success implies disconnect command got queued up successfully
4021 if(halStatus == eHAL_STATUS_SUCCESS)
4022 {
4023 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4024 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4025 }
4026 memset(&wrqu, '\0', sizeof(wrqu));
4027 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4028 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4029 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4030 }
4031 else
4032 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304033 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004034 }
4035
4036 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4037 {
4038 INIT_COMPLETION(pAdapter->session_close_comp_var);
4039 if (eHAL_STATUS_SUCCESS ==
4040 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4041 hdd_smeCloseSessionCallback, pAdapter))
4042 {
4043 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004044 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004045 &pAdapter->session_close_comp_var,
4046 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4047 }
4048 }
4049
4050 break;
4051
4052 case WLAN_HDD_SOFTAP:
4053 case WLAN_HDD_P2P_GO:
4054 //Any softap specific cleanup here...
4055 mutex_lock(&pHddCtx->sap_lock);
4056 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4057 {
4058 VOS_STATUS status;
4059 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4060
4061 //Stop Bss.
4062 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4063 if (VOS_IS_STATUS_SUCCESS(status))
4064 {
4065 hdd_hostapd_state_t *pHostapdState =
4066 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4067
4068 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4069
4070 if (!VOS_IS_STATUS_SUCCESS(status))
4071 {
4072 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004073 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004074 }
4075 }
4076 else
4077 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004078 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004079 }
4080 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4081
4082 if (eHAL_STATUS_FAILURE ==
4083 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4084 0, NULL, eANI_BOOLEAN_FALSE))
4085 {
4086 hddLog(LOGE,
4087 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004088 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004089 }
4090
4091 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4092 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4093 eANI_BOOLEAN_FALSE) )
4094 {
4095 hddLog(LOGE,
4096 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4097 }
4098
4099 // Reset WNI_CFG_PROBE_RSP Flags
4100 wlan_hdd_reset_prob_rspies(pAdapter);
4101 kfree(pAdapter->sessionCtx.ap.beacon);
4102 pAdapter->sessionCtx.ap.beacon = NULL;
4103 }
4104 mutex_unlock(&pHddCtx->sap_lock);
4105 break;
4106 case WLAN_HDD_MONITOR:
4107 break;
4108 default:
4109 break;
4110 }
4111
4112 EXIT();
4113 return VOS_STATUS_SUCCESS;
4114}
4115
4116VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4117{
4118 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4119 VOS_STATUS status;
4120 hdd_adapter_t *pAdapter;
4121
4122 ENTER();
4123
4124 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4125
4126 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4127 {
4128 pAdapter = pAdapterNode->pAdapter;
4129 netif_tx_disable(pAdapter->dev);
4130 netif_carrier_off(pAdapter->dev);
4131
4132 hdd_stop_adapter( pHddCtx, pAdapter );
4133
4134 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4135 pAdapterNode = pNext;
4136 }
4137
4138 EXIT();
4139
4140 return VOS_STATUS_SUCCESS;
4141}
4142
4143VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4144{
4145 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4146 VOS_STATUS status;
4147 hdd_adapter_t *pAdapter;
4148
4149 ENTER();
4150
4151 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4152
4153 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4154 {
4155 pAdapter = pAdapterNode->pAdapter;
4156 netif_tx_disable(pAdapter->dev);
4157 netif_carrier_off(pAdapter->dev);
4158
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004159 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4160
Jeff Johnson295189b2012-06-20 16:38:30 -07004161 hdd_deinit_tx_rx(pAdapter);
4162 hdd_wmm_adapter_close(pAdapter);
4163
4164 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4165 pAdapterNode = pNext;
4166 }
4167
4168 EXIT();
4169
4170 return VOS_STATUS_SUCCESS;
4171}
4172
4173VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4174{
4175 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4176 VOS_STATUS status;
4177 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304178 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004179
4180 ENTER();
4181
4182 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4183
4184 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4185 {
4186 pAdapter = pAdapterNode->pAdapter;
4187
4188 switch(pAdapter->device_mode)
4189 {
4190 case WLAN_HDD_INFRA_STATION:
4191 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004192 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304193
4194 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4195
Jeff Johnson295189b2012-06-20 16:38:30 -07004196 hdd_init_station_mode(pAdapter);
4197 /* Open the gates for HDD to receive Wext commands */
4198 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004199 pHddCtx->scan_info.mScanPending = FALSE;
4200 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004201
4202 //Trigger the initial scan
4203 hdd_wlan_initial_scan(pAdapter);
4204
4205 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304206 if (eConnectionState_Associated == connState ||
4207 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004208 {
4209 union iwreq_data wrqu;
4210 memset(&wrqu, '\0', sizeof(wrqu));
4211 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4212 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4213 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004214 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004215
Jeff Johnson295189b2012-06-20 16:38:30 -07004216 /* indicate disconnected event to nl80211 */
4217 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4218 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304220 else if (eConnectionState_Connecting == connState)
4221 {
4222 /*
4223 * Indicate connect failure to supplicant if we were in the
4224 * process of connecting
4225 */
4226 cfg80211_connect_result(pAdapter->dev, NULL,
4227 NULL, 0, NULL, 0,
4228 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4229 GFP_KERNEL);
4230 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004231 break;
4232
4233 case WLAN_HDD_SOFTAP:
4234 /* softAP can handle SSR */
4235 break;
4236
4237 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004238 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07004239 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004240 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004241 break;
4242
4243 case WLAN_HDD_MONITOR:
4244 /* monitor interface start */
4245 break;
4246 default:
4247 break;
4248 }
4249
4250 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4251 pAdapterNode = pNext;
4252 }
4253
4254 EXIT();
4255
4256 return VOS_STATUS_SUCCESS;
4257}
4258
4259VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4260{
4261 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4262 hdd_adapter_t *pAdapter;
4263 VOS_STATUS status;
4264 v_U32_t roamId;
4265
4266 ENTER();
4267
4268 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4269
4270 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4271 {
4272 pAdapter = pAdapterNode->pAdapter;
4273
4274 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4275 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4276 {
4277 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4278 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4279
4280 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4281 init_completion(&pAdapter->disconnect_comp_var);
4282 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4283 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4284
4285 wait_for_completion_interruptible_timeout(
4286 &pAdapter->disconnect_comp_var,
4287 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4288
4289 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4290 pHddCtx->isAmpAllowed = VOS_FALSE;
4291 sme_RoamConnect(pHddCtx->hHal,
4292 pAdapter->sessionId, &(pWextState->roamProfile),
4293 &roamId);
4294 }
4295
4296 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4297 pAdapterNode = pNext;
4298 }
4299
4300 EXIT();
4301
4302 return VOS_STATUS_SUCCESS;
4303}
4304
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004305void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4306{
4307 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4308 VOS_STATUS status;
4309 hdd_adapter_t *pAdapter;
4310 hdd_station_ctx_t *pHddStaCtx;
4311 hdd_ap_ctx_t *pHddApCtx;
4312 hdd_hostapd_state_t * pHostapdState;
4313 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4314 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4315 const char *p2pMode = "DEV";
4316 const char *ccMode = "Standalone";
4317 int n;
4318
4319 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4320 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4321 {
4322 pAdapter = pAdapterNode->pAdapter;
4323 switch (pAdapter->device_mode) {
4324 case WLAN_HDD_INFRA_STATION:
4325 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4326 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4327 staChannel = pHddStaCtx->conn_info.operationChannel;
4328 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4329 }
4330 break;
4331 case WLAN_HDD_P2P_CLIENT:
4332 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4333 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4334 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4335 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4336 p2pMode = "CLI";
4337 }
4338 break;
4339 case WLAN_HDD_P2P_GO:
4340 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4341 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4342 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4343 p2pChannel = pHddApCtx->operatingChannel;
4344 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4345 }
4346 p2pMode = "GO";
4347 break;
4348 case WLAN_HDD_SOFTAP:
4349 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4350 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4351 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4352 apChannel = pHddApCtx->operatingChannel;
4353 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4354 }
4355 break;
4356 default:
4357 break;
4358 }
4359 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4360 pAdapterNode = pNext;
4361 }
4362 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4363 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4364 }
4365 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4366 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4367 if (p2pChannel > 0) {
4368 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4369 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4370 }
4371 if (apChannel > 0) {
4372 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4373 apChannel, MAC_ADDR_ARRAY(apBssid));
4374 }
4375
4376 if (p2pChannel > 0 && apChannel > 0) {
4377 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4378 }
4379}
4380
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004381bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004382{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004383 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004384}
4385
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004386/* Once SSR is disabled then it cannot be set. */
4387void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004388{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004389 if (HDD_SSR_DISABLED == isSsrRequired)
4390 return;
4391
Jeff Johnson295189b2012-06-20 16:38:30 -07004392 isSsrRequired = value;
4393}
4394
4395VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4396 hdd_adapter_list_node_t** ppAdapterNode)
4397{
4398 VOS_STATUS status;
4399 spin_lock(&pHddCtx->hddAdapters.lock);
4400 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4401 (hdd_list_node_t**) ppAdapterNode );
4402 spin_unlock(&pHddCtx->hddAdapters.lock);
4403 return status;
4404}
4405
4406VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4407 hdd_adapter_list_node_t* pAdapterNode,
4408 hdd_adapter_list_node_t** pNextAdapterNode)
4409{
4410 VOS_STATUS status;
4411 spin_lock(&pHddCtx->hddAdapters.lock);
4412 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4413 (hdd_list_node_t*) pAdapterNode,
4414 (hdd_list_node_t**)pNextAdapterNode );
4415
4416 spin_unlock(&pHddCtx->hddAdapters.lock);
4417 return status;
4418}
4419
4420VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4421 hdd_adapter_list_node_t* pAdapterNode)
4422{
4423 VOS_STATUS status;
4424 spin_lock(&pHddCtx->hddAdapters.lock);
4425 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4426 &pAdapterNode->node );
4427 spin_unlock(&pHddCtx->hddAdapters.lock);
4428 return status;
4429}
4430
4431VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4432 hdd_adapter_list_node_t** ppAdapterNode)
4433{
4434 VOS_STATUS status;
4435 spin_lock(&pHddCtx->hddAdapters.lock);
4436 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4437 (hdd_list_node_t**) ppAdapterNode );
4438 spin_unlock(&pHddCtx->hddAdapters.lock);
4439 return status;
4440}
4441
4442VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4443 hdd_adapter_list_node_t* pAdapterNode)
4444{
4445 VOS_STATUS status;
4446 spin_lock(&pHddCtx->hddAdapters.lock);
4447 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4448 (hdd_list_node_t*) pAdapterNode );
4449 spin_unlock(&pHddCtx->hddAdapters.lock);
4450 return status;
4451}
4452
4453VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4454 hdd_adapter_list_node_t* pAdapterNode)
4455{
4456 VOS_STATUS status;
4457 spin_lock(&pHddCtx->hddAdapters.lock);
4458 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4459 (hdd_list_node_t*) pAdapterNode );
4460 spin_unlock(&pHddCtx->hddAdapters.lock);
4461 return status;
4462}
4463
4464hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4465 tSirMacAddr macAddr )
4466{
4467 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4468 hdd_adapter_t *pAdapter;
4469 VOS_STATUS status;
4470
4471 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4472
4473 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4474 {
4475 pAdapter = pAdapterNode->pAdapter;
4476
4477 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4478 macAddr, sizeof(tSirMacAddr) ) )
4479 {
4480 return pAdapter;
4481 }
4482 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4483 pAdapterNode = pNext;
4484 }
4485
4486 return NULL;
4487
4488}
4489
4490hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4491{
4492 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4493 hdd_adapter_t *pAdapter;
4494 VOS_STATUS status;
4495
4496 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4497
4498 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4499 {
4500 pAdapter = pAdapterNode->pAdapter;
4501
4502 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4503 IFNAMSIZ ) )
4504 {
4505 return pAdapter;
4506 }
4507 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4508 pAdapterNode = pNext;
4509 }
4510
4511 return NULL;
4512
4513}
4514
4515hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4516{
4517 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4518 hdd_adapter_t *pAdapter;
4519 VOS_STATUS status;
4520
4521 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4522
4523 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4524 {
4525 pAdapter = pAdapterNode->pAdapter;
4526
4527 if( pAdapter && (mode == pAdapter->device_mode) )
4528 {
4529 return pAdapter;
4530 }
4531 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4532 pAdapterNode = pNext;
4533 }
4534
4535 return NULL;
4536
4537}
4538
4539//Remove this function later
4540hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4541{
4542 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4543 hdd_adapter_t *pAdapter;
4544 VOS_STATUS status;
4545
4546 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4547
4548 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4549 {
4550 pAdapter = pAdapterNode->pAdapter;
4551
4552 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4553 {
4554 return pAdapter;
4555 }
4556
4557 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4558 pAdapterNode = pNext;
4559 }
4560
4561 return NULL;
4562
4563}
4564
Jeff Johnson295189b2012-06-20 16:38:30 -07004565/**---------------------------------------------------------------------------
4566
4567 \brief hdd_set_monitor_tx_adapter() -
4568
4569 This API initializes the adapter to be used while transmitting on monitor
4570 adapter.
4571
4572 \param - pHddCtx - Pointer to the HDD context.
4573 pAdapter - Adapter that will used for TX. This can be NULL.
4574 \return - None.
4575 --------------------------------------------------------------------------*/
4576void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4577{
4578 hdd_adapter_t *pMonAdapter;
4579
4580 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4581
4582 if( NULL != pMonAdapter )
4583 {
4584 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4585 }
4586}
Jeff Johnson295189b2012-06-20 16:38:30 -07004587/**---------------------------------------------------------------------------
4588
4589 \brief hdd_select_queue() -
4590
4591 This API returns the operating channel of the requested device mode
4592
4593 \param - pHddCtx - Pointer to the HDD context.
4594 - mode - Device mode for which operating channel is required
4595 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4596 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4597 \return - channel number. "0" id the requested device is not found OR it is not connected.
4598 --------------------------------------------------------------------------*/
4599v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4600{
4601 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4602 VOS_STATUS status;
4603 hdd_adapter_t *pAdapter;
4604 v_U8_t operatingChannel = 0;
4605
4606 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4607
4608 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4609 {
4610 pAdapter = pAdapterNode->pAdapter;
4611
4612 if( mode == pAdapter->device_mode )
4613 {
4614 switch(pAdapter->device_mode)
4615 {
4616 case WLAN_HDD_INFRA_STATION:
4617 case WLAN_HDD_P2P_CLIENT:
4618 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4619 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4620 break;
4621 case WLAN_HDD_SOFTAP:
4622 case WLAN_HDD_P2P_GO:
4623 /*softap connection info */
4624 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4625 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4626 break;
4627 default:
4628 break;
4629 }
4630
4631 break; //Found the device of interest. break the loop
4632 }
4633
4634 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4635 pAdapterNode = pNext;
4636 }
4637 return operatingChannel;
4638}
4639
4640#ifdef WLAN_FEATURE_PACKET_FILTERING
4641/**---------------------------------------------------------------------------
4642
4643 \brief hdd_set_multicast_list() -
4644
4645 This used to set the multicast address list.
4646
4647 \param - dev - Pointer to the WLAN device.
4648 - skb - Pointer to OS packet (sk_buff).
4649 \return - success/fail
4650
4651 --------------------------------------------------------------------------*/
4652static void hdd_set_multicast_list(struct net_device *dev)
4653{
4654 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004655 int mc_count;
4656 int i = 0;
4657 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304658
4659 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004660 {
4661 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304662 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 return;
4664 }
4665
4666 if (dev->flags & IFF_ALLMULTI)
4667 {
4668 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004669 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304670 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004671 }
4672 else
4673 {
4674 mc_count = netdev_mc_count(dev);
4675 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004676 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004677 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4678 {
4679 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004680 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304681 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004682 return;
4683 }
4684
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304685 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004686
4687 netdev_for_each_mc_addr(ha, dev) {
4688 if (i == mc_count)
4689 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304690 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4691 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4692 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304694 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004695 i++;
4696 }
4697 }
4698 return;
4699}
4700#endif
4701
4702/**---------------------------------------------------------------------------
4703
4704 \brief hdd_select_queue() -
4705
4706 This function is registered with the Linux OS for network
4707 core to decide which queue to use first.
4708
4709 \param - dev - Pointer to the WLAN device.
4710 - skb - Pointer to OS packet (sk_buff).
4711 \return - ac, Queue Index/access category corresponding to UP in IP header
4712
4713 --------------------------------------------------------------------------*/
4714v_U16_t hdd_select_queue(struct net_device *dev,
4715 struct sk_buff *skb)
4716{
4717 return hdd_wmm_select_queue(dev, skb);
4718}
4719
4720
4721/**---------------------------------------------------------------------------
4722
4723 \brief hdd_wlan_initial_scan() -
4724
4725 This function triggers the initial scan
4726
4727 \param - pAdapter - Pointer to the HDD adapter.
4728
4729 --------------------------------------------------------------------------*/
4730void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4731{
4732 tCsrScanRequest scanReq;
4733 tCsrChannelInfo channelInfo;
4734 eHalStatus halStatus;
4735 unsigned long scanId;
4736 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4737
4738 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4739 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4740 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4741
4742 if(sme_Is11dSupported(pHddCtx->hHal))
4743 {
4744 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4745 if ( HAL_STATUS_SUCCESS( halStatus ) )
4746 {
4747 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4748 if( !scanReq.ChannelInfo.ChannelList )
4749 {
4750 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4751 vos_mem_free(channelInfo.ChannelList);
4752 return;
4753 }
4754 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4755 channelInfo.numOfChannels);
4756 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4757 vos_mem_free(channelInfo.ChannelList);
4758 }
4759
4760 scanReq.scanType = eSIR_PASSIVE_SCAN;
4761 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4762 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4763 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4764 }
4765 else
4766 {
4767 scanReq.scanType = eSIR_ACTIVE_SCAN;
4768 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4769 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4770 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4771 }
4772
4773 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4774 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4775 {
4776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4777 __func__, halStatus );
4778 }
4779
4780 if(sme_Is11dSupported(pHddCtx->hHal))
4781 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4782}
4783
4784struct fullPowerContext
4785{
4786 struct completion completion;
4787 unsigned int magic;
4788};
4789#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4790
4791/**---------------------------------------------------------------------------
4792
4793 \brief hdd_full_power_callback() - HDD full power callback function
4794
4795 This is the function invoked by SME to inform the result of a full power
4796 request issued by HDD
4797
4798 \param - callbackcontext - Pointer to cookie
4799 \param - status - result of request
4800
4801 \return - None
4802
4803 --------------------------------------------------------------------------*/
4804static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4805{
4806 struct fullPowerContext *pContext = callbackContext;
4807
4808 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304809 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004810
4811 if (NULL == callbackContext)
4812 {
4813 hddLog(VOS_TRACE_LEVEL_ERROR,
4814 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004815 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004816 return;
4817 }
4818
4819 /* there is a race condition that exists between this callback function
4820 and the caller since the caller could time out either before or
4821 while this code is executing. we'll assume the timeout hasn't
4822 occurred, but we'll verify that right before we save our work */
4823
4824 if (POWER_CONTEXT_MAGIC != pContext->magic)
4825 {
4826 /* the caller presumably timed out so there is nothing we can do */
4827 hddLog(VOS_TRACE_LEVEL_WARN,
4828 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004829 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 return;
4831 }
4832
4833 /* the race is on. caller could have timed out immediately after
4834 we verified the magic, but if so, caller will wait a short time
4835 for us to notify the caller, so the context will stay valid */
4836 complete(&pContext->completion);
4837}
4838
4839/**---------------------------------------------------------------------------
4840
4841 \brief hdd_wlan_exit() - HDD WLAN exit function
4842
4843 This is the driver exit point (invoked during rmmod)
4844
4845 \param - pHddCtx - Pointer to the HDD Context
4846
4847 \return - None
4848
4849 --------------------------------------------------------------------------*/
4850void hdd_wlan_exit(hdd_context_t *pHddCtx)
4851{
4852 eHalStatus halStatus;
4853 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4854 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304855 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 struct fullPowerContext powerContext;
4858 long lrc;
4859
4860 ENTER();
4861
Jeff Johnson88ba7742013-02-27 14:36:02 -08004862 if (VOS_FTM_MODE != hdd_get_conparam())
4863 {
4864 // Unloading, restart logic is no more required.
4865 wlan_hdd_restart_deinit(pHddCtx);
4866 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004867
Jeff Johnson295189b2012-06-20 16:38:30 -07004868 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 {
4872 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4873 WLAN_HDD_INFRA_STATION);
4874 if (pAdapter == NULL)
4875 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4876
4877 if (pAdapter != NULL)
4878 {
4879 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4880 hdd_UnregisterWext(pAdapter->dev);
4881 }
4882 }
4883 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004884
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004886 {
4887 wlan_hdd_ftm_close(pHddCtx);
4888 goto free_hdd_ctx;
4889 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 //Stop the Interface TX queue.
4891 //netif_tx_disable(pWlanDev);
4892 //netif_carrier_off(pWlanDev);
4893
Jeff Johnson295189b2012-06-20 16:38:30 -07004894 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4895 {
4896 pAdapter = hdd_get_adapter(pHddCtx,
4897 WLAN_HDD_SOFTAP);
4898 }
4899 else
4900 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004901 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004902 {
4903 pAdapter = hdd_get_adapter(pHddCtx,
4904 WLAN_HDD_INFRA_STATION);
4905 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 /* DeRegister with platform driver as client for Suspend/Resume */
4908 vosStatus = hddDeregisterPmOps(pHddCtx);
4909 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4910 {
4911 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4912 VOS_ASSERT(0);
4913 }
4914
4915 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4916 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4917 {
4918 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4919 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004920
4921 // Cancel any outstanding scan requests. We are about to close all
4922 // of our adapters, but an adapter structure is what SME passes back
4923 // to our callback function. Hence if there are any outstanding scan
4924 // requests then there is a race condition between when the adapter
4925 // is closed and when the callback is invoked. We try to resolve that
4926 // race condition here by canceling any outstanding scans before we
4927 // close the adapters.
4928 // Note that the scans may be cancelled in an asynchronous manner, so
4929 // ideally there needs to be some kind of synchronization. Rather than
4930 // introduce a new synchronization here, we will utilize the fact that
4931 // we are about to Request Full Power, and since that is synchronized,
4932 // the expectation is that by the time Request Full Power has completed,
4933 // all scans will be cancelled.
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304934 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004935
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004936 //Stop the traffic monitor timer
4937 if ( VOS_TIMER_STATE_RUNNING ==
4938 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4939 {
4940 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4941 }
4942
4943 // Destroy the traffic monitor timer
4944 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4945 &pHddCtx->tx_rx_trafficTmr)))
4946 {
4947 hddLog(VOS_TRACE_LEVEL_ERROR,
4948 "%s: Cannot deallocate Traffic monitor timer", __func__);
4949 }
4950
Jeff Johnson295189b2012-06-20 16:38:30 -07004951 //Disable IMPS/BMPS as we do not want the device to enter any power
4952 //save mode during shutdown
4953 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4954 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4955 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4956
4957 //Ensure that device is in full power as we will touch H/W during vos_Stop
4958 init_completion(&powerContext.completion);
4959 powerContext.magic = POWER_CONTEXT_MAGIC;
4960
4961 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4962 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4963
4964 if (eHAL_STATUS_SUCCESS != halStatus)
4965 {
4966 if (eHAL_STATUS_PMC_PENDING == halStatus)
4967 {
4968 /* request was sent -- wait for the response */
4969 lrc = wait_for_completion_interruptible_timeout(
4970 &powerContext.completion,
4971 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4972 /* either we have a response or we timed out
4973 either way, first invalidate our magic */
4974 powerContext.magic = 0;
4975 if (lrc <= 0)
4976 {
4977 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004978 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004979 /* there is a race condition such that the callback
4980 function could be executing at the same time we are. of
4981 primary concern is if the callback function had already
4982 verified the "magic" but hasn't yet set the completion
4983 variable. Since the completion variable is on our
4984 stack, we'll delay just a bit to make sure the data is
4985 still valid if that is the case */
4986 msleep(50);
4987 }
4988 }
4989 else
4990 {
4991 hddLog(VOS_TRACE_LEVEL_ERROR,
4992 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004993 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 VOS_ASSERT(0);
4995 /* continue -- need to clean up as much as possible */
4996 }
4997 }
4998
Yue Ma0d4891e2013-08-06 17:01:45 -07004999 hdd_debugfs_exit(pHddCtx);
5000
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 // Unregister the Net Device Notifier
5002 unregister_netdevice_notifier(&hdd_netdev_notifier);
5003
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 hdd_stop_all_adapters( pHddCtx );
5005
Jeff Johnson295189b2012-06-20 16:38:30 -07005006#ifdef WLAN_BTAMP_FEATURE
5007 vosStatus = WLANBAP_Stop(pVosContext);
5008 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5009 {
5010 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5011 "%s: Failed to stop BAP",__func__);
5012 }
5013#endif //WLAN_BTAMP_FEATURE
5014
5015 //Stop all the modules
5016 vosStatus = vos_stop( pVosContext );
5017 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5018 {
5019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5020 "%s: Failed to stop VOSS",__func__);
5021 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5022 }
5023
Jeff Johnson295189b2012-06-20 16:38:30 -07005024 //Assert Deep sleep signal now to put Libra HW in lowest power state
5025 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5026 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5027
5028 //Vote off any PMIC voltage supplies
5029 vos_chipPowerDown(NULL, NULL, NULL);
5030
5031 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5032
Leo Chang59cdc7e2013-07-10 10:08:21 -07005033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005035 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005036
5037 //Close the scheduler before calling vos_close to make sure no thread is
5038 // scheduled after the each module close is called i.e after all the data
5039 // structures are freed.
5040 vosStatus = vos_sched_close( pVosContext );
5041 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5042 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5043 "%s: Failed to close VOSS Scheduler",__func__);
5044 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5045 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005046#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005047#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5048 /* Destroy the wake lock */
5049 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5050#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005051 /* Destroy the wake lock */
5052 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005053#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005054
5055 //Close VOSS
5056 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5057 vos_close(pVosContext);
5058
Jeff Johnson295189b2012-06-20 16:38:30 -07005059 //Close Watchdog
5060 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5061 vos_watchdog_close(pVosContext);
5062
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305063 //Clean up HDD Nlink Service
5064 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005065#ifdef WLAN_KD_READY_NOTIFIER
5066 nl_srv_exit(pHddCtx->ptt_pid);
5067#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305068 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005069#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305070
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 /* Cancel the vote for XO Core ON.
5072 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5073 * exited at this point
5074 */
5075 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5076 " when WLAN is turned OFF\n");
5077 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5078 {
5079 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5080 " Not returning failure."
5081 " Power consumed will be high\n");
5082 }
5083
5084 hdd_close_all_adapters( pHddCtx );
5085
5086
5087 //Free up dynamically allocated members inside HDD Adapter
5088 kfree(pHddCtx->cfg_ini);
5089 pHddCtx->cfg_ini= NULL;
5090
5091 /* free the power on lock from platform driver */
5092 if (free_riva_power_on_lock("wlan"))
5093 {
5094 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5095 __func__);
5096 }
5097
Jeff Johnson88ba7742013-02-27 14:36:02 -08005098free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07005099 /* FTM mode, WIPHY did not registered
5100 If un-register here, system crash will happen */
5101 if (VOS_FTM_MODE != hdd_get_conparam())
5102 {
5103 wiphy_unregister(wiphy) ;
5104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 if (hdd_is_ssr_required())
5107 {
5108 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005109 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 msleep(5000);
5111 }
5112 hdd_set_ssr_required (VOS_FALSE);
5113}
5114
5115
5116/**---------------------------------------------------------------------------
5117
5118 \brief hdd_update_config_from_nv() - Function to update the contents of
5119 the running configuration with parameters taken from NV storage
5120
5121 \param - pHddCtx - Pointer to the HDD global context
5122
5123 \return - VOS_STATUS_SUCCESS if successful
5124
5125 --------------------------------------------------------------------------*/
5126static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5127{
Jeff Johnson295189b2012-06-20 16:38:30 -07005128 v_BOOL_t itemIsValid = VOS_FALSE;
5129 VOS_STATUS status;
5130 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5131 v_U8_t macLoop;
5132
5133 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5134 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5135 if(status != VOS_STATUS_SUCCESS)
5136 {
5137 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5138 return VOS_STATUS_E_FAILURE;
5139 }
5140
5141 if (itemIsValid == VOS_TRUE)
5142 {
5143 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5144 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5145 VOS_MAX_CONCURRENCY_PERSONA);
5146 if(status != VOS_STATUS_SUCCESS)
5147 {
5148 /* Get MAC from NV fail, not update CFG info
5149 * INI MAC value will be used for MAC setting */
5150 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5151 return VOS_STATUS_E_FAILURE;
5152 }
5153
5154 /* If first MAC is not valid, treat all others are not valid
5155 * Then all MACs will be got from ini file */
5156 if(vos_is_macaddr_zero(&macFromNV[0]))
5157 {
5158 /* MAC address in NV file is not configured yet */
5159 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5160 return VOS_STATUS_E_INVAL;
5161 }
5162
5163 /* Get MAC address from NV, update CFG info */
5164 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5165 {
5166 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5167 {
5168 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5169 /* This MAC is not valid, skip it
5170 * This MAC will be got from ini file */
5171 }
5172 else
5173 {
5174 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5175 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5176 VOS_MAC_ADDR_SIZE);
5177 }
5178 }
5179 }
5180 else
5181 {
5182 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5183 return VOS_STATUS_E_FAILURE;
5184 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005185
Jeff Johnson295189b2012-06-20 16:38:30 -07005186
5187 return VOS_STATUS_SUCCESS;
5188}
5189
5190/**---------------------------------------------------------------------------
5191
5192 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5193
5194 \param - pAdapter - Pointer to the HDD
5195
5196 \return - None
5197
5198 --------------------------------------------------------------------------*/
5199VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5200{
5201 eHalStatus halStatus;
5202 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305203 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005204
Jeff Johnson295189b2012-06-20 16:38:30 -07005205
5206 // Send ready indication to the HDD. This will kick off the MAC
5207 // into a 'running' state and should kick off an initial scan.
5208 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5209 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5210 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 "code %08d [x%08x]",__func__, halStatus, halStatus );
5213 return VOS_STATUS_E_FAILURE;
5214 }
5215
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305216 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005217 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5218 // And RIVA will crash
5219 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5220 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305221 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5222 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5223
5224
Jeff Johnson295189b2012-06-20 16:38:30 -07005225 return VOS_STATUS_SUCCESS;
5226}
5227
Jeff Johnson295189b2012-06-20 16:38:30 -07005228/* wake lock APIs for HDD */
5229void hdd_prevent_suspend(void)
5230{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005231#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005232 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005233#else
5234 wcnss_prevent_suspend();
5235#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005236}
5237
5238void hdd_allow_suspend(void)
5239{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005240#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005242#else
5243 wcnss_allow_suspend();
5244#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005245}
5246
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005247void hdd_allow_suspend_timeout(v_U32_t timeout)
5248{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005249#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005250 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005251#else
5252 /* Do nothing as there is no API in wcnss for timeout*/
5253#endif
5254}
5255
Jeff Johnson295189b2012-06-20 16:38:30 -07005256/**---------------------------------------------------------------------------
5257
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005258 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5259 information between Host and Riva
5260
5261 This function gets reported version of FW
5262 It also finds the version of Riva headers used to compile the host
5263 It compares the above two and prints a warning if they are different
5264 It gets the SW and HW version string
5265 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5266 indicating the features they support through a bitmap
5267
5268 \param - pHddCtx - Pointer to HDD context
5269
5270 \return - void
5271
5272 --------------------------------------------------------------------------*/
5273
5274void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5275{
5276
5277 tSirVersionType versionCompiled;
5278 tSirVersionType versionReported;
5279 tSirVersionString versionString;
5280 tANI_U8 fwFeatCapsMsgSupported = 0;
5281 VOS_STATUS vstatus;
5282
5283 /* retrieve and display WCNSS version information */
5284 do {
5285
5286 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5287 &versionCompiled);
5288 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5289 {
5290 hddLog(VOS_TRACE_LEVEL_FATAL,
5291 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005292 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005293 break;
5294 }
5295
5296 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5297 &versionReported);
5298 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL,
5301 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005302 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005303 break;
5304 }
5305
5306 if ((versionCompiled.major != versionReported.major) ||
5307 (versionCompiled.minor != versionReported.minor) ||
5308 (versionCompiled.version != versionReported.version) ||
5309 (versionCompiled.revision != versionReported.revision))
5310 {
5311 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5312 "Host expected %u.%u.%u.%u\n",
5313 WLAN_MODULE_NAME,
5314 (int)versionReported.major,
5315 (int)versionReported.minor,
5316 (int)versionReported.version,
5317 (int)versionReported.revision,
5318 (int)versionCompiled.major,
5319 (int)versionCompiled.minor,
5320 (int)versionCompiled.version,
5321 (int)versionCompiled.revision);
5322 }
5323 else
5324 {
5325 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5326 WLAN_MODULE_NAME,
5327 (int)versionReported.major,
5328 (int)versionReported.minor,
5329 (int)versionReported.version,
5330 (int)versionReported.revision);
5331 }
5332
5333 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5334 versionString,
5335 sizeof(versionString));
5336 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5337 {
5338 hddLog(VOS_TRACE_LEVEL_FATAL,
5339 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005340 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005341 break;
5342 }
5343
5344 pr_info("%s: WCNSS software version %s\n",
5345 WLAN_MODULE_NAME, versionString);
5346
5347 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5348 versionString,
5349 sizeof(versionString));
5350 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5351 {
5352 hddLog(VOS_TRACE_LEVEL_FATAL,
5353 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005354 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005355 break;
5356 }
5357
5358 pr_info("%s: WCNSS hardware version %s\n",
5359 WLAN_MODULE_NAME, versionString);
5360
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005361 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5362 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005363 send the message only if it the riva is 1.1
5364 minor numbers for different riva branches:
5365 0 -> (1.0)Mainline Build
5366 1 -> (1.1)Mainline Build
5367 2->(1.04) Stability Build
5368 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005369 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005370 ((versionReported.minor>=1) && (versionReported.version>=1)))
5371 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5372 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005373
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005374 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005375 {
5376#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5377 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5378 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5379#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005380 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5381 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5382 {
5383 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5384 }
5385
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005386 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005387 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005388
5389 } while (0);
5390
5391}
5392
5393/**---------------------------------------------------------------------------
5394
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305395 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5396
5397 \param - pHddCtx - Pointer to the hdd context
5398
5399 \return - true if hardware supports 5GHz
5400
5401 --------------------------------------------------------------------------*/
5402static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5403{
5404 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5405 * then hardware support 5Ghz.
5406 */
5407 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5408 {
5409 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5410 return true;
5411 }
5412 else
5413 {
5414 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5415 __func__);
5416 return false;
5417 }
5418}
5419
5420
5421/**---------------------------------------------------------------------------
5422
Jeff Johnson295189b2012-06-20 16:38:30 -07005423 \brief hdd_wlan_startup() - HDD init function
5424
5425 This is the driver startup code executed once a WLAN device has been detected
5426
5427 \param - dev - Pointer to the underlying device
5428
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005429 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005430
5431 --------------------------------------------------------------------------*/
5432
5433int hdd_wlan_startup(struct device *dev )
5434{
5435 VOS_STATUS status;
5436 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005437 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 hdd_context_t *pHddCtx = NULL;
5439 v_CONTEXT_t pVosContext= NULL;
5440#ifdef WLAN_BTAMP_FEATURE
5441 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5442 WLANBAP_ConfigType btAmpConfig;
5443 hdd_config_t *pConfig;
5444#endif
5445 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005447
5448 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 /*
5450 * cfg80211: wiphy allocation
5451 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305452 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005453
5454 if(wiphy == NULL)
5455 {
5456 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005457 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 }
5459
5460 pHddCtx = wiphy_priv(wiphy);
5461
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 //Initialize the adapter context to zeros.
5463 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5464
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 hdd_prevent_suspend();
5467 pHddCtx->isLoadUnloadInProgress = TRUE;
5468
5469 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5470
5471 /*Get vos context here bcoz vos_open requires it*/
5472 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5473
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005474 if(pVosContext == NULL)
5475 {
5476 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5477 goto err_free_hdd_context;
5478 }
5479
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 //Save the Global VOSS context in adapter context for future.
5481 pHddCtx->pvosContext = pVosContext;
5482
5483 //Save the adapter context in global context for future.
5484 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5485
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 pHddCtx->parent_dev = dev;
5487
5488 init_completion(&pHddCtx->full_pwr_comp_var);
5489 init_completion(&pHddCtx->standby_comp_var);
5490 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005491 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005492 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhalfddc28c2013-09-05 13:03:40 -07005493 init_completion(&pHddCtx->linux_reg_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005494
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305495 spin_lock_init(&pHddCtx->schedScan_lock);
5496
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5498
5499 // Load all config first as TL config is needed during vos_open
5500 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5501 if(pHddCtx->cfg_ini == NULL)
5502 {
5503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5504 goto err_free_hdd_context;
5505 }
5506
5507 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5508
5509 // Read and parse the qcom_cfg.ini file
5510 status = hdd_parse_config_ini( pHddCtx );
5511 if ( VOS_STATUS_SUCCESS != status )
5512 {
5513 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5514 __func__, WLAN_INI_FILE);
5515 goto err_config;
5516 }
5517
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305518 /* INI has been read, initialise the configuredMcastBcastFilter with
5519 * INI value as this will serve as the default value
5520 */
5521 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5522 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5523 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305524
5525 if (false == hdd_is_5g_supported(pHddCtx))
5526 {
5527 //5Ghz is not supported.
5528 if (1 != pHddCtx->cfg_ini->nBandCapability)
5529 {
5530 hddLog(VOS_TRACE_LEVEL_INFO,
5531 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5532 pHddCtx->cfg_ini->nBandCapability = 1;
5533 }
5534 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305535
5536 /* If SNR Monitoring is enabled, FW has to parse all beacons
5537 * for calcaluting and storing the average SNR, so set Nth beacon
5538 * filter to 1 to enable FW to parse all the beaocons
5539 */
5540 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5541 {
5542 /* The log level is deliberately set to WARN as overriding
5543 * nthBeaconFilter to 1 will increase power cosumption and this
5544 * might just prove helpful to detect the power issue.
5545 */
5546 hddLog(VOS_TRACE_LEVEL_WARN,
5547 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5548 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5549 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305551 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305553 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 {
5555 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305556 "%s: wlan_hdd_cfg80211_init return failure", __func__);
5557 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07005558 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005559
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005560 // Update VOS trace levels based upon the cfg.ini
5561 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5562 pHddCtx->cfg_ini->vosTraceEnableBAP);
5563 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5564 pHddCtx->cfg_ini->vosTraceEnableTL);
5565 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5566 pHddCtx->cfg_ini->vosTraceEnableWDI);
5567 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5568 pHddCtx->cfg_ini->vosTraceEnableHDD);
5569 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5570 pHddCtx->cfg_ini->vosTraceEnableSME);
5571 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5572 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05305573 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
5574 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005575 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5576 pHddCtx->cfg_ini->vosTraceEnableWDA);
5577 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5578 pHddCtx->cfg_ini->vosTraceEnableSYS);
5579 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5580 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005581 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5582 pHddCtx->cfg_ini->vosTraceEnableSAP);
5583 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5584 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005585
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 // Update WDI trace levels based upon the cfg.ini
5587 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5588 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5589 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5590 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5591 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5592 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5593 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5594 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005595
Jeff Johnson88ba7742013-02-27 14:36:02 -08005596 if (VOS_FTM_MODE == hdd_get_conparam())
5597 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5599 {
5600 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5601 goto err_free_hdd_context;
5602 }
5603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5604 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005605 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005606
Jeff Johnson88ba7742013-02-27 14:36:02 -08005607 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5609 {
5610 status = vos_watchdog_open(pVosContext,
5611 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5612
5613 if(!VOS_IS_STATUS_SUCCESS( status ))
5614 {
5615 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305616 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005617 }
5618 }
5619
5620 pHddCtx->isLogpInProgress = FALSE;
5621 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5622
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5624 if(!VOS_IS_STATUS_SUCCESS(status))
5625 {
5626 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005627 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 }
5629
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 status = vos_open( &pVosContext, 0);
5631 if ( !VOS_IS_STATUS_SUCCESS( status ))
5632 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005633 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5634 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005635 }
5636
Jeff Johnson295189b2012-06-20 16:38:30 -07005637 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5638
5639 if ( NULL == pHddCtx->hHal )
5640 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005641 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 goto err_vosclose;
5643 }
5644
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005645 status = vos_preStart( pHddCtx->pvosContext );
5646 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5647 {
5648 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5649 goto err_vosclose;
5650 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005651
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005652 /* Note that the vos_preStart() sequence triggers the cfg download.
5653 The cfg download must occur before we update the SME config
5654 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 status = hdd_set_sme_config( pHddCtx );
5656
5657 if ( VOS_STATUS_SUCCESS != status )
5658 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005659 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5660 goto err_vosclose;
5661 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005662
5663 //Initialize the WMM module
5664 status = hdd_wmm_init(pHddCtx);
5665 if (!VOS_IS_STATUS_SUCCESS(status))
5666 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005667 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 goto err_vosclose;
5669 }
5670
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 /* In the integrated architecture we update the configuration from
5672 the INI file and from NV before vOSS has been started so that
5673 the final contents are available to send down to the cCPU */
5674
5675 // Apply the cfg.ini to cfg.dat
5676 if (FALSE == hdd_update_config_dat(pHddCtx))
5677 {
5678 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5679 goto err_vosclose;
5680 }
5681
5682 // Apply the NV to cfg.dat
5683 /* Prima Update MAC address only at here */
5684 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5685 {
5686#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5687 /* There was not a valid set of MAC Addresses in NV. See if the
5688 default addresses were modified by the cfg.ini settings. If so,
5689 we'll use them, but if not, we'll autogenerate a set of MAC
5690 addresses based upon the device serial number */
5691
5692 static const v_MACADDR_t default_address =
5693 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5694 unsigned int serialno;
5695 int i;
5696
5697 serialno = wcnss_get_serial_number();
5698 if ((0 != serialno) &&
5699 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5700 sizeof(default_address))))
5701 {
5702 /* cfg.ini has the default address, invoke autogen logic */
5703
5704 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5705 bytes of the serial number that can be used to generate
5706 the other 3 bytes of the MAC address. Mask off all but
5707 the lower 3 bytes (this will also make sure we don't
5708 overflow in the next step) */
5709 serialno &= 0x00FFFFFF;
5710
5711 /* we need a unique address for each session */
5712 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5713
5714 /* autogen all addresses */
5715 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5716 {
5717 /* start with the entire default address */
5718 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5719 /* then replace the lower 3 bytes */
5720 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5721 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5722 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5723
5724 serialno++;
5725 }
5726
5727 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5728 MAC_ADDRESS_STR,
5729 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5730 }
5731 else
5732#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5733 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005734 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005735 "%s: Invalid MAC address in NV, using MAC from ini file "
5736 MAC_ADDRESS_STR, __func__,
5737 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5738 }
5739 }
5740 {
5741 eHalStatus halStatus;
5742 // Set the MAC Address
5743 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5744 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5745 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5746 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5747
5748 if (!HAL_STATUS_SUCCESS( halStatus ))
5749 {
5750 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5751 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005752 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 }
5754 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005755
5756 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5757 Note: Firmware image will be read and downloaded inside vos_start API */
5758 status = vos_start( pHddCtx->pvosContext );
5759 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5760 {
5761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5762 goto err_vosclose;
5763 }
5764
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005765 /* Exchange capability info between Host and FW and also get versioning info from FW */
5766 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005767
5768 status = hdd_post_voss_start_config( pHddCtx );
5769 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5770 {
5771 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5772 __func__);
5773 goto err_vosstop;
5774 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305775 wlan_hdd_cfg80211_update_reg_info( wiphy );
5776
5777 /* registration of wiphy dev with cfg80211 */
5778 if (0 > wlan_hdd_cfg80211_register(wiphy))
5779 {
5780 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5781 goto err_vosstop;
5782 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005783
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5785 {
5786 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5787 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5788 }
5789 else
5790 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5792 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5793 if (pAdapter != NULL)
5794 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305795 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305797 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5798 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5799 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005800
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305801 /* Generate the P2P Device Address. This consists of the device's
5802 * primary MAC address with the locally administered bit set.
5803 */
5804 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005805 }
5806 else
5807 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305808 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5809 if (p2p_dev_addr != NULL)
5810 {
5811 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5812 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5813 }
5814 else
5815 {
5816 hddLog(VOS_TRACE_LEVEL_FATAL,
5817 "%s: Failed to allocate mac_address for p2p_device",
5818 __func__);
5819 goto err_close_adapter;
5820 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005822
5823 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5824 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5825 if ( NULL == pP2pAdapter )
5826 {
5827 hddLog(VOS_TRACE_LEVEL_FATAL,
5828 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005829 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005830 goto err_close_adapter;
5831 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005834
5835 if( pAdapter == NULL )
5836 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005837 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5838 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005840
Jeff Johnson295189b2012-06-20 16:38:30 -07005841#ifdef WLAN_BTAMP_FEATURE
5842 vStatus = WLANBAP_Open(pVosContext);
5843 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5844 {
5845 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5846 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005847 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 }
5849
5850 vStatus = BSL_Init(pVosContext);
5851 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5852 {
5853 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5854 "%s: Failed to Init BSL",__func__);
5855 goto err_bap_close;
5856 }
5857 vStatus = WLANBAP_Start(pVosContext);
5858 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5859 {
5860 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5861 "%s: Failed to start TL",__func__);
5862 goto err_bap_close;
5863 }
5864
5865 pConfig = pHddCtx->cfg_ini;
5866 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5867 status = WLANBAP_SetConfig(&btAmpConfig);
5868
5869#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005870
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005871#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5872 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5873 {
5874 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5875 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5876 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5877 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5878 }
5879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005880#ifdef FEATURE_WLAN_SCAN_PNO
5881 /*SME must send channel update configuration to RIVA*/
5882 sme_UpdateChannelConfig(pHddCtx->hHal);
5883#endif
5884
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 /* Register with platform driver as client for Suspend/Resume */
5886 status = hddRegisterPmOps(pHddCtx);
5887 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5888 {
5889 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5890#ifdef WLAN_BTAMP_FEATURE
5891 goto err_bap_stop;
5892#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005893 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005894#endif //WLAN_BTAMP_FEATURE
5895 }
5896
Yue Ma0d4891e2013-08-06 17:01:45 -07005897 /* Open debugfs interface */
5898 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5899 {
5900 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5901 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07005902 }
5903
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 /* Register TM level change handler function to the platform */
5905 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5906 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5907 {
5908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5909 goto err_unregister_pmops;
5910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005911
5912 /* register for riva power on lock to platform driver */
5913 if (req_riva_power_on_lock("wlan"))
5914 {
5915 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5916 __func__);
5917 goto err_unregister_pmops;
5918 }
5919
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 // register net device notifier for device change notification
5921 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5922
5923 if(ret < 0)
5924 {
5925 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5926 goto err_free_power_on_lock;
5927 }
5928
5929 //Initialize the nlink service
5930 if(nl_srv_init() != 0)
5931 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305932 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 goto err_reg_netdev;
5934 }
5935
5936 //Initialize the BTC service
5937 if(btc_activate_service(pHddCtx) != 0)
5938 {
5939 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5940 goto err_nl_srv;
5941 }
5942
5943#ifdef PTT_SOCK_SVC_ENABLE
5944 //Initialize the PTT service
5945 if(ptt_sock_activate_svc(pHddCtx) != 0)
5946 {
5947 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5948 goto err_nl_srv;
5949 }
5950#endif
5951
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005955 /* Action frame registered in one adapter which will
5956 * applicable to all interfaces
5957 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005958 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005959 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005960
5961 mutex_init(&pHddCtx->sap_lock);
5962
5963 pHddCtx->isLoadUnloadInProgress = FALSE;
5964
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005965#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005966#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5967 /* Initialize the wake lcok */
5968 wake_lock_init(&pHddCtx->rx_wake_lock,
5969 WAKE_LOCK_SUSPEND,
5970 "qcom_rx_wakelock");
5971#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005972 /* Initialize the wake lcok */
5973 wake_lock_init(&pHddCtx->sap_wake_lock,
5974 WAKE_LOCK_SUSPEND,
5975 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005976#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005977
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005978 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5979 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005980
5981 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5982 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305983
Jeff Johnsone7245742012-09-05 17:12:55 -07005984 // Initialize the restart logic
5985 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305986
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005987 //Register the traffic monitor timer now
5988 if ( pHddCtx->cfg_ini->dynSplitscan)
5989 {
5990 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
5991 VOS_TIMER_TYPE_SW,
5992 hdd_tx_rx_pkt_cnt_stat_timer_handler,
5993 (void *)pHddCtx);
5994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005995 goto success;
5996
5997err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005998#ifdef WLAN_KD_READY_NOTIFIER
5999 nl_srv_exit(pHddCtx->ptt_pid);
6000#else
Jeff Johnson295189b2012-06-20 16:38:30 -07006001 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006002#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07006003err_reg_netdev:
6004 unregister_netdevice_notifier(&hdd_netdev_notifier);
6005
6006err_free_power_on_lock:
6007 free_riva_power_on_lock("wlan");
6008
6009err_unregister_pmops:
6010 hddDevTmUnregisterNotifyCallback(pHddCtx);
6011 hddDeregisterPmOps(pHddCtx);
6012
Yue Ma0d4891e2013-08-06 17:01:45 -07006013 hdd_debugfs_exit(pHddCtx);
6014
Jeff Johnson295189b2012-06-20 16:38:30 -07006015#ifdef WLAN_BTAMP_FEATURE
6016err_bap_stop:
6017 WLANBAP_Stop(pVosContext);
6018#endif
6019
6020#ifdef WLAN_BTAMP_FEATURE
6021err_bap_close:
6022 WLANBAP_Close(pVosContext);
6023#endif
6024
Jeff Johnson295189b2012-06-20 16:38:30 -07006025err_close_adapter:
6026 hdd_close_all_adapters( pHddCtx );
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306027 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
6029err_vosstop:
6030 vos_stop(pVosContext);
6031
6032err_vosclose:
6033 status = vos_sched_close( pVosContext );
6034 if (!VOS_IS_STATUS_SUCCESS(status)) {
6035 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6036 "%s: Failed to close VOSS Scheduler", __func__);
6037 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6038 }
6039 vos_close(pVosContext );
6040
Jeff Johnson295189b2012-06-20 16:38:30 -07006041err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006042 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006043
6044err_wdclose:
6045 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6046 vos_watchdog_close(pVosContext);
6047
Jeff Johnson295189b2012-06-20 16:38:30 -07006048err_config:
6049 kfree(pHddCtx->cfg_ini);
6050 pHddCtx->cfg_ini= NULL;
6051
6052err_free_hdd_context:
6053 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 wiphy_free(wiphy) ;
6055 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006056 VOS_BUG(1);
6057
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006058 if (hdd_is_ssr_required())
6059 {
6060 /* WDI timeout had happened during load, so SSR is needed here */
6061 subsystem_restart("wcnss");
6062 msleep(5000);
6063 }
6064 hdd_set_ssr_required (VOS_FALSE);
6065
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006066 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006067
6068success:
6069 EXIT();
6070 return 0;
6071}
6072
6073/**---------------------------------------------------------------------------
6074
Jeff Johnson32d95a32012-09-10 13:15:23 -07006075 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006076
Jeff Johnson32d95a32012-09-10 13:15:23 -07006077 This is the driver entry point - called in different timeline depending
6078 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006079
6080 \param - None
6081
6082 \return - 0 for success, non zero for failure
6083
6084 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006085static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006086{
6087 VOS_STATUS status;
6088 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 struct device *dev = NULL;
6090 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006091#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6092 int max_retries = 0;
6093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006094
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306095#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6096 vos_wconn_trace_init();
6097#endif
6098
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 ENTER();
6100
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006101#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006102 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006103#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006104
6105 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6106 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6107
6108 //Power Up Libra WLAN card first if not already powered up
6109 status = vos_chipPowerUp(NULL,NULL,NULL);
6110 if (!VOS_IS_STATUS_SUCCESS(status))
6111 {
6112 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6113 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306114#ifdef WLAN_OPEN_SOURCE
6115 wake_lock_destroy(&wlan_wake_lock);
6116#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006117 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 }
6119
Jeff Johnson295189b2012-06-20 16:38:30 -07006120#ifdef ANI_BUS_TYPE_PCI
6121
6122 dev = wcnss_wlan_get_device();
6123
6124#endif // ANI_BUS_TYPE_PCI
6125
6126#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006127
6128#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6129 /* wait until WCNSS driver downloads NV */
6130 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6131 msleep(1000);
6132 }
6133 if (max_retries >= 5) {
6134 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306135#ifdef WLAN_OPEN_SOURCE
6136 wake_lock_destroy(&wlan_wake_lock);
6137#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006138 return -ENODEV;
6139 }
6140#endif
6141
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 dev = wcnss_wlan_get_device();
6143#endif // ANI_BUS_TYPE_PLATFORM
6144
6145
6146 do {
6147 if (NULL == dev) {
6148 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6149 ret_status = -1;
6150 break;
6151 }
6152
6153#ifdef MEMORY_DEBUG
6154 vos_mem_init();
6155#endif
6156
6157#ifdef TIMER_MANAGER
6158 vos_timer_manager_init();
6159#endif
6160
6161 /* Preopen VOSS so that it is ready to start at least SAL */
6162 status = vos_preOpen(&pVosContext);
6163
6164 if (!VOS_IS_STATUS_SUCCESS(status))
6165 {
6166 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6167 ret_status = -1;
6168 break;
6169 }
6170
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006171#ifndef MODULE
6172 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6173 */
6174 hdd_set_conparam((v_UINT_t)con_mode);
6175#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006176
6177 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006178 if (hdd_wlan_startup(dev))
6179 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006181 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006182 vos_preClose( &pVosContext );
6183 ret_status = -1;
6184 break;
6185 }
6186
6187 /* Cancel the vote for XO Core ON
6188 * This is done here for safety purposes in case we re-initialize without turning
6189 * it OFF in any error scenario.
6190 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006191 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006193 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006194 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6195 {
6196 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6197 " Power consumed will be high\n");
6198 }
6199 } while (0);
6200
6201 if (0 != ret_status)
6202 {
6203 //Assert Deep sleep signal now to put Libra HW in lowest power state
6204 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6205 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6206
6207 //Vote off any PMIC voltage supplies
6208 vos_chipPowerDown(NULL, NULL, NULL);
6209#ifdef TIMER_MANAGER
6210 vos_timer_exit();
6211#endif
6212#ifdef MEMORY_DEBUG
6213 vos_mem_exit();
6214#endif
6215
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006216#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006218#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006219 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6220 }
6221 else
6222 {
6223 //Send WLAN UP indication to Nlink Service
6224 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6225
6226 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 }
6228
6229 EXIT();
6230
6231 return ret_status;
6232}
6233
Jeff Johnson32d95a32012-09-10 13:15:23 -07006234/**---------------------------------------------------------------------------
6235
6236 \brief hdd_module_init() - Init Function
6237
6238 This is the driver entry point (invoked when module is loaded using insmod)
6239
6240 \param - None
6241
6242 \return - 0 for success, non zero for failure
6243
6244 --------------------------------------------------------------------------*/
6245#ifdef MODULE
6246static int __init hdd_module_init ( void)
6247{
6248 return hdd_driver_init();
6249}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006250#else /* #ifdef MODULE */
6251static int __init hdd_module_init ( void)
6252{
6253 /* Driver initialization is delayed to fwpath_changed_handler */
6254 return 0;
6255}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006256#endif /* #ifdef MODULE */
6257
Jeff Johnson295189b2012-06-20 16:38:30 -07006258
6259/**---------------------------------------------------------------------------
6260
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006261 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006262
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006263 This is the driver exit point (invoked when module is unloaded using rmmod
6264 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006265
6266 \param - None
6267
6268 \return - None
6269
6270 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006271static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006272{
6273 hdd_context_t *pHddCtx = NULL;
6274 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006275 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006276
6277 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6278
6279 //Get the global vos context
6280 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6281
6282 if(!pVosContext)
6283 {
6284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6285 goto done;
6286 }
6287
6288 //Get the HDD context.
6289 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6290
6291 if(!pHddCtx)
6292 {
6293 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6294 }
6295 else
6296 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006297 while(isWDresetInProgress()) {
6298 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6299 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006300 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006301
6302 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6303 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6304 "%s:SSR never completed, fatal error", __func__);
6305 VOS_BUG(0);
6306 }
6307 }
6308
Jeff Johnson295189b2012-06-20 16:38:30 -07006309
6310 pHddCtx->isLoadUnloadInProgress = TRUE;
6311 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6312
6313 //Do all the cleanup before deregistering the driver
6314 hdd_wlan_exit(pHddCtx);
6315 }
6316
Jeff Johnson295189b2012-06-20 16:38:30 -07006317 vos_preClose( &pVosContext );
6318
6319#ifdef TIMER_MANAGER
6320 vos_timer_exit();
6321#endif
6322#ifdef MEMORY_DEBUG
6323 vos_mem_exit();
6324#endif
6325
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306326#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6327 vos_wconn_trace_exit();
6328#endif
6329
Jeff Johnson295189b2012-06-20 16:38:30 -07006330done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006331#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006333#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006334 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6335}
6336
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006337/**---------------------------------------------------------------------------
6338
6339 \brief hdd_module_exit() - Exit function
6340
6341 This is the driver exit point (invoked when module is unloaded using rmmod)
6342
6343 \param - None
6344
6345 \return - None
6346
6347 --------------------------------------------------------------------------*/
6348static void __exit hdd_module_exit(void)
6349{
6350 hdd_driver_exit();
6351}
6352
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006353#ifdef MODULE
6354static int fwpath_changed_handler(const char *kmessage,
6355 struct kernel_param *kp)
6356{
Jeff Johnson76052702013-04-16 13:55:05 -07006357 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006358}
6359
6360static int con_mode_handler(const char *kmessage,
6361 struct kernel_param *kp)
6362{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006363 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006364}
6365#else /* #ifdef MODULE */
6366/**---------------------------------------------------------------------------
6367
Jeff Johnson76052702013-04-16 13:55:05 -07006368 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006369
Jeff Johnson76052702013-04-16 13:55:05 -07006370 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006371 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006372 - invoked when module parameter fwpath is modified from userspace to signal
6373 initializing the WLAN driver or when con_mode is modified from userspace
6374 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006375
6376 \return - 0 for success, non zero for failure
6377
6378 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006379static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006380{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006381 int ret_status;
6382
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006383 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006384 ret_status = hdd_driver_init();
6385 wlan_hdd_inited = ret_status ? 0 : 1;
6386 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006387 }
6388
6389 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006390
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006391 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006392
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006393 ret_status = hdd_driver_init();
6394 wlan_hdd_inited = ret_status ? 0 : 1;
6395 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006396}
6397
Jeff Johnson295189b2012-06-20 16:38:30 -07006398/**---------------------------------------------------------------------------
6399
Jeff Johnson76052702013-04-16 13:55:05 -07006400 \brief fwpath_changed_handler() - Handler Function
6401
6402 Handle changes to the fwpath parameter
6403
6404 \return - 0 for success, non zero for failure
6405
6406 --------------------------------------------------------------------------*/
6407static int fwpath_changed_handler(const char *kmessage,
6408 struct kernel_param *kp)
6409{
6410 int ret;
6411
6412 ret = param_set_copystring(kmessage, kp);
6413 if (0 == ret)
6414 ret = kickstart_driver();
6415 return ret;
6416}
6417
6418/**---------------------------------------------------------------------------
6419
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006420 \brief con_mode_handler() -
6421
6422 Handler function for module param con_mode when it is changed by userspace
6423 Dynamically linked - do nothing
6424 Statically linked - exit and init driver, as in rmmod and insmod
6425
Jeff Johnson76052702013-04-16 13:55:05 -07006426 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006427
Jeff Johnson76052702013-04-16 13:55:05 -07006428 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006429
6430 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006431static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006432{
Jeff Johnson76052702013-04-16 13:55:05 -07006433 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006434
Jeff Johnson76052702013-04-16 13:55:05 -07006435 ret = param_set_int(kmessage, kp);
6436 if (0 == ret)
6437 ret = kickstart_driver();
6438 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006439}
6440#endif /* #ifdef MODULE */
6441
6442/**---------------------------------------------------------------------------
6443
Jeff Johnson295189b2012-06-20 16:38:30 -07006444 \brief hdd_get_conparam() -
6445
6446 This is the driver exit point (invoked when module is unloaded using rmmod)
6447
6448 \param - None
6449
6450 \return - tVOS_CON_MODE
6451
6452 --------------------------------------------------------------------------*/
6453tVOS_CON_MODE hdd_get_conparam ( void )
6454{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006455#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006456 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006457#else
6458 return (tVOS_CON_MODE)curr_con_mode;
6459#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006460}
6461void hdd_set_conparam ( v_UINT_t newParam )
6462{
6463 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006464#ifndef MODULE
6465 curr_con_mode = con_mode;
6466#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006467}
6468/**---------------------------------------------------------------------------
6469
6470 \brief hdd_softap_sta_deauth() - function
6471
6472 This to take counter measure to handle deauth req from HDD
6473
6474 \param - pAdapter - Pointer to the HDD
6475
6476 \param - enable - boolean value
6477
6478 \return - None
6479
6480 --------------------------------------------------------------------------*/
6481
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006482VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006483{
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006485 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006486
6487 ENTER();
6488
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006489 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6490 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006491
6492 //Ignore request to deauth bcmc station
6493 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006494 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006495
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006496 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006497
6498 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006499 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006500}
6501
6502/**---------------------------------------------------------------------------
6503
6504 \brief hdd_softap_sta_disassoc() - function
6505
6506 This to take counter measure to handle deauth req from HDD
6507
6508 \param - pAdapter - Pointer to the HDD
6509
6510 \param - enable - boolean value
6511
6512 \return - None
6513
6514 --------------------------------------------------------------------------*/
6515
6516void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6517{
6518 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6519
6520 ENTER();
6521
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306522 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006523
6524 //Ignore request to disassoc bcmc station
6525 if( pDestMacAddress[0] & 0x1 )
6526 return;
6527
6528 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6529}
6530
6531void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6532{
6533 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6534
6535 ENTER();
6536
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306537 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006538
6539 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6540}
6541
Jeff Johnson295189b2012-06-20 16:38:30 -07006542/**---------------------------------------------------------------------------
6543 *
6544 * \brief hdd_get__concurrency_mode() -
6545 *
6546 *
6547 * \param - None
6548 *
6549 * \return - CONCURRENCY MODE
6550 *
6551 * --------------------------------------------------------------------------*/
6552tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6553{
6554 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6555 hdd_context_t *pHddCtx;
6556
6557 if (NULL != pVosContext)
6558 {
6559 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6560 if (NULL != pHddCtx)
6561 {
6562 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6563 }
6564 }
6565
6566 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006567 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006568 return VOS_STA;
6569}
6570
6571/* Decide whether to allow/not the apps power collapse.
6572 * Allow apps power collapse if we are in connected state.
6573 * if not, allow only if we are in IMPS */
6574v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6575{
6576 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006577 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006578 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006579 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6580 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6581 hdd_adapter_t *pAdapter = NULL;
6582 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006583 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006584
Jeff Johnson295189b2012-06-20 16:38:30 -07006585 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6586 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006587
Yathish9f22e662012-12-10 14:21:35 -08006588 concurrent_state = hdd_get_concurrency_mode();
6589
6590#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6591 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6592 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6593 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6594 return TRUE;
6595#endif
6596
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 /*loop through all adapters. TBD fix for Concurrency */
6598 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6599 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6600 {
6601 pAdapter = pAdapterNode->pAdapter;
6602 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6603 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6604 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006605 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006607 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006608 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6609 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006610 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006611 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006612 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6613 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006614 return FALSE;
6615 }
6616 }
6617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6618 pAdapterNode = pNext;
6619 }
6620 return TRUE;
6621}
6622
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006623/* Decides whether to send suspend notification to Riva
6624 * if any adapter is in BMPS; then it is required */
6625v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6626{
6627 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6628 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6629
6630 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6631 {
6632 return TRUE;
6633 }
6634 return FALSE;
6635}
6636
Jeff Johnson295189b2012-06-20 16:38:30 -07006637void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6638{
6639 switch(mode)
6640 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006641 case VOS_STA_MODE:
6642 case VOS_P2P_CLIENT_MODE:
6643 case VOS_P2P_GO_MODE:
6644 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006645 pHddCtx->concurrency_mode |= (1 << mode);
6646 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006647 break;
6648 default:
6649 break;
6650
6651 }
6652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6653 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6654}
6655
6656
6657void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6658{
6659 switch(mode)
6660 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006661 case VOS_STA_MODE:
6662 case VOS_P2P_CLIENT_MODE:
6663 case VOS_P2P_GO_MODE:
6664 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006665 pHddCtx->no_of_sessions[mode]--;
6666 if (!(pHddCtx->no_of_sessions[mode]))
6667 pHddCtx->concurrency_mode &= (~(1 << mode));
6668 break;
6669 default:
6670 break;
6671 }
6672 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6673 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6674}
6675
Jeff Johnsone7245742012-09-05 17:12:55 -07006676/**---------------------------------------------------------------------------
6677 *
6678 * \brief wlan_hdd_restart_init
6679 *
6680 * This function initalizes restart timer/flag. An internal function.
6681 *
6682 * \param - pHddCtx
6683 *
6684 * \return - None
6685 *
6686 * --------------------------------------------------------------------------*/
6687
6688static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6689{
6690 /* Initialize */
6691 pHddCtx->hdd_restart_retries = 0;
6692 atomic_set(&pHddCtx->isRestartInProgress, 0);
6693 vos_timer_init(&pHddCtx->hdd_restart_timer,
6694 VOS_TIMER_TYPE_SW,
6695 wlan_hdd_restart_timer_cb,
6696 pHddCtx);
6697}
6698/**---------------------------------------------------------------------------
6699 *
6700 * \brief wlan_hdd_restart_deinit
6701 *
6702 * This function cleans up the resources used. An internal function.
6703 *
6704 * \param - pHddCtx
6705 *
6706 * \return - None
6707 *
6708 * --------------------------------------------------------------------------*/
6709
6710static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6711{
6712
6713 VOS_STATUS vos_status;
6714 /* Block any further calls */
6715 atomic_set(&pHddCtx->isRestartInProgress, 1);
6716 /* Cleanup */
6717 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6718 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006719 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006720 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6721 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006722 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006723
6724}
6725
6726/**---------------------------------------------------------------------------
6727 *
6728 * \brief wlan_hdd_framework_restart
6729 *
6730 * This function uses a cfg80211 API to start a framework initiated WLAN
6731 * driver module unload/load.
6732 *
6733 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6734 *
6735 *
6736 * \param - pHddCtx
6737 *
6738 * \return - VOS_STATUS_SUCCESS: Success
6739 * VOS_STATUS_E_EMPTY: Adapter is Empty
6740 * VOS_STATUS_E_NOMEM: No memory
6741
6742 * --------------------------------------------------------------------------*/
6743
6744static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6745{
6746 VOS_STATUS status = VOS_STATUS_SUCCESS;
6747 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006748 int len = (sizeof (struct ieee80211_mgmt));
6749 struct ieee80211_mgmt *mgmt = NULL;
6750
6751 /* Prepare the DEAUTH managment frame with reason code */
6752 mgmt = kzalloc(len, GFP_KERNEL);
6753 if(mgmt == NULL)
6754 {
6755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6756 "%s: memory allocation failed (%d bytes)", __func__, len);
6757 return VOS_STATUS_E_NOMEM;
6758 }
6759 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006760
6761 /* Iterate over all adapters/devices */
6762 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6763 do
6764 {
6765 if( (status == VOS_STATUS_SUCCESS) &&
6766 pAdapterNode &&
6767 pAdapterNode->pAdapter)
6768 {
6769 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6770 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6771 pAdapterNode->pAdapter->dev->name,
6772 pAdapterNode->pAdapter->device_mode,
6773 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006774 /*
6775 * CFG80211 event to restart the driver
6776 *
6777 * 'cfg80211_send_unprot_deauth' sends a
6778 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6779 * of SME(Linux Kernel) state machine.
6780 *
6781 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6782 * the driver.
6783 *
6784 */
6785
6786 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006787 }
6788 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6789 pAdapterNode = pNext;
6790 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6791
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006792
6793 /* Free the allocated management frame */
6794 kfree(mgmt);
6795
Jeff Johnsone7245742012-09-05 17:12:55 -07006796 /* Retry until we unload or reach max count */
6797 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6798 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6799
6800 return status;
6801
6802}
6803/**---------------------------------------------------------------------------
6804 *
6805 * \brief wlan_hdd_restart_timer_cb
6806 *
6807 * Restart timer callback. An internal function.
6808 *
6809 * \param - User data:
6810 *
6811 * \return - None
6812 *
6813 * --------------------------------------------------------------------------*/
6814
6815void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6816{
6817 hdd_context_t *pHddCtx = usrDataForCallback;
6818 wlan_hdd_framework_restart(pHddCtx);
6819 return;
6820
6821}
6822
6823
6824/**---------------------------------------------------------------------------
6825 *
6826 * \brief wlan_hdd_restart_driver
6827 *
6828 * This function sends an event to supplicant to restart the WLAN driver.
6829 *
6830 * This function is called from vos_wlanRestart.
6831 *
6832 * \param - pHddCtx
6833 *
6834 * \return - VOS_STATUS_SUCCESS: Success
6835 * VOS_STATUS_E_EMPTY: Adapter is Empty
6836 * VOS_STATUS_E_ALREADY: Request already in progress
6837
6838 * --------------------------------------------------------------------------*/
6839VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6840{
6841 VOS_STATUS status = VOS_STATUS_SUCCESS;
6842
6843 /* A tight check to make sure reentrancy */
6844 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6845 {
6846 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6847 "%s: WLAN restart is already in progress", __func__);
6848
6849 return VOS_STATUS_E_ALREADY;
6850 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006851 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006852#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006853 wcnss_reset_intr();
6854#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006855
Jeff Johnsone7245742012-09-05 17:12:55 -07006856 return status;
6857}
6858
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006859/*
6860 * API to find if there is any STA or P2P-Client is connected
6861 */
6862VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6863{
6864 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6865}
Jeff Johnsone7245742012-09-05 17:12:55 -07006866
Jeff Johnson295189b2012-06-20 16:38:30 -07006867//Register the module init/exit functions
6868module_init(hdd_module_init);
6869module_exit(hdd_module_exit);
6870
6871MODULE_LICENSE("Dual BSD/GPL");
6872MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6873MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6874
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006875module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6876 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006877
Jeff Johnson76052702013-04-16 13:55:05 -07006878module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006879 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);