blob: bcb02c05901c732e879636ddf66c05b8bd0a55e8 [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;
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530607 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -0700608
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700610 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611
612 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
613 {
614 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
615 sizeof(tSirMacAddr)))
616 {
617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700618 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 ret = -EFAULT;
620 }
621 }
Amar Singhal0974e402013-02-12 14:27:46 -0800622 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 {
Amar Singhal0974e402013-02-12 14:27:46 -0800624 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626
Jeff Johnson295189b2012-06-20 16:38:30 -0700627 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800628
629 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700630 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800632 "%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 -0700633 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800634 ret = hdd_setBand_helper(dev, ptr);
635 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
637 {
638 char *country_code;
639
640 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700641
642 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530643 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700644 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530645 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700646 if( 0 != ret )
647 {
648 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
649 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
650
651 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530652 /* If you get a 00 country code it means you are world roaming.
653 In case of world roaming, country code should be updated by
654 DRIVER COUNTRY */
655 if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode,
656 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0)
657 {
658 regulatory_hint(wiphy, "00");
659 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700660 }
661 /*
662 command should be a string having format
663 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
664 */
Amar Singhal0974e402013-02-12 14:27:46 -0800665 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700666 {
Amar Singhal0974e402013-02-12 14:27:46 -0800667 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700668
669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700670 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700671
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800672 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700673 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800674 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
675 {
676 int suspend = 0;
677 tANI_U8 *ptr = (tANI_U8*)command + 15;
678
679 suspend = *ptr - '0';
680 hdd_set_wlan_suspend_mode(suspend);
681 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800682#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
683 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
684 {
685 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700686 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800687 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
688 eHalStatus status = eHAL_STATUS_SUCCESS;
689
690 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
691 value = value + 15;
692
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700693 /* Convert the value from ascii to integer */
694 ret = kstrtos8(value, 10, &rssi);
695 if (ret < 0)
696 {
697 /* If the input value is greater than max value of datatype, then also
698 kstrtou8 fails */
699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
700 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
701 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
702 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
703 ret = -EINVAL;
704 goto exit;
705 }
706
Srinivas Girigowdade697412013-02-14 16:31:48 -0800707 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700708
Srinivas Girigowdade697412013-02-14 16:31:48 -0800709 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
710 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
711 {
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
713 "Neighbor lookup threshold value %d is out of range"
714 " (Min: %d Max: %d)", lookUpThreshold,
715 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
716 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
717 ret = -EINVAL;
718 goto exit;
719 }
720
721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
722 "%s: Received Command to Set Roam trigger"
723 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
724
725 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
726 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
727 if (eHAL_STATUS_SUCCESS != status)
728 {
729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
730 "%s: Failed to set roam trigger, try again", __func__);
731 ret = -EPERM;
732 goto exit;
733 }
734
735 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
736 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
737 }
738 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
739 {
740 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
741 int rssi = (-1) * lookUpThreshold;
742 char extra[32];
743 tANI_U8 len = 0;
744
745 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
746 if (copy_to_user(priv_data.buf, &extra, len + 1))
747 {
748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
749 "%s: failed to copy data to user buffer", __func__);
750 ret = -EFAULT;
751 goto exit;
752 }
753 }
754 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
755 {
756 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700757 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700758 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700759
Srinivas Girigowdade697412013-02-14 16:31:48 -0800760 /* input refresh period is in terms of seconds */
761 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
762 value = value + 18;
763 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700764 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800765 if (ret < 0)
766 {
767 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700768 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700770 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800771 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700772 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
773 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800774 ret = -EINVAL;
775 goto exit;
776 }
777
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700778 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
779 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800780 {
781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700782 "Roam scan period value %d is out of range"
783 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700784 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
785 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800786 ret = -EINVAL;
787 goto exit;
788 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700789 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800790
791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
792 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700793 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800794
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700795 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
796 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800797 }
798 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
799 {
800 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
801 char extra[32];
802 tANI_U8 len = 0;
803
804 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
805 /* Returned value is in units of seconds */
806 if (copy_to_user(priv_data.buf, &extra, len + 1))
807 {
808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
809 "%s: failed to copy data to user buffer", __func__);
810 ret = -EFAULT;
811 goto exit;
812 }
813 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700814 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
815 {
816 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700817 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700818 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700819
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700820 /* input refresh period is in terms of seconds */
821 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
822 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700823
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700826 if (ret < 0)
827 {
828 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700831 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700832 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700833 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
834 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
835 ret = -EINVAL;
836 goto exit;
837 }
838
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700839 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
840 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
841 {
842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
843 "Neighbor scan results refresh period value %d is out of range"
844 " (Min: %d Max: %d)", roamScanRefreshPeriod,
845 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
846 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
847 ret = -EINVAL;
848 goto exit;
849 }
850 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
851
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
853 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700854 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700855
856 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
857 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
858 }
859 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
860 {
861 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
862 char extra[32];
863 tANI_U8 len = 0;
864
865 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
866 /* Returned value is in units of seconds */
867 if (copy_to_user(priv_data.buf, &extra, len + 1))
868 {
869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
870 "%s: failed to copy data to user buffer", __func__);
871 ret = -EFAULT;
872 goto exit;
873 }
874 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700875#ifdef FEATURE_WLAN_LFR
876 /* SETROAMMODE */
877 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
878 {
879 tANI_U8 *value = command;
880 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
881
882 /* Move pointer to ahead of SETROAMMODE<delimiter> */
883 value = value + SIZE_OF_SETROAMMODE + 1;
884
885 /* Convert the value from ascii to integer */
886 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
887 if (ret < 0)
888 {
889 /* If the input value is greater than max value of datatype, then also
890 kstrtou8 fails */
891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
892 "%s: kstrtou8 failed range [%d - %d]", __func__,
893 CFG_LFR_FEATURE_ENABLED_MIN,
894 CFG_LFR_FEATURE_ENABLED_MAX);
895 ret = -EINVAL;
896 goto exit;
897 }
898 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
899 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
900 {
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
902 "Roam Mode value %d is out of range"
903 " (Min: %d Max: %d)", roamMode,
904 CFG_LFR_FEATURE_ENABLED_MIN,
905 CFG_LFR_FEATURE_ENABLED_MAX);
906 ret = -EINVAL;
907 goto exit;
908 }
909
910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
911 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
912 /*
913 * Note that
914 * SETROAMMODE 0 is to enable LFR while
915 * SETROAMMODE 1 is to disable LFR, but
916 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
917 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
918 */
919 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
920 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
921 else
922 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
923
924 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
925 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
926 }
927 /* GETROAMMODE */
928 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
929 {
930 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
931 char extra[32];
932 tANI_U8 len = 0;
933
934 /*
935 * roamMode value shall be inverted because the sementics is different.
936 */
937 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
938 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
939 else
940 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
941
942 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
943 if (copy_to_user(priv_data.buf, &extra, len + 1))
944 {
945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
946 "%s: failed to copy data to user buffer", __func__);
947 ret = -EFAULT;
948 goto exit;
949 }
950 }
951#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800952#endif
953#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
954 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
955 {
956 tANI_U8 *value = command;
957 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
958
959 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
960 value = value + 13;
961 /* Convert the value from ascii to integer */
962 ret = kstrtou8(value, 10, &roamRssiDiff);
963 if (ret < 0)
964 {
965 /* If the input value is greater than max value of datatype, then also
966 kstrtou8 fails */
967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
968 "%s: kstrtou8 failed range [%d - %d]", __func__,
969 CFG_ROAM_RSSI_DIFF_MIN,
970 CFG_ROAM_RSSI_DIFF_MAX);
971 ret = -EINVAL;
972 goto exit;
973 }
974
975 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
976 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
977 {
978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
979 "Roam rssi diff value %d is out of range"
980 " (Min: %d Max: %d)", roamRssiDiff,
981 CFG_ROAM_RSSI_DIFF_MIN,
982 CFG_ROAM_RSSI_DIFF_MAX);
983 ret = -EINVAL;
984 goto exit;
985 }
986
987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
988 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
989
990 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
991 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
992 }
993 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
994 {
995 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
996 char extra[32];
997 tANI_U8 len = 0;
998
999 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1000 if (copy_to_user(priv_data.buf, &extra, len + 1))
1001 {
1002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1003 "%s: failed to copy data to user buffer", __func__);
1004 ret = -EFAULT;
1005 goto exit;
1006 }
1007 }
1008#endif
1009#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1010 else if (strncmp(command, "GETBAND", 7) == 0)
1011 {
1012 int band = -1;
1013 char extra[32];
1014 tANI_U8 len = 0;
1015 hdd_getBand_helper(pHddCtx, &band);
1016
1017 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1018 if (copy_to_user(priv_data.buf, &extra, len + 1))
1019 {
1020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1021 "%s: failed to copy data to user buffer", __func__);
1022 ret = -EFAULT;
1023 goto exit;
1024 }
1025 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001026 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1027 {
1028 tANI_U8 *value = command;
1029 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1030 tANI_U8 numChannels = 0;
1031 eHalStatus status = eHAL_STATUS_SUCCESS;
1032
1033 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1034 if (eHAL_STATUS_SUCCESS != status)
1035 {
1036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1037 "%s: Failed to parse channel list information", __func__);
1038 ret = -EINVAL;
1039 goto exit;
1040 }
1041
1042 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1043 {
1044 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1045 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1046 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1047 ret = -EINVAL;
1048 goto exit;
1049 }
1050 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1051 numChannels);
1052 if (eHAL_STATUS_SUCCESS != status)
1053 {
1054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1055 "%s: Failed to update channel list information", __func__);
1056 ret = -EINVAL;
1057 goto exit;
1058 }
1059 }
1060 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1061 {
1062 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1063 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001064 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001065 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001066 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001067
1068 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1069 ChannelList, &numChannels ))
1070 {
1071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1072 "%s: failed to get roam scan channel list", __func__);
1073 ret = -EFAULT;
1074 goto exit;
1075 }
1076 /* output channel list is of the format
1077 [Number of roam scan channels][Channel1][Channel2]... */
1078 /* copy the number of channels in the 0th index */
1079 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1080 for (j = 0; (j < numChannels); j++)
1081 {
1082 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1083 }
1084
1085 if (copy_to_user(priv_data.buf, &extra, len + 1))
1086 {
1087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1088 "%s: failed to copy data to user buffer", __func__);
1089 ret = -EFAULT;
1090 goto exit;
1091 }
1092 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001093 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1094 {
1095 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1096 char extra[32];
1097 tANI_U8 len = 0;
1098
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001099 /* Check if the features OKC/CCX/11R are supported simultaneously,
1100 then this operation is not permitted (return FAILURE) */
1101 if (ccxMode &&
1102 hdd_is_okc_mode_enabled(pHddCtx) &&
1103 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1104 {
1105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1106 "%s: OKC/CCX/11R are supported simultaneously"
1107 " hence this operation is not permitted!", __func__);
1108 ret = -EPERM;
1109 goto exit;
1110 }
1111
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001112 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1113 if (copy_to_user(priv_data.buf, &extra, len + 1))
1114 {
1115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1116 "%s: failed to copy data to user buffer", __func__);
1117 ret = -EFAULT;
1118 goto exit;
1119 }
1120 }
1121 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1122 {
1123 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1124 char extra[32];
1125 tANI_U8 len = 0;
1126
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001127 /* Check if the features OKC/CCX/11R are supported simultaneously,
1128 then this operation is not permitted (return FAILURE) */
1129 if (okcMode &&
1130 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1131 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1132 {
1133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1134 "%s: OKC/CCX/11R are supported simultaneously"
1135 " hence this operation is not permitted!", __func__);
1136 ret = -EPERM;
1137 goto exit;
1138 }
1139
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001140 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1141 if (copy_to_user(priv_data.buf, &extra, len + 1))
1142 {
1143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1144 "%s: failed to copy data to user buffer", __func__);
1145 ret = -EFAULT;
1146 goto exit;
1147 }
1148 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001149 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001150 {
1151 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1152 char extra[32];
1153 tANI_U8 len = 0;
1154
1155 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1156 if (copy_to_user(priv_data.buf, &extra, len + 1))
1157 {
1158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1159 "%s: failed to copy data to user buffer", __func__);
1160 ret = -EFAULT;
1161 goto exit;
1162 }
1163 }
1164 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1165 {
1166 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1167 char extra[32];
1168 tANI_U8 len = 0;
1169
1170 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1171 if (copy_to_user(priv_data.buf, &extra, len + 1))
1172 {
1173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1174 "%s: failed to copy data to user buffer", __func__);
1175 ret = -EFAULT;
1176 goto exit;
1177 }
1178 }
1179 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1180 {
1181 tANI_U8 *value = command;
1182 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1183
1184 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1185 value = value + 26;
1186 /* Convert the value from ascii to integer */
1187 ret = kstrtou8(value, 10, &minTime);
1188 if (ret < 0)
1189 {
1190 /* If the input value is greater than max value of datatype, then also
1191 kstrtou8 fails */
1192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1193 "%s: kstrtou8 failed range [%d - %d]", __func__,
1194 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1195 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1196 ret = -EINVAL;
1197 goto exit;
1198 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001199 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1200 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1201 {
1202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1203 "scan min channel time value %d is out of range"
1204 " (Min: %d Max: %d)", minTime,
1205 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1206 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1207 ret = -EINVAL;
1208 goto exit;
1209 }
1210
1211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1212 "%s: Received Command to change channel min time = %d", __func__, minTime);
1213
1214 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1215 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1216 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001217 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1218 {
1219 tANI_U8 *value = command;
1220 tANI_U8 channel = 0;
1221 tANI_U8 dwellTime = 0;
1222 tANI_U8 bufLen = 0;
1223 tANI_U8 *buf = NULL;
1224 tSirMacAddr targetApBssid;
1225 eHalStatus status = eHAL_STATUS_SUCCESS;
1226 struct ieee80211_channel chan;
1227 tANI_U8 finalLen = 0;
1228 tANI_U8 *finalBuf = NULL;
1229 tANI_U8 temp = 0;
1230 u64 cookie;
1231 hdd_station_ctx_t *pHddStaCtx = NULL;
1232 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1233
1234 /* if not associated, no need to send action frame */
1235 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1236 {
1237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1238 ret = -EINVAL;
1239 goto exit;
1240 }
1241
1242 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1243 &dwellTime, &buf, &bufLen);
1244 if (eHAL_STATUS_SUCCESS != status)
1245 {
1246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1247 "%s: Failed to parse send action frame data", __func__);
1248 ret = -EINVAL;
1249 goto exit;
1250 }
1251
1252 /* if the target bssid is different from currently associated AP,
1253 then no need to send action frame */
1254 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1255 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1256 {
1257 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1258 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001259 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001260 goto exit;
1261 }
1262
1263 /* if the channel number is different from operating channel then
1264 no need to send action frame */
1265 if (channel != pHddStaCtx->conn_info.operationChannel)
1266 {
1267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1268 "%s: channel(%d) is different from operating channel(%d)",
1269 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1270 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001271 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001272 goto exit;
1273 }
1274 chan.center_freq = sme_ChnToFreq(channel);
1275
1276 finalLen = bufLen + 24;
1277 finalBuf = vos_mem_malloc(finalLen);
1278 if (NULL == finalBuf)
1279 {
1280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1281 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001282 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001283 goto exit;
1284 }
1285 vos_mem_zero(finalBuf, finalLen);
1286
1287 /* Fill subtype */
1288 temp = SIR_MAC_MGMT_ACTION << 4;
1289 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1290
1291 /* Fill type */
1292 temp = SIR_MAC_MGMT_FRAME;
1293 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1294
1295 /* Fill destination address (bssid of the AP) */
1296 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1297
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001298 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001299 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1300
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001301 /* Fill BSSID (AP mac address) */
1302 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001303
1304 /* Fill received buffer from 24th address */
1305 vos_mem_copy(finalBuf + 24, buf, bufLen);
1306
Jeff Johnson11c33152013-04-16 17:52:40 -07001307 /* done with the parsed buffer */
1308 vos_mem_free(buf);
1309
Yue Maf49ba872013-08-19 12:04:25 -07001310 wlan_hdd_action( NULL,
1311#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1312 &(pAdapter->wdev),
1313#else
1314 dev,
1315#endif
1316 &chan, 0,
1317#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1318 NL80211_CHAN_HT20, 1,
1319#endif
1320 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001321 1, &cookie );
1322 vos_mem_free(finalBuf);
1323 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001324 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1325 {
1326 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1327 char extra[32];
1328 tANI_U8 len = 0;
1329
1330 /* value is interms of msec */
1331 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1332 if (copy_to_user(priv_data.buf, &extra, len + 1))
1333 {
1334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1335 "%s: failed to copy data to user buffer", __func__);
1336 ret = -EFAULT;
1337 goto exit;
1338 }
1339 }
1340 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1341 {
1342 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001343 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001344 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001345
1346 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1347 value = value + 19;
1348 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001349 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001350 if (ret < 0)
1351 {
1352 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001353 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001355 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001356 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1357 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1358 ret = -EINVAL;
1359 goto exit;
1360 }
1361
1362 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1363 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1364 {
1365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1366 "lfr mode value %d is out of range"
1367 " (Min: %d Max: %d)", maxTime,
1368 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1369 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1370 ret = -EINVAL;
1371 goto exit;
1372 }
1373
1374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1375 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1376
1377 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001378
1379 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1380 * where RFS is the RF Switching time. It is twice RFS to consider the
1381 * time to go off channel and return to the home channel. */
1382 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1383 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1384 {
1385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1386 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1387 " Hence enforcing home away time to disable (0)",
1388 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1389 homeAwayTime = 0;
1390 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1391 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1392 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001393 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1394 }
1395 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1396 {
1397 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1398 char extra[32];
1399 tANI_U8 len = 0;
1400
1401 /* value is interms of msec */
1402 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1403 if (copy_to_user(priv_data.buf, &extra, len + 1))
1404 {
1405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1406 "%s: failed to copy data to user buffer", __func__);
1407 ret = -EFAULT;
1408 goto exit;
1409 }
1410 }
1411 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1412 {
1413 tANI_U8 *value = command;
1414 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1415
1416 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1417 value = value + 16;
1418 /* Convert the value from ascii to integer */
1419 ret = kstrtou16(value, 10, &val);
1420 if (ret < 0)
1421 {
1422 /* If the input value is greater than max value of datatype, then also
1423 kstrtou16 fails */
1424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1425 "%s: kstrtou16 failed range [%d - %d]", __func__,
1426 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1427 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1428 ret = -EINVAL;
1429 goto exit;
1430 }
1431
1432 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1433 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1434 {
1435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1436 "scan home time value %d is out of range"
1437 " (Min: %d Max: %d)", val,
1438 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1439 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1440 ret = -EINVAL;
1441 goto exit;
1442 }
1443
1444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1445 "%s: Received Command to change scan home time = %d", __func__, val);
1446
1447 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1448 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1449 }
1450 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1451 {
1452 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1453 char extra[32];
1454 tANI_U8 len = 0;
1455
1456 /* value is interms of msec */
1457 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1458 if (copy_to_user(priv_data.buf, &extra, len + 1))
1459 {
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1461 "%s: failed to copy data to user buffer", __func__);
1462 ret = -EFAULT;
1463 goto exit;
1464 }
1465 }
1466 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1467 {
1468 tANI_U8 *value = command;
1469 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1470
1471 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1472 value = value + 17;
1473 /* Convert the value from ascii to integer */
1474 ret = kstrtou8(value, 10, &val);
1475 if (ret < 0)
1476 {
1477 /* If the input value is greater than max value of datatype, then also
1478 kstrtou8 fails */
1479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1480 "%s: kstrtou8 failed range [%d - %d]", __func__,
1481 CFG_ROAM_INTRA_BAND_MIN,
1482 CFG_ROAM_INTRA_BAND_MAX);
1483 ret = -EINVAL;
1484 goto exit;
1485 }
1486
1487 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1488 (val > CFG_ROAM_INTRA_BAND_MAX))
1489 {
1490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1491 "intra band mode value %d is out of range"
1492 " (Min: %d Max: %d)", val,
1493 CFG_ROAM_INTRA_BAND_MIN,
1494 CFG_ROAM_INTRA_BAND_MAX);
1495 ret = -EINVAL;
1496 goto exit;
1497 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1499 "%s: Received Command to change intra band = %d", __func__, val);
1500
1501 pHddCtx->cfg_ini->nRoamIntraBand = val;
1502 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1503 }
1504 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1505 {
1506 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1507 char extra[32];
1508 tANI_U8 len = 0;
1509
1510 /* value is interms of msec */
1511 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1512 if (copy_to_user(priv_data.buf, &extra, len + 1))
1513 {
1514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1515 "%s: failed to copy data to user buffer", __func__);
1516 ret = -EFAULT;
1517 goto exit;
1518 }
1519 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001520 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1521 {
1522 tANI_U8 *value = command;
1523 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1524
1525 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1526 value = value + 15;
1527 /* Convert the value from ascii to integer */
1528 ret = kstrtou8(value, 10, &nProbes);
1529 if (ret < 0)
1530 {
1531 /* If the input value is greater than max value of datatype, then also
1532 kstrtou8 fails */
1533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1534 "%s: kstrtou8 failed range [%d - %d]", __func__,
1535 CFG_ROAM_SCAN_N_PROBES_MIN,
1536 CFG_ROAM_SCAN_N_PROBES_MAX);
1537 ret = -EINVAL;
1538 goto exit;
1539 }
1540
1541 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1542 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1543 {
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1545 "NProbes value %d is out of range"
1546 " (Min: %d Max: %d)", nProbes,
1547 CFG_ROAM_SCAN_N_PROBES_MIN,
1548 CFG_ROAM_SCAN_N_PROBES_MAX);
1549 ret = -EINVAL;
1550 goto exit;
1551 }
1552
1553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1554 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1555
1556 pHddCtx->cfg_ini->nProbes = nProbes;
1557 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1558 }
1559 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1560 {
1561 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1562 char extra[32];
1563 tANI_U8 len = 0;
1564
1565 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1566 if (copy_to_user(priv_data.buf, &extra, len + 1))
1567 {
1568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1569 "%s: failed to copy data to user buffer", __func__);
1570 ret = -EFAULT;
1571 goto exit;
1572 }
1573 }
1574 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1575 {
1576 tANI_U8 *value = command;
1577 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001578 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001579
1580 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1581 /* input value is in units of msec */
1582 value = value + 20;
1583 /* Convert the value from ascii to integer */
1584 ret = kstrtou16(value, 10, &homeAwayTime);
1585 if (ret < 0)
1586 {
1587 /* If the input value is greater than max value of datatype, then also
1588 kstrtou8 fails */
1589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1590 "%s: kstrtou8 failed range [%d - %d]", __func__,
1591 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1592 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1593 ret = -EINVAL;
1594 goto exit;
1595 }
1596
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001597 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1598 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1599 {
1600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1601 "homeAwayTime value %d is out of range"
1602 " (Min: %d Max: %d)", homeAwayTime,
1603 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1604 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1605 ret = -EINVAL;
1606 goto exit;
1607 }
1608
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1610 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1611
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001612 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1613 * where RFS is the RF Switching time. It is twice RFS to consider the
1614 * time to go off channel and return to the home channel. */
1615 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1616 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1617 {
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1619 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1620 " Hence enforcing home away time to disable (0)",
1621 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1622 homeAwayTime = 0;
1623 }
1624
1625 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1626 {
1627 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1628 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1629 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001630 }
1631 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1632 {
1633 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1634 char extra[32];
1635 tANI_U8 len = 0;
1636
1637 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1638 if (copy_to_user(priv_data.buf, &extra, len + 1))
1639 {
1640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1641 "%s: failed to copy data to user buffer", __func__);
1642 ret = -EFAULT;
1643 goto exit;
1644 }
1645 }
1646 else if (strncmp(command, "REASSOC", 7) == 0)
1647 {
1648 tANI_U8 *value = command;
1649 tANI_U8 channel = 0;
1650 tSirMacAddr targetApBssid;
1651 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001652#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1653 tCsrHandoffRequest handoffInfo;
1654#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001655 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001656 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1657
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001658 /* if not associated, no need to proceed with reassoc */
1659 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1660 {
1661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1662 ret = -EINVAL;
1663 goto exit;
1664 }
1665
1666 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1667 if (eHAL_STATUS_SUCCESS != status)
1668 {
1669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1670 "%s: Failed to parse reassoc command data", __func__);
1671 ret = -EINVAL;
1672 goto exit;
1673 }
1674
1675 /* if the target bssid is same as currently associated AP,
1676 then no need to proceed with reassoc */
1677 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1678 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1679 {
1680 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1681 ret = -EINVAL;
1682 goto exit;
1683 }
1684
1685 /* Check channel number is a valid channel number */
1686 if(VOS_STATUS_SUCCESS !=
1687 wlan_hdd_validate_operation_channel(pAdapter, channel))
1688 {
1689 hddLog(VOS_TRACE_LEVEL_ERROR,
1690 "%s: Invalid Channel [%d] \n", __func__, channel);
1691 return -EINVAL;
1692 }
1693
1694 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001695#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1696 handoffInfo.channel = channel;
1697 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1698 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1699#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001700 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001701#endif
1702#ifdef FEATURE_WLAN_LFR
1703 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1704 {
1705 tANI_U8 *value = command;
1706 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1707
1708 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1709 value = value + 12;
1710 /* Convert the value from ascii to integer */
1711 ret = kstrtou8(value, 10, &lfrMode);
1712 if (ret < 0)
1713 {
1714 /* If the input value is greater than max value of datatype, then also
1715 kstrtou8 fails */
1716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1717 "%s: kstrtou8 failed range [%d - %d]", __func__,
1718 CFG_LFR_FEATURE_ENABLED_MIN,
1719 CFG_LFR_FEATURE_ENABLED_MAX);
1720 ret = -EINVAL;
1721 goto exit;
1722 }
1723
1724 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1725 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1726 {
1727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1728 "lfr mode value %d is out of range"
1729 " (Min: %d Max: %d)", lfrMode,
1730 CFG_LFR_FEATURE_ENABLED_MIN,
1731 CFG_LFR_FEATURE_ENABLED_MAX);
1732 ret = -EINVAL;
1733 goto exit;
1734 }
1735
1736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1737 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1738
1739 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1740 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1741 }
1742#endif
1743#ifdef WLAN_FEATURE_VOWIFI_11R
1744 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1745 {
1746 tANI_U8 *value = command;
1747 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1748
1749 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1750 value = value + 18;
1751 /* Convert the value from ascii to integer */
1752 ret = kstrtou8(value, 10, &ft);
1753 if (ret < 0)
1754 {
1755 /* If the input value is greater than max value of datatype, then also
1756 kstrtou8 fails */
1757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1758 "%s: kstrtou8 failed range [%d - %d]", __func__,
1759 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1760 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1761 ret = -EINVAL;
1762 goto exit;
1763 }
1764
1765 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1766 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1767 {
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1769 "ft mode value %d is out of range"
1770 " (Min: %d Max: %d)", ft,
1771 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1772 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1773 ret = -EINVAL;
1774 goto exit;
1775 }
1776
1777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1778 "%s: Received Command to change ft mode = %d", __func__, ft);
1779
1780 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1781 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1782 }
1783#endif
1784#ifdef FEATURE_WLAN_CCX
1785 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1786 {
1787 tANI_U8 *value = command;
1788 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1789
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001790 /* Check if the features OKC/CCX/11R are supported simultaneously,
1791 then this operation is not permitted (return FAILURE) */
1792 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1793 hdd_is_okc_mode_enabled(pHddCtx) &&
1794 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1795 {
1796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1797 "%s: OKC/CCX/11R are supported simultaneously"
1798 " hence this operation is not permitted!", __func__);
1799 ret = -EPERM;
1800 goto exit;
1801 }
1802
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001803 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1804 value = value + 11;
1805 /* Convert the value from ascii to integer */
1806 ret = kstrtou8(value, 10, &ccxMode);
1807 if (ret < 0)
1808 {
1809 /* If the input value is greater than max value of datatype, then also
1810 kstrtou8 fails */
1811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s: kstrtou8 failed range [%d - %d]", __func__,
1813 CFG_CCX_FEATURE_ENABLED_MIN,
1814 CFG_CCX_FEATURE_ENABLED_MAX);
1815 ret = -EINVAL;
1816 goto exit;
1817 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001818 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1819 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1820 {
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1822 "Ccx mode value %d is out of range"
1823 " (Min: %d Max: %d)", ccxMode,
1824 CFG_CCX_FEATURE_ENABLED_MIN,
1825 CFG_CCX_FEATURE_ENABLED_MAX);
1826 ret = -EINVAL;
1827 goto exit;
1828 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1830 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1831
1832 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1833 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1834 }
1835#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001836 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1837 {
1838 tANI_U8 *value = command;
1839 tANI_BOOLEAN roamScanControl = 0;
1840
1841 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1842 value = value + 19;
1843 /* Convert the value from ascii to integer */
1844 ret = kstrtou8(value, 10, &roamScanControl);
1845 if (ret < 0)
1846 {
1847 /* If the input value is greater than max value of datatype, then also
1848 kstrtou8 fails */
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: kstrtou8 failed ", __func__);
1851 ret = -EINVAL;
1852 goto exit;
1853 }
1854
1855 if (0 != roamScanControl)
1856 {
1857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1858 "roam scan control invalid value = %d",
1859 roamScanControl);
1860 ret = -EINVAL;
1861 goto exit;
1862 }
1863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1864 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1865
1866 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1867 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001868#ifdef FEATURE_WLAN_OKC
1869 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1870 {
1871 tANI_U8 *value = command;
1872 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1873
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001874 /* Check if the features OKC/CCX/11R are supported simultaneously,
1875 then this operation is not permitted (return FAILURE) */
1876 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1877 hdd_is_okc_mode_enabled(pHddCtx) &&
1878 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1881 "%s: OKC/CCX/11R are supported simultaneously"
1882 " hence this operation is not permitted!", __func__);
1883 ret = -EPERM;
1884 goto exit;
1885 }
1886
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001887 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1888 value = value + 11;
1889 /* Convert the value from ascii to integer */
1890 ret = kstrtou8(value, 10, &okcMode);
1891 if (ret < 0)
1892 {
1893 /* If the input value is greater than max value of datatype, then also
1894 kstrtou8 fails */
1895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1896 "%s: kstrtou8 failed range [%d - %d]", __func__,
1897 CFG_OKC_FEATURE_ENABLED_MIN,
1898 CFG_OKC_FEATURE_ENABLED_MAX);
1899 ret = -EINVAL;
1900 goto exit;
1901 }
1902
1903 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1904 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1905 {
1906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1907 "Okc mode value %d is out of range"
1908 " (Min: %d Max: %d)", okcMode,
1909 CFG_OKC_FEATURE_ENABLED_MIN,
1910 CFG_OKC_FEATURE_ENABLED_MAX);
1911 ret = -EINVAL;
1912 goto exit;
1913 }
1914
1915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1916 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1917
1918 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1919 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001920 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1921 {
1922 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1923 char extra[32];
1924 tANI_U8 len = 0;
1925
1926 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1927 if (copy_to_user(priv_data.buf, &extra, len + 1))
1928 {
1929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1930 "%s: failed to copy data to user buffer", __func__);
1931 ret = -EFAULT;
1932 goto exit;
1933 }
1934 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001935#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301936#ifdef WLAN_FEATURE_PACKET_FILTERING
1937 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1938 {
1939 tANI_U8 filterType = 0;
1940 tANI_U8 *value = command;
1941
1942 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1943 value = value + 22;
1944
1945 /* Convert the value from ascii to integer */
1946 ret = kstrtou8(value, 10, &filterType);
1947 if (ret < 0)
1948 {
1949 /* If the input value is greater than max value of datatype,
1950 * then also kstrtou8 fails
1951 */
1952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1953 "%s: kstrtou8 failed range ", __func__);
1954 ret = -EINVAL;
1955 goto exit;
1956 }
1957
1958 if (filterType != 0 && filterType != 1)
1959 {
1960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1961 "%s: Accepted Values are 0 and 1 ", __func__);
1962 ret = -EINVAL;
1963 goto exit;
1964 }
1965 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
1966 pAdapter->sessionId);
1967 }
1968#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05301969 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
1970 {
1971 char *dhcpPhase;
1972 dhcpPhase = command + 12;
1973 if ('1' == *dhcpPhase)
1974 {
1975 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
1976 pAdapter->macAddressCurrent.bytes);
1977 }
1978 else if ('2' == *dhcpPhase)
1979 {
1980 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
1981 pAdapter->macAddressCurrent.bytes);
1982 }
1983 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07001984 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
1985 {
1986 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
1987 }
1988 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
1989 {
1990 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
1991 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05301992 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
1993 {
1994 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1995 char extra[32];
1996 tANI_U8 len = 0;
1997
1998 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
1999 (int)pCfg->nActiveMaxChnTime);
2000 if (copy_to_user(priv_data.buf, &extra, len + 1))
2001 {
2002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2003 "%s: failed to copy data to user buffer", __func__);
2004 ret = -EFAULT;
2005 goto exit;
2006 }
2007 ret = len;
2008 }
2009 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2010 {
2011 tANI_U8 *value = command;
2012 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2013 int val = 0, temp;
2014
2015 value = value + 13;
2016 temp = kstrtou32(value, 10, &val);
2017 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2018 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2019 {
2020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2021 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2022 ret = -EFAULT;
2023 goto exit;
2024 }
2025 pCfg->nActiveMaxChnTime = val;
2026 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002027 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2028 {
2029 tANI_U8 filterType = 0;
2030 tANI_U8 *value;
2031 value = command + 9;
2032
2033 /* Convert the value from ascii to integer */
2034 ret = kstrtou8(value, 10, &filterType);
2035 if (ret < 0)
2036 {
2037 /* If the input value is greater than max value of datatype,
2038 * then also kstrtou8 fails
2039 */
2040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2041 "%s: kstrtou8 failed range ", __func__);
2042 ret = -EINVAL;
2043 goto exit;
2044 }
2045 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2046 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2047 {
2048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2049 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2050 " 2-Sink ", __func__);
2051 ret = -EINVAL;
2052 goto exit;
2053 }
2054 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2055 pHddCtx->drvr_miracast = filterType;
2056 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2057 }
Leo Chang614d2072013-08-22 14:59:44 -07002058 else if (strncmp(command, "SETMCRATE", 9) == 0)
2059 {
2060 int rc;
2061 tANI_U8 *value = command;
2062 int targetRate;
2063
2064 /* Only valid for SAP mode */
2065 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2066 {
2067 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2068 "%s: SAP mode is not running", __func__);
2069 ret = -EFAULT;
2070 goto exit;
2071 }
2072
2073 /* Move pointer to ahead of SETMCRATE<delimiter> */
2074 /* input value is in units of hundred kbps */
2075 value = value + 10;
2076 /* Convert the value from ascii to integer, decimal base */
2077 ret = kstrtouint(value, 10, &targetRate);
2078
2079 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2080 if (rc)
2081 {
2082 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2083 "%s: Set MC Rate Fail %d", __func__, rc);
2084 ret = -EFAULT;
2085 goto exit;
2086 }
2087 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002088 else {
2089 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2090 __func__, command);
2091 }
2092
Jeff Johnson295189b2012-06-20 16:38:30 -07002093 }
2094exit:
2095 if (command)
2096 {
2097 kfree(command);
2098 }
2099 return ret;
2100}
2101
Srinivas Girigowdade697412013-02-14 16:31:48 -08002102#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2103void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2104{
2105 eCsrBand band = -1;
2106 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2107 switch (band)
2108 {
2109 case eCSR_BAND_ALL:
2110 *pBand = WLAN_HDD_UI_BAND_AUTO;
2111 break;
2112
2113 case eCSR_BAND_24:
2114 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2115 break;
2116
2117 case eCSR_BAND_5G:
2118 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2119 break;
2120
2121 default:
2122 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2123 *pBand = -1;
2124 break;
2125 }
2126}
2127
2128/**---------------------------------------------------------------------------
2129
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002130 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2131
2132 This function parses the send action frame data passed in the format
2133 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2134
Srinivas Girigowda56076852013-08-20 14:00:50 -07002135 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002136 \param - pTargetApBssid Pointer to target Ap bssid
2137 \param - pChannel Pointer to the Target AP channel
2138 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2139 \param - pBuf Pointer to data
2140 \param - pBufLen Pointer to data length
2141
2142 \return - 0 for success non-zero for failure
2143
2144 --------------------------------------------------------------------------*/
2145VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2146 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2147{
2148 tANI_U8 *inPtr = pValue;
2149 tANI_U8 *dataEnd;
2150 int tempInt;
2151 int j = 0;
2152 int i = 0;
2153 int v = 0;
2154 tANI_U8 tempBuf[32];
2155 tANI_U8 tempByte = 0;
2156
2157 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2158 /*no argument after the command*/
2159 if (NULL == inPtr)
2160 {
2161 return -EINVAL;
2162 }
2163
2164 /*no space after the command*/
2165 else if (SPACE_ASCII_VALUE != *inPtr)
2166 {
2167 return -EINVAL;
2168 }
2169
2170 /*removing empty spaces*/
2171 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2172
2173 /*no argument followed by spaces*/
2174 if ('\0' == *inPtr)
2175 {
2176 return -EINVAL;
2177 }
2178
2179 /*getting the first argument ie the target AP bssid */
2180 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2181 {
2182 return -EINVAL;
2183 }
2184 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2185 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2186 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2187
2188 /* point to the next argument */
2189 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2190 /*no argument after the command*/
2191 if (NULL == inPtr) return -EINVAL;
2192
2193 /*removing empty spaces*/
2194 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2195
2196 /*no argument followed by spaces*/
2197 if ('\0' == *inPtr)
2198 {
2199 return -EINVAL;
2200 }
2201
2202 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002203 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002204 v = kstrtos32(tempBuf, 10, &tempInt);
2205 if ( v < 0) return -EINVAL;
2206
2207 *pChannel = tempInt;
2208
2209 /* point to the next argument */
2210 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2211 /*no argument after the command*/
2212 if (NULL == inPtr) return -EINVAL;
2213 /*removing empty spaces*/
2214 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2215
2216 /*no argument followed by spaces*/
2217 if ('\0' == *inPtr)
2218 {
2219 return -EINVAL;
2220 }
2221
2222 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002223 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002224 v = kstrtos32(tempBuf, 10, &tempInt);
2225 if ( v < 0) return -EINVAL;
2226
2227 *pDwellTime = tempInt;
2228
2229 /* point to the next argument */
2230 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2231 /*no argument after the command*/
2232 if (NULL == inPtr) return -EINVAL;
2233 /*removing empty spaces*/
2234 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2235
2236 /*no argument followed by spaces*/
2237 if ('\0' == *inPtr)
2238 {
2239 return -EINVAL;
2240 }
2241
2242 /* find the length of data */
2243 dataEnd = inPtr;
2244 while(('\0' != *dataEnd) )
2245 {
2246 dataEnd++;
2247 ++(*pBufLen);
2248 }
2249 if ( *pBufLen <= 0) return -EINVAL;
2250
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002251 /* Allocate the number of bytes based on the number of input characters
2252 whether it is even or odd.
2253 if the number of input characters are even, then we need N/2 byte.
2254 if the number of input characters are odd, then we need do (N+1)/2 to
2255 compensate rounding off.
2256 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2257 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2258 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002259 if (NULL == *pBuf)
2260 {
2261 hddLog(VOS_TRACE_LEVEL_FATAL,
2262 "%s: vos_mem_alloc failed ", __func__);
2263 return -EINVAL;
2264 }
2265
2266 /* the buffer received from the upper layer is character buffer,
2267 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2268 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2269 and f0 in 3rd location */
2270 for (i = 0, j = 0; j < *pBufLen; j += 2)
2271 {
2272 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2273 (*pBuf)[i++] = tempByte;
2274 }
2275 *pBufLen = i;
2276 return VOS_STATUS_SUCCESS;
2277}
2278
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002279/**---------------------------------------------------------------------------
2280
Srinivas Girigowdade697412013-02-14 16:31:48 -08002281 \brief hdd_parse_channellist() - HDD Parse channel list
2282
2283 This function parses the channel list passed in the format
2284 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002285 if the Number of channels (N) does not match with the actual number of channels passed
2286 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2287 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2288 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2289 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002290
2291 \param - pValue Pointer to input channel list
2292 \param - ChannelList Pointer to local output array to record channel list
2293 \param - pNumChannels Pointer to number of roam scan channels
2294
2295 \return - 0 for success non-zero for failure
2296
2297 --------------------------------------------------------------------------*/
2298VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2299{
2300 tANI_U8 *inPtr = pValue;
2301 int tempInt;
2302 int j = 0;
2303 int v = 0;
2304 char buf[32];
2305
2306 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2307 /*no argument after the command*/
2308 if (NULL == inPtr)
2309 {
2310 return -EINVAL;
2311 }
2312
2313 /*no space after the command*/
2314 else if (SPACE_ASCII_VALUE != *inPtr)
2315 {
2316 return -EINVAL;
2317 }
2318
2319 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002320 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002321
2322 /*no argument followed by spaces*/
2323 if ('\0' == *inPtr)
2324 {
2325 return -EINVAL;
2326 }
2327
2328 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002329 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002330 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002331 if ((v < 0) ||
2332 (tempInt <= 0) ||
2333 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2334 {
2335 return -EINVAL;
2336 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337
2338 *pNumChannels = tempInt;
2339
2340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2341 "Number of channels are: %d", *pNumChannels);
2342
2343 for (j = 0; j < (*pNumChannels); j++)
2344 {
2345 /*inPtr pointing to the beginning of first space after number of channels*/
2346 inPtr = strpbrk( inPtr, " " );
2347 /*no channel list after the number of channels argument*/
2348 if (NULL == inPtr)
2349 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002350 if (0 != j)
2351 {
2352 *pNumChannels = j;
2353 return VOS_STATUS_SUCCESS;
2354 }
2355 else
2356 {
2357 return -EINVAL;
2358 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002359 }
2360
2361 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002362 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002363
2364 /*no channel list after the number of channels argument and spaces*/
2365 if ( '\0' == *inPtr )
2366 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002367 if (0 != j)
2368 {
2369 *pNumChannels = j;
2370 return VOS_STATUS_SUCCESS;
2371 }
2372 else
2373 {
2374 return -EINVAL;
2375 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376 }
2377
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002378 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002379 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002380 if ((v < 0) ||
2381 (tempInt <= 0) ||
2382 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2383 {
2384 return -EINVAL;
2385 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002386 pChannelList[j] = tempInt;
2387
2388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2389 "Channel %d added to preferred channel list",
2390 pChannelList[j] );
2391 }
2392
Srinivas Girigowdade697412013-02-14 16:31:48 -08002393 return VOS_STATUS_SUCCESS;
2394}
2395
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002396
2397/**---------------------------------------------------------------------------
2398
2399 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2400
2401 This function parses the reasoc command data passed in the format
2402 REASSOC<space><bssid><space><channel>
2403
Srinivas Girigowda56076852013-08-20 14:00:50 -07002404 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002405 \param - pTargetApBssid Pointer to target Ap bssid
2406 \param - pChannel Pointer to the Target AP channel
2407
2408 \return - 0 for success non-zero for failure
2409
2410 --------------------------------------------------------------------------*/
2411VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2412{
2413 tANI_U8 *inPtr = pValue;
2414 int tempInt;
2415 int v = 0;
2416 tANI_U8 tempBuf[32];
2417
2418 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2419 /*no argument after the command*/
2420 if (NULL == inPtr)
2421 {
2422 return -EINVAL;
2423 }
2424
2425 /*no space after the command*/
2426 else if (SPACE_ASCII_VALUE != *inPtr)
2427 {
2428 return -EINVAL;
2429 }
2430
2431 /*removing empty spaces*/
2432 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2433
2434 /*no argument followed by spaces*/
2435 if ('\0' == *inPtr)
2436 {
2437 return -EINVAL;
2438 }
2439
2440 /*getting the first argument ie the target AP bssid */
2441 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2442 {
2443 return -EINVAL;
2444 }
2445 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2446 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2447 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2448
2449 /* point to the next argument */
2450 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2451 /*no argument after the command*/
2452 if (NULL == inPtr) return -EINVAL;
2453
2454 /*removing empty spaces*/
2455 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2456
2457 /*no argument followed by spaces*/
2458 if ('\0' == *inPtr)
2459 {
2460 return -EINVAL;
2461 }
2462
2463 /*getting the next argument ie the channel number */
2464 sscanf(inPtr, "%s ", tempBuf);
2465 v = kstrtos32(tempBuf, 10, &tempInt);
2466 if ( v < 0) return -EINVAL;
2467
2468 *pChannel = tempInt;
2469 return VOS_STATUS_SUCCESS;
2470}
2471
2472#endif
2473
Jeff Johnson295189b2012-06-20 16:38:30 -07002474/**---------------------------------------------------------------------------
2475
2476 \brief hdd_open() - HDD Open function
2477
2478 This is called in response to ifconfig up
2479
2480 \param - dev Pointer to net_device structure
2481
2482 \return - 0 for success non-zero for failure
2483
2484 --------------------------------------------------------------------------*/
2485int hdd_open (struct net_device *dev)
2486{
2487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2488 hdd_context_t *pHddCtx;
2489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2490 VOS_STATUS status;
2491 v_BOOL_t in_standby = TRUE;
2492
2493 if (NULL == pAdapter)
2494 {
2495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002496 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 return -ENODEV;
2498 }
2499
2500 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2501 if (NULL == pHddCtx)
2502 {
2503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002504 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002505 return -ENODEV;
2506 }
2507
2508 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2509 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2510 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002511 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2512 {
2513 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302514 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002515 in_standby = FALSE;
2516 break;
2517 }
2518 else
2519 {
2520 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2521 pAdapterNode = pNext;
2522 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002523 }
2524
2525 if (TRUE == in_standby)
2526 {
2527 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2528 {
2529 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2530 "wlan out of power save", __func__);
2531 return -EINVAL;
2532 }
2533 }
2534
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002535 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2537 {
2538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002539 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002540 /* Enable TX queues only when we are connected */
2541 netif_tx_start_all_queues(dev);
2542 }
2543
2544 return 0;
2545}
2546
2547int hdd_mon_open (struct net_device *dev)
2548{
2549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2550
2551 if(pAdapter == NULL) {
2552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002553 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002554 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 }
2556
2557 netif_start_queue(dev);
2558
2559 return 0;
2560}
2561/**---------------------------------------------------------------------------
2562
2563 \brief hdd_stop() - HDD stop function
2564
2565 This is called in response to ifconfig down
2566
2567 \param - dev Pointer to net_device structure
2568
2569 \return - 0 for success non-zero for failure
2570
2571 --------------------------------------------------------------------------*/
2572
2573int hdd_stop (struct net_device *dev)
2574{
2575 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2576 hdd_context_t *pHddCtx;
2577 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2578 VOS_STATUS status;
2579 v_BOOL_t enter_standby = TRUE;
2580
2581 ENTER();
2582
2583 if (NULL == pAdapter)
2584 {
2585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002586 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002587 return -ENODEV;
2588 }
2589
2590 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2591 if (NULL == pHddCtx)
2592 {
2593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002594 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002595 return -ENODEV;
2596 }
2597
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002598 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2600 netif_tx_disable(pAdapter->dev);
2601 netif_carrier_off(pAdapter->dev);
2602
2603
2604 /* SoftAP ifaces should never go in power save mode
2605 making sure same here. */
2606 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2607 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002608 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002609 )
2610 {
2611 /* SoftAP mode, so return from here */
2612 EXIT();
2613 return 0;
2614 }
2615
2616 /* Find if any iface is up then
2617 if any iface is up then can't put device to sleep/ power save mode. */
2618 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2619 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2620 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002621 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2622 {
2623 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302624 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002625 enter_standby = FALSE;
2626 break;
2627 }
2628 else
2629 {
2630 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2631 pAdapterNode = pNext;
2632 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002633 }
2634
2635 if (TRUE == enter_standby)
2636 {
2637 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2638 "entering standby", __func__);
2639 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2640 {
2641 /*log and return success*/
2642 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2643 "wlan in power save", __func__);
2644 }
2645 }
2646
2647 EXIT();
2648 return 0;
2649}
2650
2651/**---------------------------------------------------------------------------
2652
2653 \brief hdd_uninit() - HDD uninit function
2654
2655 This is called during the netdev unregister to uninitialize all data
2656associated with the device
2657
2658 \param - dev Pointer to net_device structure
2659
2660 \return - void
2661
2662 --------------------------------------------------------------------------*/
2663static void hdd_uninit (struct net_device *dev)
2664{
2665 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2666
2667 ENTER();
2668
2669 do
2670 {
2671 if (NULL == pAdapter)
2672 {
2673 hddLog(VOS_TRACE_LEVEL_FATAL,
2674 "%s: NULL pAdapter", __func__);
2675 break;
2676 }
2677
2678 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2679 {
2680 hddLog(VOS_TRACE_LEVEL_FATAL,
2681 "%s: Invalid magic", __func__);
2682 break;
2683 }
2684
2685 if (NULL == pAdapter->pHddCtx)
2686 {
2687 hddLog(VOS_TRACE_LEVEL_FATAL,
2688 "%s: NULL pHddCtx", __func__);
2689 break;
2690 }
2691
2692 if (dev != pAdapter->dev)
2693 {
2694 hddLog(VOS_TRACE_LEVEL_FATAL,
2695 "%s: Invalid device reference", __func__);
2696 /* we haven't validated all cases so let this go for now */
2697 }
2698
2699 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2700
2701 /* after uninit our adapter structure will no longer be valid */
2702 pAdapter->dev = NULL;
2703 pAdapter->magic = 0;
2704 } while (0);
2705
2706 EXIT();
2707}
2708
2709/**---------------------------------------------------------------------------
2710
2711 \brief hdd_release_firmware() -
2712
2713 This function calls the release firmware API to free the firmware buffer.
2714
2715 \param - pFileName Pointer to the File Name.
2716 pCtx - Pointer to the adapter .
2717
2718
2719 \return - 0 for success, non zero for failure
2720
2721 --------------------------------------------------------------------------*/
2722
2723VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2724{
2725 VOS_STATUS status = VOS_STATUS_SUCCESS;
2726 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2727 ENTER();
2728
2729
2730 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2731
2732 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2733
2734 if(pHddCtx->fw) {
2735 release_firmware(pHddCtx->fw);
2736 pHddCtx->fw = NULL;
2737 }
2738 else
2739 status = VOS_STATUS_E_FAILURE;
2740 }
2741 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2742 if(pHddCtx->nv) {
2743 release_firmware(pHddCtx->nv);
2744 pHddCtx->nv = NULL;
2745 }
2746 else
2747 status = VOS_STATUS_E_FAILURE;
2748
2749 }
2750
2751 EXIT();
2752 return status;
2753}
2754
2755/**---------------------------------------------------------------------------
2756
2757 \brief hdd_request_firmware() -
2758
2759 This function reads the firmware file using the request firmware
2760 API and returns the the firmware data and the firmware file size.
2761
2762 \param - pfileName - Pointer to the file name.
2763 - pCtx - Pointer to the adapter .
2764 - ppfw_data - Pointer to the pointer of the firmware data.
2765 - pSize - Pointer to the file size.
2766
2767 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2768
2769 --------------------------------------------------------------------------*/
2770
2771
2772VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2773{
2774 int status;
2775 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2776 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2777 ENTER();
2778
2779 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2780
2781 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2782
2783 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2784 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2785 __func__, pfileName);
2786 retval = VOS_STATUS_E_FAILURE;
2787 }
2788
2789 else {
2790 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2791 *pSize = pHddCtx->fw->size;
2792 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2793 __func__, *pSize);
2794 }
2795 }
2796 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2797
2798 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2799
2800 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2801 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2802 __func__, pfileName);
2803 retval = VOS_STATUS_E_FAILURE;
2804 }
2805
2806 else {
2807 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2808 *pSize = pHddCtx->nv->size;
2809 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2810 __func__, *pSize);
2811 }
2812 }
2813
2814 EXIT();
2815 return retval;
2816}
2817/**---------------------------------------------------------------------------
2818 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2819
2820 This is the function invoked by SME to inform the result of a full power
2821 request issued by HDD
2822
2823 \param - callbackcontext - Pointer to cookie
2824 status - result of request
2825
2826 \return - None
2827
2828--------------------------------------------------------------------------*/
2829void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2830{
2831 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2832
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002833 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002834 if(&pHddCtx->full_pwr_comp_var)
2835 {
2836 complete(&pHddCtx->full_pwr_comp_var);
2837 }
2838}
2839
2840/**---------------------------------------------------------------------------
2841
2842 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2843
2844 This is the function invoked by SME to inform the result of BMPS
2845 request issued by HDD
2846
2847 \param - callbackcontext - Pointer to cookie
2848 status - result of request
2849
2850 \return - None
2851
2852--------------------------------------------------------------------------*/
2853void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2854{
2855
2856 struct completion *completion_var = (struct completion*) callbackContext;
2857
2858 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2859 if(completion_var != NULL)
2860 {
2861 complete(completion_var);
2862 }
2863}
2864
2865/**---------------------------------------------------------------------------
2866
2867 \brief hdd_get_cfg_file_size() -
2868
2869 This function reads the configuration file using the request firmware
2870 API and returns the configuration file size.
2871
2872 \param - pCtx - Pointer to the adapter .
2873 - pFileName - Pointer to the file name.
2874 - pBufSize - Pointer to the buffer size.
2875
2876 \return - 0 for success, non zero for failure
2877
2878 --------------------------------------------------------------------------*/
2879
2880VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2881{
2882 int status;
2883 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2884
2885 ENTER();
2886
2887 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2888
2889 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2890 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2891 status = VOS_STATUS_E_FAILURE;
2892 }
2893 else {
2894 *pBufSize = pHddCtx->fw->size;
2895 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2896 release_firmware(pHddCtx->fw);
2897 pHddCtx->fw = NULL;
2898 }
2899
2900 EXIT();
2901 return VOS_STATUS_SUCCESS;
2902}
2903
2904/**---------------------------------------------------------------------------
2905
2906 \brief hdd_read_cfg_file() -
2907
2908 This function reads the configuration file using the request firmware
2909 API and returns the cfg data and the buffer size of the configuration file.
2910
2911 \param - pCtx - Pointer to the adapter .
2912 - pFileName - Pointer to the file name.
2913 - pBuffer - Pointer to the data buffer.
2914 - pBufSize - Pointer to the buffer size.
2915
2916 \return - 0 for success, non zero for failure
2917
2918 --------------------------------------------------------------------------*/
2919
2920VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2921 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2922{
2923 int status;
2924 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2925
2926 ENTER();
2927
2928 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2929
2930 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2931 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2932 return VOS_STATUS_E_FAILURE;
2933 }
2934 else {
2935 if(*pBufSize != pHddCtx->fw->size) {
2936 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2937 "file size", __func__);
2938 release_firmware(pHddCtx->fw);
2939 pHddCtx->fw = NULL;
2940 return VOS_STATUS_E_FAILURE;
2941 }
2942 else {
2943 if(pBuffer) {
2944 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2945 }
2946 release_firmware(pHddCtx->fw);
2947 pHddCtx->fw = NULL;
2948 }
2949 }
2950
2951 EXIT();
2952
2953 return VOS_STATUS_SUCCESS;
2954}
2955
2956/**---------------------------------------------------------------------------
2957
Jeff Johnson295189b2012-06-20 16:38:30 -07002958 \brief hdd_set_mac_address() -
2959
2960 This function sets the user specified mac address using
2961 the command ifconfig wlanX hw ether <mac adress>.
2962
2963 \param - dev - Pointer to the net device.
2964 - addr - Pointer to the sockaddr.
2965 \return - 0 for success, non zero for failure
2966
2967 --------------------------------------------------------------------------*/
2968
2969static int hdd_set_mac_address(struct net_device *dev, void *addr)
2970{
2971 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2972 struct sockaddr *psta_mac_addr = addr;
2973 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2974
2975 ENTER();
2976
2977 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2978
2979#ifdef HDD_SESSIONIZE
2980 // set the MAC address though the STA ID CFG.
2981 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2982 (v_U8_t *)&pAdapter->macAddressCurrent,
2983 sizeof( pAdapter->macAddressCurrent ),
2984 hdd_set_mac_addr_cb, VOS_FALSE );
2985#endif
2986
2987 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2988
2989 EXIT();
2990 return halStatus;
2991}
2992
2993tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2994{
2995 int i;
2996 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2997 {
2998 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2999 break;
3000 }
3001
3002 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3003 return NULL;
3004
3005 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3006 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3007}
3008
3009void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3010{
3011 int i;
3012 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3013 {
3014 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3015 {
3016 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3017 break;
3018 }
3019 }
3020 return;
3021}
3022
3023#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3024 static struct net_device_ops wlan_drv_ops = {
3025 .ndo_open = hdd_open,
3026 .ndo_stop = hdd_stop,
3027 .ndo_uninit = hdd_uninit,
3028 .ndo_start_xmit = hdd_hard_start_xmit,
3029 .ndo_tx_timeout = hdd_tx_timeout,
3030 .ndo_get_stats = hdd_stats,
3031 .ndo_do_ioctl = hdd_ioctl,
3032 .ndo_set_mac_address = hdd_set_mac_address,
3033 .ndo_select_queue = hdd_select_queue,
3034#ifdef WLAN_FEATURE_PACKET_FILTERING
3035#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3036 .ndo_set_rx_mode = hdd_set_multicast_list,
3037#else
3038 .ndo_set_multicast_list = hdd_set_multicast_list,
3039#endif //LINUX_VERSION_CODE
3040#endif
3041 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003042 static struct net_device_ops wlan_mon_drv_ops = {
3043 .ndo_open = hdd_mon_open,
3044 .ndo_stop = hdd_stop,
3045 .ndo_uninit = hdd_uninit,
3046 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3047 .ndo_tx_timeout = hdd_tx_timeout,
3048 .ndo_get_stats = hdd_stats,
3049 .ndo_do_ioctl = hdd_ioctl,
3050 .ndo_set_mac_address = hdd_set_mac_address,
3051 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003052
3053#endif
3054
3055void hdd_set_station_ops( struct net_device *pWlanDev )
3056{
3057#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3058 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3059 pWlanDev->netdev_ops = &wlan_drv_ops;
3060#else
3061 pWlanDev->open = hdd_open;
3062 pWlanDev->stop = hdd_stop;
3063 pWlanDev->uninit = hdd_uninit;
3064 pWlanDev->hard_start_xmit = NULL;
3065 pWlanDev->tx_timeout = hdd_tx_timeout;
3066 pWlanDev->get_stats = hdd_stats;
3067 pWlanDev->do_ioctl = hdd_ioctl;
3068 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3069 pWlanDev->set_mac_address = hdd_set_mac_address;
3070#endif
3071}
3072
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003073static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003074{
3075 struct net_device *pWlanDev = NULL;
3076 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003077 /*
3078 * cfg80211 initialization and registration....
3079 */
3080 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3081
Jeff Johnson295189b2012-06-20 16:38:30 -07003082 if(pWlanDev != NULL)
3083 {
3084
3085 //Save the pointer to the net_device in the HDD adapter
3086 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3087
Jeff Johnson295189b2012-06-20 16:38:30 -07003088 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3089
3090 pAdapter->dev = pWlanDev;
3091 pAdapter->pHddCtx = pHddCtx;
3092 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3093
3094 init_completion(&pAdapter->session_open_comp_var);
3095 init_completion(&pAdapter->session_close_comp_var);
3096 init_completion(&pAdapter->disconnect_comp_var);
3097 init_completion(&pAdapter->linkup_event_var);
3098 init_completion(&pAdapter->cancel_rem_on_chan_var);
3099 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003100#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3101 init_completion(&pAdapter->offchannel_tx_event);
3102#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003103 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003104#ifdef FEATURE_WLAN_TDLS
3105 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003106 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003107 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303108 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003110 init_completion(&pHddCtx->mc_sus_event_var);
3111 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303112 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003113 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003114
Jeff Johnson295189b2012-06-20 16:38:30 -07003115 pAdapter->isLinkUpSvcNeeded = FALSE;
3116 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3117 //Init the net_device structure
3118 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3119
3120 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3121 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3122 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3123 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3124
3125 hdd_set_station_ops( pAdapter->dev );
3126
3127 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003128 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3129 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3130 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003131 /* set pWlanDev's parent to underlying device */
3132 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3133 }
3134
3135 return pAdapter;
3136}
3137
3138VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3139{
3140 struct net_device *pWlanDev = pAdapter->dev;
3141 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3142 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3143 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3144
3145 if( rtnl_lock_held )
3146 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003147 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003148 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3149 {
3150 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3151 return VOS_STATUS_E_FAILURE;
3152 }
3153 }
3154 if (register_netdevice(pWlanDev))
3155 {
3156 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3157 return VOS_STATUS_E_FAILURE;
3158 }
3159 }
3160 else
3161 {
3162 if(register_netdev(pWlanDev))
3163 {
3164 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3165 return VOS_STATUS_E_FAILURE;
3166 }
3167 }
3168 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3169
3170 return VOS_STATUS_SUCCESS;
3171}
3172
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003173static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003174{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003175 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003176
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003177 if (NULL == pAdapter)
3178 {
3179 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3180 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003181 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003182
3183 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3184 {
3185 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3186 return eHAL_STATUS_NOT_INITIALIZED;
3187 }
3188
3189 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3190
3191 /* need to make sure all of our scheduled work has completed.
3192 * This callback is called from MC thread context, so it is safe to
3193 * to call below flush workqueue API from here.
3194 */
3195 flush_scheduled_work();
3196
3197 /* We can be blocked while waiting for scheduled work to be
3198 * flushed, and the adapter structure can potentially be freed, in
3199 * which case the magic will have been reset. So make sure the
3200 * magic is still good, and hence the adapter structure is still
3201 * valid, before signaling completion */
3202 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3203 {
3204 complete(&pAdapter->session_close_comp_var);
3205 }
3206
Jeff Johnson295189b2012-06-20 16:38:30 -07003207 return eHAL_STATUS_SUCCESS;
3208}
3209
3210VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3211{
3212 struct net_device *pWlanDev = pAdapter->dev;
3213 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3214 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3215 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3216 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3217 int rc = 0;
3218
3219 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003220 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003221 //Open a SME session for future operation
3222 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003223 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003224 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3225 {
3226 hddLog(VOS_TRACE_LEVEL_FATAL,
3227 "sme_OpenSession() failed with status code %08d [x%08lx]",
3228 halStatus, halStatus );
3229 status = VOS_STATUS_E_FAILURE;
3230 goto error_sme_open;
3231 }
3232
3233 //Block on a completion variable. Can't wait forever though.
3234 rc = wait_for_completion_interruptible_timeout(
3235 &pAdapter->session_open_comp_var,
3236 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3237 if (!rc)
3238 {
3239 hddLog(VOS_TRACE_LEVEL_FATAL,
3240 "Session is not opened within timeout period code %08d", rc );
3241 status = VOS_STATUS_E_FAILURE;
3242 goto error_sme_open;
3243 }
3244
3245 // Register wireless extensions
3246 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3247 {
3248 hddLog(VOS_TRACE_LEVEL_FATAL,
3249 "hdd_register_wext() failed with status code %08d [x%08lx]",
3250 halStatus, halStatus );
3251 status = VOS_STATUS_E_FAILURE;
3252 goto error_register_wext;
3253 }
3254 //Safe to register the hard_start_xmit function again
3255#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3256 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3257#else
3258 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3259#endif
3260
3261 //Set the Connection State to Not Connected
3262 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3263
3264 //Set the default operation channel
3265 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3266
3267 /* Make the default Auth Type as OPEN*/
3268 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3269
3270 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3271 {
3272 hddLog(VOS_TRACE_LEVEL_FATAL,
3273 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3274 status, status );
3275 goto error_init_txrx;
3276 }
3277
3278 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3279
3280 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3281 {
3282 hddLog(VOS_TRACE_LEVEL_FATAL,
3283 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3284 status, status );
3285 goto error_wmm_init;
3286 }
3287
3288 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3289
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003290#ifdef FEATURE_WLAN_TDLS
3291 if(0 != wlan_hdd_tdls_init(pAdapter))
3292 {
3293 status = VOS_STATUS_E_FAILURE;
3294 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3295 goto error_tdls_init;
3296 }
3297 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3298#endif
3299
Jeff Johnson295189b2012-06-20 16:38:30 -07003300 return VOS_STATUS_SUCCESS;
3301
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003302#ifdef FEATURE_WLAN_TDLS
3303error_tdls_init:
3304 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3305 hdd_wmm_adapter_close(pAdapter);
3306#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003307error_wmm_init:
3308 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3309 hdd_deinit_tx_rx(pAdapter);
3310error_init_txrx:
3311 hdd_UnregisterWext(pWlanDev);
3312error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003313 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003314 {
3315 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003316 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003318 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003319 {
3320 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003321 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003322 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003323 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003324 }
3325}
3326error_sme_open:
3327 return status;
3328}
3329
Jeff Johnson295189b2012-06-20 16:38:30 -07003330void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3331{
3332 hdd_cfg80211_state_t *cfgState;
3333
3334 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3335
3336 if( NULL != cfgState->buf )
3337 {
3338 int rc;
3339 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3340 rc = wait_for_completion_interruptible_timeout(
3341 &pAdapter->tx_action_cnf_event,
3342 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3343 if(!rc)
3344 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3347 }
3348 }
3349 return;
3350}
Jeff Johnson295189b2012-06-20 16:38:30 -07003351
3352void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3353{
3354 ENTER();
3355 switch ( pAdapter->device_mode )
3356 {
3357 case WLAN_HDD_INFRA_STATION:
3358 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003359 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003360 {
3361 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3362 {
3363 hdd_deinit_tx_rx( pAdapter );
3364 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3365 }
3366
3367 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3368 {
3369 hdd_wmm_adapter_close( pAdapter );
3370 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3371 }
3372
Jeff Johnson295189b2012-06-20 16:38:30 -07003373 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003374#ifdef FEATURE_WLAN_TDLS
3375 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3376 {
3377 wlan_hdd_tdls_exit(pAdapter);
3378 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3379 }
3380#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003381
3382 break;
3383 }
3384
3385 case WLAN_HDD_SOFTAP:
3386 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003387 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003388 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003389
3390 hdd_unregister_hostapd(pAdapter);
3391 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003392 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003393 break;
3394 }
3395
3396 case WLAN_HDD_MONITOR:
3397 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003398 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003399 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3400 {
3401 hdd_deinit_tx_rx( pAdapter );
3402 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3403 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003404 if(NULL != pAdapterforTx)
3405 {
3406 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3407 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 break;
3409 }
3410
3411
3412 default:
3413 break;
3414 }
3415
3416 EXIT();
3417}
3418
3419void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3420{
3421 struct net_device *pWlanDev = pAdapter->dev;
3422
3423 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3424 if( rtnl_held )
3425 {
3426 unregister_netdevice(pWlanDev);
3427 }
3428 else
3429 {
3430 unregister_netdev(pWlanDev);
3431 }
3432 // note that the pAdapter is no longer valid at this point
3433 // since the memory has been reclaimed
3434 }
3435
3436}
3437
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003438void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3439{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303440 VOS_STATUS status;
3441 hdd_adapter_t *pAdapter = NULL;
3442 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003443
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303444 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003445
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303446 /*loop through all adapters.*/
3447 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003448 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303449 pAdapter = pAdapterNode->pAdapter;
3450 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3451 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003452
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303453 { // we skip this registration for modes other than STA and P2P client modes.
3454 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3455 pAdapterNode = pNext;
3456 continue;
3457 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003458
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303459 //Apply Dynamic DTIM For P2P
3460 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3461 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3462 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3463 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3464 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3465 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3466 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3467 (eConnectionState_Associated ==
3468 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3469 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3470 {
3471 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003472
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303473 powerRequest.uIgnoreDTIM = 1;
3474 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3475
3476 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3477 {
3478 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3479 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3480 }
3481 else
3482 {
3483 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3484 }
3485
3486 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3487 * specified during Enter/Exit BMPS when LCD off*/
3488 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3489 NULL, eANI_BOOLEAN_FALSE);
3490 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3491 NULL, eANI_BOOLEAN_FALSE);
3492
3493 /* switch to the DTIM specified in cfg.ini */
3494 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3495 "Switch to DTIM %d", powerRequest.uListenInterval);
3496 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3497 break;
3498
3499 }
3500
3501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3502 pAdapterNode = pNext;
3503 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003504}
3505
3506void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3507{
3508 /*Switch back to DTIM 1*/
3509 tSirSetPowerParamsReq powerRequest = { 0 };
3510
3511 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3512 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003513 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003514
3515 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3516 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3517 NULL, eANI_BOOLEAN_FALSE);
3518 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3519 NULL, eANI_BOOLEAN_FALSE);
3520
3521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3522 "Switch to DTIM%d",powerRequest.uListenInterval);
3523 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3524
3525}
3526
Jeff Johnson295189b2012-06-20 16:38:30 -07003527VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3528{
3529 VOS_STATUS status = VOS_STATUS_SUCCESS;
3530
3531 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3532 {
3533 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3534 }
3535
3536 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3537 {
3538 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3539 }
3540
3541 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3542 {
3543 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3544 }
3545
3546 return status;
3547}
3548
3549VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3550{
3551 hdd_adapter_t *pAdapter = NULL;
3552 eHalStatus halStatus;
3553 VOS_STATUS status = VOS_STATUS_E_INVAL;
3554 v_BOOL_t disableBmps = FALSE;
3555 v_BOOL_t disableImps = FALSE;
3556
3557 switch(session_type)
3558 {
3559 case WLAN_HDD_INFRA_STATION:
3560 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003561 case WLAN_HDD_P2P_CLIENT:
3562 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003563 //Exit BMPS -> Is Sta/P2P Client is already connected
3564 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3565 if((NULL != pAdapter)&&
3566 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3567 {
3568 disableBmps = TRUE;
3569 }
3570
3571 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3572 if((NULL != pAdapter)&&
3573 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3574 {
3575 disableBmps = TRUE;
3576 }
3577
3578 //Exit both Bmps and Imps incase of Go/SAP Mode
3579 if((WLAN_HDD_SOFTAP == session_type) ||
3580 (WLAN_HDD_P2P_GO == session_type))
3581 {
3582 disableBmps = TRUE;
3583 disableImps = TRUE;
3584 }
3585
3586 if(TRUE == disableImps)
3587 {
3588 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3589 {
3590 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3591 }
3592 }
3593
3594 if(TRUE == disableBmps)
3595 {
3596 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3597 {
3598 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3599
3600 if(eHAL_STATUS_SUCCESS != halStatus)
3601 {
3602 status = VOS_STATUS_E_FAILURE;
3603 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3604 VOS_ASSERT(0);
3605 return status;
3606 }
3607 }
3608
3609 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3610 {
3611 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3612
3613 if(eHAL_STATUS_SUCCESS != halStatus)
3614 {
3615 status = VOS_STATUS_E_FAILURE;
3616 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3617 VOS_ASSERT(0);
3618 return status;
3619 }
3620 }
3621 }
3622
3623 if((TRUE == disableBmps) ||
3624 (TRUE == disableImps))
3625 {
3626 /* Now, get the chip into Full Power now */
3627 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3628 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3629 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3630
3631 if(halStatus != eHAL_STATUS_SUCCESS)
3632 {
3633 if(halStatus == eHAL_STATUS_PMC_PENDING)
3634 {
3635 //Block on a completion variable. Can't wait forever though
3636 wait_for_completion_interruptible_timeout(
3637 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3638 }
3639 else
3640 {
3641 status = VOS_STATUS_E_FAILURE;
3642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3643 VOS_ASSERT(0);
3644 return status;
3645 }
3646 }
3647
3648 status = VOS_STATUS_SUCCESS;
3649 }
3650
3651 break;
3652 }
3653 return status;
3654}
3655
3656hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003657 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003658 tANI_U8 rtnl_held )
3659{
3660 hdd_adapter_t *pAdapter = NULL;
3661 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3662 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3663 VOS_STATUS exitbmpsStatus;
3664
3665 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3666
3667 //Disable BMPS incase of Concurrency
3668 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3669
3670 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3671 {
3672 //Fail to Exit BMPS
3673 VOS_ASSERT(0);
3674 return NULL;
3675 }
3676
3677 switch(session_type)
3678 {
3679 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003680 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003681 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003682 {
3683 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3684
3685 if( NULL == pAdapter )
3686 return NULL;
3687
Jeff Johnsone7245742012-09-05 17:12:55 -07003688 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3689 NL80211_IFTYPE_P2P_CLIENT:
3690 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003691
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 pAdapter->device_mode = session_type;
3693
3694 status = hdd_init_station_mode( pAdapter );
3695 if( VOS_STATUS_SUCCESS != status )
3696 goto err_free_netdev;
3697
3698 status = hdd_register_interface( pAdapter, rtnl_held );
3699 if( VOS_STATUS_SUCCESS != status )
3700 {
3701 hdd_deinit_adapter(pHddCtx, pAdapter);
3702 goto err_free_netdev;
3703 }
3704 //Stop the Interface TX queue.
3705 netif_tx_disable(pAdapter->dev);
3706 //netif_tx_disable(pWlanDev);
3707 netif_carrier_off(pAdapter->dev);
3708
3709 break;
3710 }
3711
Jeff Johnson295189b2012-06-20 16:38:30 -07003712 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 case WLAN_HDD_SOFTAP:
3714 {
3715 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3716 if( NULL == pAdapter )
3717 return NULL;
3718
Jeff Johnson295189b2012-06-20 16:38:30 -07003719 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3720 NL80211_IFTYPE_AP:
3721 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003722 pAdapter->device_mode = session_type;
3723
3724 status = hdd_init_ap_mode(pAdapter);
3725 if( VOS_STATUS_SUCCESS != status )
3726 goto err_free_netdev;
3727
3728 status = hdd_register_hostapd( pAdapter, rtnl_held );
3729 if( VOS_STATUS_SUCCESS != status )
3730 {
3731 hdd_deinit_adapter(pHddCtx, pAdapter);
3732 goto err_free_netdev;
3733 }
3734
3735 netif_tx_disable(pAdapter->dev);
3736 netif_carrier_off(pAdapter->dev);
3737
3738 hdd_set_conparam( 1 );
3739 break;
3740 }
3741 case WLAN_HDD_MONITOR:
3742 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003743 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3744 if( NULL == pAdapter )
3745 return NULL;
3746
3747 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3748 pAdapter->device_mode = session_type;
3749 status = hdd_register_interface( pAdapter, rtnl_held );
3750#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3751 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3752#else
3753 pAdapter->dev->open = hdd_mon_open;
3754 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3755#endif
3756 hdd_init_tx_rx( pAdapter );
3757 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3758 //Set adapter to be used for data tx. It will use either GO or softap.
3759 pAdapter->sessionCtx.monitor.pAdapterForTx =
3760 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003761 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3762 {
3763 pAdapter->sessionCtx.monitor.pAdapterForTx =
3764 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3765 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 /* This workqueue will be used to transmit management packet over
3767 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003768 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3769 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3770 return NULL;
3771 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003772
Jeff Johnson295189b2012-06-20 16:38:30 -07003773 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3774 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003775 }
3776 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003777 case WLAN_HDD_FTM:
3778 {
3779 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3780
3781 if( NULL == pAdapter )
3782 return NULL;
3783 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3784 * message while loading driver in FTM mode. */
3785 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3786 pAdapter->device_mode = session_type;
3787 status = hdd_register_interface( pAdapter, rtnl_held );
3788 }
3789 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 default:
3791 {
3792 VOS_ASSERT(0);
3793 return NULL;
3794 }
3795 }
3796
3797
3798 if( VOS_STATUS_SUCCESS == status )
3799 {
3800 //Add it to the hdd's session list.
3801 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3802 if( NULL == pHddAdapterNode )
3803 {
3804 status = VOS_STATUS_E_NOMEM;
3805 }
3806 else
3807 {
3808 pHddAdapterNode->pAdapter = pAdapter;
3809 status = hdd_add_adapter_back ( pHddCtx,
3810 pHddAdapterNode );
3811 }
3812 }
3813
3814 if( VOS_STATUS_SUCCESS != status )
3815 {
3816 if( NULL != pAdapter )
3817 {
3818 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3819 pAdapter = NULL;
3820 }
3821 if( NULL != pHddAdapterNode )
3822 {
3823 vos_mem_free( pHddAdapterNode );
3824 }
3825
3826 goto resume_bmps;
3827 }
3828
3829 if(VOS_STATUS_SUCCESS == status)
3830 {
3831 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3832
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003833 //Initialize the WoWL service
3834 if(!hdd_init_wowl(pAdapter))
3835 {
3836 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3837 goto err_free_netdev;
3838 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 return pAdapter;
3841
3842err_free_netdev:
3843 free_netdev(pAdapter->dev);
3844 wlan_hdd_release_intf_addr( pHddCtx,
3845 pAdapter->macAddressCurrent.bytes );
3846
3847resume_bmps:
3848 //If bmps disabled enable it
3849 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3850 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303851 if (pHddCtx->hdd_wlan_suspended)
3852 {
3853 hdd_set_pwrparams(pHddCtx);
3854 }
3855 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003856 }
3857 return NULL;
3858}
3859
3860VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3861 tANI_U8 rtnl_held )
3862{
3863 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3864 VOS_STATUS status;
3865
3866 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3867 if( VOS_STATUS_SUCCESS != status )
3868 return status;
3869
3870 while ( pCurrent->pAdapter != pAdapter )
3871 {
3872 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3873 if( VOS_STATUS_SUCCESS != status )
3874 break;
3875
3876 pCurrent = pNext;
3877 }
3878 pAdapterNode = pCurrent;
3879 if( VOS_STATUS_SUCCESS == status )
3880 {
3881 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3882 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3883 hdd_remove_adapter( pHddCtx, pAdapterNode );
3884 vos_mem_free( pAdapterNode );
3885
Jeff Johnson295189b2012-06-20 16:38:30 -07003886
3887 /* If there is a single session of STA/P2P client, re-enable BMPS */
3888 if ((!vos_concurrent_sessions_running()) &&
3889 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3890 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
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
3899 return VOS_STATUS_SUCCESS;
3900 }
3901
3902 return VOS_STATUS_E_FAILURE;
3903}
3904
3905VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3906{
3907 hdd_adapter_list_node_t *pHddAdapterNode;
3908 VOS_STATUS status;
3909
3910 ENTER();
3911
3912 do
3913 {
3914 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3915 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3916 {
3917 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3918 vos_mem_free( pHddAdapterNode );
3919 }
3920 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3921
3922 EXIT();
3923
3924 return VOS_STATUS_SUCCESS;
3925}
3926
3927void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3928{
3929 v_U8_t addIE[1] = {0};
3930
3931 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3932 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3933 eANI_BOOLEAN_FALSE) )
3934 {
3935 hddLog(LOGE,
3936 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3937 }
3938
3939 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3940 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3941 eANI_BOOLEAN_FALSE) )
3942 {
3943 hddLog(LOGE,
3944 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3945 }
3946
3947 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3948 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3949 eANI_BOOLEAN_FALSE) )
3950 {
3951 hddLog(LOGE,
3952 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3953 }
3954}
3955
3956VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3957{
3958 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3959 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3960 union iwreq_data wrqu;
3961
3962 ENTER();
3963
3964 switch(pAdapter->device_mode)
3965 {
3966 case WLAN_HDD_INFRA_STATION:
3967 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003968 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003969 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3970 {
3971 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3972 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3973 pAdapter->sessionId,
3974 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3975 else
3976 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3977 pAdapter->sessionId,
3978 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3979 //success implies disconnect command got queued up successfully
3980 if(halStatus == eHAL_STATUS_SUCCESS)
3981 {
3982 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3983 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3984 }
3985 memset(&wrqu, '\0', sizeof(wrqu));
3986 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3987 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3988 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3989 }
3990 else
3991 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05303992 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003993 }
3994
3995 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3996 {
3997 INIT_COMPLETION(pAdapter->session_close_comp_var);
3998 if (eHAL_STATUS_SUCCESS ==
3999 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4000 hdd_smeCloseSessionCallback, pAdapter))
4001 {
4002 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004003 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004004 &pAdapter->session_close_comp_var,
4005 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4006 }
4007 }
4008
4009 break;
4010
4011 case WLAN_HDD_SOFTAP:
4012 case WLAN_HDD_P2P_GO:
4013 //Any softap specific cleanup here...
4014 mutex_lock(&pHddCtx->sap_lock);
4015 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4016 {
4017 VOS_STATUS status;
4018 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4019
4020 //Stop Bss.
4021 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4022 if (VOS_IS_STATUS_SUCCESS(status))
4023 {
4024 hdd_hostapd_state_t *pHostapdState =
4025 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4026
4027 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4028
4029 if (!VOS_IS_STATUS_SUCCESS(status))
4030 {
4031 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004032 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004033 }
4034 }
4035 else
4036 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004037 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004038 }
4039 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4040
4041 if (eHAL_STATUS_FAILURE ==
4042 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4043 0, NULL, eANI_BOOLEAN_FALSE))
4044 {
4045 hddLog(LOGE,
4046 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004047 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004048 }
4049
4050 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4051 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4052 eANI_BOOLEAN_FALSE) )
4053 {
4054 hddLog(LOGE,
4055 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4056 }
4057
4058 // Reset WNI_CFG_PROBE_RSP Flags
4059 wlan_hdd_reset_prob_rspies(pAdapter);
4060 kfree(pAdapter->sessionCtx.ap.beacon);
4061 pAdapter->sessionCtx.ap.beacon = NULL;
4062 }
4063 mutex_unlock(&pHddCtx->sap_lock);
4064 break;
4065 case WLAN_HDD_MONITOR:
4066 break;
4067 default:
4068 break;
4069 }
4070
4071 EXIT();
4072 return VOS_STATUS_SUCCESS;
4073}
4074
4075VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4076{
4077 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4078 VOS_STATUS status;
4079 hdd_adapter_t *pAdapter;
4080
4081 ENTER();
4082
4083 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4084
4085 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4086 {
4087 pAdapter = pAdapterNode->pAdapter;
4088 netif_tx_disable(pAdapter->dev);
4089 netif_carrier_off(pAdapter->dev);
4090
4091 hdd_stop_adapter( pHddCtx, pAdapter );
4092
4093 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4094 pAdapterNode = pNext;
4095 }
4096
4097 EXIT();
4098
4099 return VOS_STATUS_SUCCESS;
4100}
4101
4102VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4103{
4104 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4105 VOS_STATUS status;
4106 hdd_adapter_t *pAdapter;
4107
4108 ENTER();
4109
4110 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4111
4112 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4113 {
4114 pAdapter = pAdapterNode->pAdapter;
4115 netif_tx_disable(pAdapter->dev);
4116 netif_carrier_off(pAdapter->dev);
4117
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004118 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4119
Jeff Johnson295189b2012-06-20 16:38:30 -07004120 hdd_deinit_tx_rx(pAdapter);
4121 hdd_wmm_adapter_close(pAdapter);
4122
4123 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4124 pAdapterNode = pNext;
4125 }
4126
4127 EXIT();
4128
4129 return VOS_STATUS_SUCCESS;
4130}
4131
4132VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4133{
4134 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4135 VOS_STATUS status;
4136 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304137 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004138
4139 ENTER();
4140
4141 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4142
4143 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4144 {
4145 pAdapter = pAdapterNode->pAdapter;
4146
4147 switch(pAdapter->device_mode)
4148 {
4149 case WLAN_HDD_INFRA_STATION:
4150 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004151 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304152
4153 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4154
Jeff Johnson295189b2012-06-20 16:38:30 -07004155 hdd_init_station_mode(pAdapter);
4156 /* Open the gates for HDD to receive Wext commands */
4157 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004158 pHddCtx->scan_info.mScanPending = FALSE;
4159 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004160
4161 //Trigger the initial scan
4162 hdd_wlan_initial_scan(pAdapter);
4163
4164 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304165 if (eConnectionState_Associated == connState ||
4166 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004167 {
4168 union iwreq_data wrqu;
4169 memset(&wrqu, '\0', sizeof(wrqu));
4170 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4171 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4172 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004173 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004174
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 /* indicate disconnected event to nl80211 */
4176 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4177 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304179 else if (eConnectionState_Connecting == connState)
4180 {
4181 /*
4182 * Indicate connect failure to supplicant if we were in the
4183 * process of connecting
4184 */
4185 cfg80211_connect_result(pAdapter->dev, NULL,
4186 NULL, 0, NULL, 0,
4187 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4188 GFP_KERNEL);
4189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004190 break;
4191
4192 case WLAN_HDD_SOFTAP:
4193 /* softAP can handle SSR */
4194 break;
4195
4196 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004199 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004200 break;
4201
4202 case WLAN_HDD_MONITOR:
4203 /* monitor interface start */
4204 break;
4205 default:
4206 break;
4207 }
4208
4209 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4210 pAdapterNode = pNext;
4211 }
4212
4213 EXIT();
4214
4215 return VOS_STATUS_SUCCESS;
4216}
4217
4218VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4219{
4220 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4221 hdd_adapter_t *pAdapter;
4222 VOS_STATUS status;
4223 v_U32_t roamId;
4224
4225 ENTER();
4226
4227 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4228
4229 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4230 {
4231 pAdapter = pAdapterNode->pAdapter;
4232
4233 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4234 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4235 {
4236 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4238
4239 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4240 init_completion(&pAdapter->disconnect_comp_var);
4241 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4242 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4243
4244 wait_for_completion_interruptible_timeout(
4245 &pAdapter->disconnect_comp_var,
4246 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4247
4248 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4249 pHddCtx->isAmpAllowed = VOS_FALSE;
4250 sme_RoamConnect(pHddCtx->hHal,
4251 pAdapter->sessionId, &(pWextState->roamProfile),
4252 &roamId);
4253 }
4254
4255 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4256 pAdapterNode = pNext;
4257 }
4258
4259 EXIT();
4260
4261 return VOS_STATUS_SUCCESS;
4262}
4263
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004264void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4265{
4266 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4267 VOS_STATUS status;
4268 hdd_adapter_t *pAdapter;
4269 hdd_station_ctx_t *pHddStaCtx;
4270 hdd_ap_ctx_t *pHddApCtx;
4271 hdd_hostapd_state_t * pHostapdState;
4272 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4273 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4274 const char *p2pMode = "DEV";
4275 const char *ccMode = "Standalone";
4276 int n;
4277
4278 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4279 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4280 {
4281 pAdapter = pAdapterNode->pAdapter;
4282 switch (pAdapter->device_mode) {
4283 case WLAN_HDD_INFRA_STATION:
4284 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4285 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4286 staChannel = pHddStaCtx->conn_info.operationChannel;
4287 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4288 }
4289 break;
4290 case WLAN_HDD_P2P_CLIENT:
4291 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4292 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4293 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4294 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4295 p2pMode = "CLI";
4296 }
4297 break;
4298 case WLAN_HDD_P2P_GO:
4299 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4300 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4301 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4302 p2pChannel = pHddApCtx->operatingChannel;
4303 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4304 }
4305 p2pMode = "GO";
4306 break;
4307 case WLAN_HDD_SOFTAP:
4308 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4309 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4310 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4311 apChannel = pHddApCtx->operatingChannel;
4312 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4313 }
4314 break;
4315 default:
4316 break;
4317 }
4318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4319 pAdapterNode = pNext;
4320 }
4321 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4322 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4323 }
4324 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4325 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4326 if (p2pChannel > 0) {
4327 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4328 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4329 }
4330 if (apChannel > 0) {
4331 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4332 apChannel, MAC_ADDR_ARRAY(apBssid));
4333 }
4334
4335 if (p2pChannel > 0 && apChannel > 0) {
4336 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4337 }
4338}
4339
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004340bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004341{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004342 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004343}
4344
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004345/* Once SSR is disabled then it cannot be set. */
4346void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004347{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004348 if (HDD_SSR_DISABLED == isSsrRequired)
4349 return;
4350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 isSsrRequired = value;
4352}
4353
4354VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4355 hdd_adapter_list_node_t** ppAdapterNode)
4356{
4357 VOS_STATUS status;
4358 spin_lock(&pHddCtx->hddAdapters.lock);
4359 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4360 (hdd_list_node_t**) ppAdapterNode );
4361 spin_unlock(&pHddCtx->hddAdapters.lock);
4362 return status;
4363}
4364
4365VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4366 hdd_adapter_list_node_t* pAdapterNode,
4367 hdd_adapter_list_node_t** pNextAdapterNode)
4368{
4369 VOS_STATUS status;
4370 spin_lock(&pHddCtx->hddAdapters.lock);
4371 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4372 (hdd_list_node_t*) pAdapterNode,
4373 (hdd_list_node_t**)pNextAdapterNode );
4374
4375 spin_unlock(&pHddCtx->hddAdapters.lock);
4376 return status;
4377}
4378
4379VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4380 hdd_adapter_list_node_t* pAdapterNode)
4381{
4382 VOS_STATUS status;
4383 spin_lock(&pHddCtx->hddAdapters.lock);
4384 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4385 &pAdapterNode->node );
4386 spin_unlock(&pHddCtx->hddAdapters.lock);
4387 return status;
4388}
4389
4390VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4391 hdd_adapter_list_node_t** ppAdapterNode)
4392{
4393 VOS_STATUS status;
4394 spin_lock(&pHddCtx->hddAdapters.lock);
4395 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4396 (hdd_list_node_t**) ppAdapterNode );
4397 spin_unlock(&pHddCtx->hddAdapters.lock);
4398 return status;
4399}
4400
4401VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4402 hdd_adapter_list_node_t* pAdapterNode)
4403{
4404 VOS_STATUS status;
4405 spin_lock(&pHddCtx->hddAdapters.lock);
4406 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4407 (hdd_list_node_t*) pAdapterNode );
4408 spin_unlock(&pHddCtx->hddAdapters.lock);
4409 return status;
4410}
4411
4412VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4413 hdd_adapter_list_node_t* pAdapterNode)
4414{
4415 VOS_STATUS status;
4416 spin_lock(&pHddCtx->hddAdapters.lock);
4417 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4418 (hdd_list_node_t*) pAdapterNode );
4419 spin_unlock(&pHddCtx->hddAdapters.lock);
4420 return status;
4421}
4422
4423hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4424 tSirMacAddr macAddr )
4425{
4426 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4427 hdd_adapter_t *pAdapter;
4428 VOS_STATUS status;
4429
4430 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4431
4432 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4433 {
4434 pAdapter = pAdapterNode->pAdapter;
4435
4436 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4437 macAddr, sizeof(tSirMacAddr) ) )
4438 {
4439 return pAdapter;
4440 }
4441 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4442 pAdapterNode = pNext;
4443 }
4444
4445 return NULL;
4446
4447}
4448
4449hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4450{
4451 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4452 hdd_adapter_t *pAdapter;
4453 VOS_STATUS status;
4454
4455 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4456
4457 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4458 {
4459 pAdapter = pAdapterNode->pAdapter;
4460
4461 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4462 IFNAMSIZ ) )
4463 {
4464 return pAdapter;
4465 }
4466 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4467 pAdapterNode = pNext;
4468 }
4469
4470 return NULL;
4471
4472}
4473
4474hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4475{
4476 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4477 hdd_adapter_t *pAdapter;
4478 VOS_STATUS status;
4479
4480 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4481
4482 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4483 {
4484 pAdapter = pAdapterNode->pAdapter;
4485
4486 if( pAdapter && (mode == pAdapter->device_mode) )
4487 {
4488 return pAdapter;
4489 }
4490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4491 pAdapterNode = pNext;
4492 }
4493
4494 return NULL;
4495
4496}
4497
4498//Remove this function later
4499hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4500{
4501 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4502 hdd_adapter_t *pAdapter;
4503 VOS_STATUS status;
4504
4505 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4506
4507 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4508 {
4509 pAdapter = pAdapterNode->pAdapter;
4510
4511 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4512 {
4513 return pAdapter;
4514 }
4515
4516 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4517 pAdapterNode = pNext;
4518 }
4519
4520 return NULL;
4521
4522}
4523
Jeff Johnson295189b2012-06-20 16:38:30 -07004524/**---------------------------------------------------------------------------
4525
4526 \brief hdd_set_monitor_tx_adapter() -
4527
4528 This API initializes the adapter to be used while transmitting on monitor
4529 adapter.
4530
4531 \param - pHddCtx - Pointer to the HDD context.
4532 pAdapter - Adapter that will used for TX. This can be NULL.
4533 \return - None.
4534 --------------------------------------------------------------------------*/
4535void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4536{
4537 hdd_adapter_t *pMonAdapter;
4538
4539 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4540
4541 if( NULL != pMonAdapter )
4542 {
4543 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4544 }
4545}
Jeff Johnson295189b2012-06-20 16:38:30 -07004546/**---------------------------------------------------------------------------
4547
4548 \brief hdd_select_queue() -
4549
4550 This API returns the operating channel of the requested device mode
4551
4552 \param - pHddCtx - Pointer to the HDD context.
4553 - mode - Device mode for which operating channel is required
4554 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4555 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4556 \return - channel number. "0" id the requested device is not found OR it is not connected.
4557 --------------------------------------------------------------------------*/
4558v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4559{
4560 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4561 VOS_STATUS status;
4562 hdd_adapter_t *pAdapter;
4563 v_U8_t operatingChannel = 0;
4564
4565 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4566
4567 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4568 {
4569 pAdapter = pAdapterNode->pAdapter;
4570
4571 if( mode == pAdapter->device_mode )
4572 {
4573 switch(pAdapter->device_mode)
4574 {
4575 case WLAN_HDD_INFRA_STATION:
4576 case WLAN_HDD_P2P_CLIENT:
4577 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4578 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4579 break;
4580 case WLAN_HDD_SOFTAP:
4581 case WLAN_HDD_P2P_GO:
4582 /*softap connection info */
4583 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4584 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4585 break;
4586 default:
4587 break;
4588 }
4589
4590 break; //Found the device of interest. break the loop
4591 }
4592
4593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4594 pAdapterNode = pNext;
4595 }
4596 return operatingChannel;
4597}
4598
4599#ifdef WLAN_FEATURE_PACKET_FILTERING
4600/**---------------------------------------------------------------------------
4601
4602 \brief hdd_set_multicast_list() -
4603
4604 This used to set the multicast address list.
4605
4606 \param - dev - Pointer to the WLAN device.
4607 - skb - Pointer to OS packet (sk_buff).
4608 \return - success/fail
4609
4610 --------------------------------------------------------------------------*/
4611static void hdd_set_multicast_list(struct net_device *dev)
4612{
4613 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004614 int mc_count;
4615 int i = 0;
4616 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304617
4618 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004619 {
4620 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304621 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004622 return;
4623 }
4624
4625 if (dev->flags & IFF_ALLMULTI)
4626 {
4627 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004628 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304629 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 }
4631 else
4632 {
4633 mc_count = netdev_mc_count(dev);
4634 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004635 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004636 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4637 {
4638 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004639 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304640 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 return;
4642 }
4643
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304644 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004645
4646 netdev_for_each_mc_addr(ha, dev) {
4647 if (i == mc_count)
4648 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304649 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4650 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4651 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004652 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304653 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 i++;
4655 }
4656 }
4657 return;
4658}
4659#endif
4660
4661/**---------------------------------------------------------------------------
4662
4663 \brief hdd_select_queue() -
4664
4665 This function is registered with the Linux OS for network
4666 core to decide which queue to use first.
4667
4668 \param - dev - Pointer to the WLAN device.
4669 - skb - Pointer to OS packet (sk_buff).
4670 \return - ac, Queue Index/access category corresponding to UP in IP header
4671
4672 --------------------------------------------------------------------------*/
4673v_U16_t hdd_select_queue(struct net_device *dev,
4674 struct sk_buff *skb)
4675{
4676 return hdd_wmm_select_queue(dev, skb);
4677}
4678
4679
4680/**---------------------------------------------------------------------------
4681
4682 \brief hdd_wlan_initial_scan() -
4683
4684 This function triggers the initial scan
4685
4686 \param - pAdapter - Pointer to the HDD adapter.
4687
4688 --------------------------------------------------------------------------*/
4689void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4690{
4691 tCsrScanRequest scanReq;
4692 tCsrChannelInfo channelInfo;
4693 eHalStatus halStatus;
4694 unsigned long scanId;
4695 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4696
4697 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4698 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4699 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4700
4701 if(sme_Is11dSupported(pHddCtx->hHal))
4702 {
4703 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4704 if ( HAL_STATUS_SUCCESS( halStatus ) )
4705 {
4706 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4707 if( !scanReq.ChannelInfo.ChannelList )
4708 {
4709 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4710 vos_mem_free(channelInfo.ChannelList);
4711 return;
4712 }
4713 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4714 channelInfo.numOfChannels);
4715 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4716 vos_mem_free(channelInfo.ChannelList);
4717 }
4718
4719 scanReq.scanType = eSIR_PASSIVE_SCAN;
4720 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4721 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4722 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4723 }
4724 else
4725 {
4726 scanReq.scanType = eSIR_ACTIVE_SCAN;
4727 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4728 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4729 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4730 }
4731
4732 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4733 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4734 {
4735 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4736 __func__, halStatus );
4737 }
4738
4739 if(sme_Is11dSupported(pHddCtx->hHal))
4740 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4741}
4742
4743struct fullPowerContext
4744{
4745 struct completion completion;
4746 unsigned int magic;
4747};
4748#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4749
4750/**---------------------------------------------------------------------------
4751
4752 \brief hdd_full_power_callback() - HDD full power callback function
4753
4754 This is the function invoked by SME to inform the result of a full power
4755 request issued by HDD
4756
4757 \param - callbackcontext - Pointer to cookie
4758 \param - status - result of request
4759
4760 \return - None
4761
4762 --------------------------------------------------------------------------*/
4763static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4764{
4765 struct fullPowerContext *pContext = callbackContext;
4766
4767 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304768 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004769
4770 if (NULL == callbackContext)
4771 {
4772 hddLog(VOS_TRACE_LEVEL_ERROR,
4773 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004774 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 return;
4776 }
4777
4778 /* there is a race condition that exists between this callback function
4779 and the caller since the caller could time out either before or
4780 while this code is executing. we'll assume the timeout hasn't
4781 occurred, but we'll verify that right before we save our work */
4782
4783 if (POWER_CONTEXT_MAGIC != pContext->magic)
4784 {
4785 /* the caller presumably timed out so there is nothing we can do */
4786 hddLog(VOS_TRACE_LEVEL_WARN,
4787 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004788 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 return;
4790 }
4791
4792 /* the race is on. caller could have timed out immediately after
4793 we verified the magic, but if so, caller will wait a short time
4794 for us to notify the caller, so the context will stay valid */
4795 complete(&pContext->completion);
4796}
4797
4798/**---------------------------------------------------------------------------
4799
4800 \brief hdd_wlan_exit() - HDD WLAN exit function
4801
4802 This is the driver exit point (invoked during rmmod)
4803
4804 \param - pHddCtx - Pointer to the HDD Context
4805
4806 \return - None
4807
4808 --------------------------------------------------------------------------*/
4809void hdd_wlan_exit(hdd_context_t *pHddCtx)
4810{
4811 eHalStatus halStatus;
4812 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4813 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304814 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004816 struct fullPowerContext powerContext;
4817 long lrc;
4818
4819 ENTER();
4820
Jeff Johnson88ba7742013-02-27 14:36:02 -08004821 if (VOS_FTM_MODE != hdd_get_conparam())
4822 {
4823 // Unloading, restart logic is no more required.
4824 wlan_hdd_restart_deinit(pHddCtx);
4825 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004826
Jeff Johnson295189b2012-06-20 16:38:30 -07004827 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004828 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 {
4831 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4832 WLAN_HDD_INFRA_STATION);
4833 if (pAdapter == NULL)
4834 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4835
4836 if (pAdapter != NULL)
4837 {
4838 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4839 hdd_UnregisterWext(pAdapter->dev);
4840 }
4841 }
4842 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004843
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004845 {
4846 wlan_hdd_ftm_close(pHddCtx);
4847 goto free_hdd_ctx;
4848 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004849 //Stop the Interface TX queue.
4850 //netif_tx_disable(pWlanDev);
4851 //netif_carrier_off(pWlanDev);
4852
Jeff Johnson295189b2012-06-20 16:38:30 -07004853 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4854 {
4855 pAdapter = hdd_get_adapter(pHddCtx,
4856 WLAN_HDD_SOFTAP);
4857 }
4858 else
4859 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 {
4862 pAdapter = hdd_get_adapter(pHddCtx,
4863 WLAN_HDD_INFRA_STATION);
4864 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 /* DeRegister with platform driver as client for Suspend/Resume */
4867 vosStatus = hddDeregisterPmOps(pHddCtx);
4868 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4869 {
4870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4871 VOS_ASSERT(0);
4872 }
4873
4874 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4875 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4876 {
4877 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004879
4880 // Cancel any outstanding scan requests. We are about to close all
4881 // of our adapters, but an adapter structure is what SME passes back
4882 // to our callback function. Hence if there are any outstanding scan
4883 // requests then there is a race condition between when the adapter
4884 // is closed and when the callback is invoked. We try to resolve that
4885 // race condition here by canceling any outstanding scans before we
4886 // close the adapters.
4887 // Note that the scans may be cancelled in an asynchronous manner, so
4888 // ideally there needs to be some kind of synchronization. Rather than
4889 // introduce a new synchronization here, we will utilize the fact that
4890 // we are about to Request Full Power, and since that is synchronized,
4891 // the expectation is that by the time Request Full Power has completed,
4892 // all scans will be cancelled.
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304893 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004894
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004895 //Stop the traffic monitor timer
4896 if ( VOS_TIMER_STATE_RUNNING ==
4897 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4898 {
4899 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4900 }
4901
4902 // Destroy the traffic monitor timer
4903 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4904 &pHddCtx->tx_rx_trafficTmr)))
4905 {
4906 hddLog(VOS_TRACE_LEVEL_ERROR,
4907 "%s: Cannot deallocate Traffic monitor timer", __func__);
4908 }
4909
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 //Disable IMPS/BMPS as we do not want the device to enter any power
4911 //save mode during shutdown
4912 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4913 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4914 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4915
4916 //Ensure that device is in full power as we will touch H/W during vos_Stop
4917 init_completion(&powerContext.completion);
4918 powerContext.magic = POWER_CONTEXT_MAGIC;
4919
4920 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4921 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4922
4923 if (eHAL_STATUS_SUCCESS != halStatus)
4924 {
4925 if (eHAL_STATUS_PMC_PENDING == halStatus)
4926 {
4927 /* request was sent -- wait for the response */
4928 lrc = wait_for_completion_interruptible_timeout(
4929 &powerContext.completion,
4930 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4931 /* either we have a response or we timed out
4932 either way, first invalidate our magic */
4933 powerContext.magic = 0;
4934 if (lrc <= 0)
4935 {
4936 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004937 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004938 /* there is a race condition such that the callback
4939 function could be executing at the same time we are. of
4940 primary concern is if the callback function had already
4941 verified the "magic" but hasn't yet set the completion
4942 variable. Since the completion variable is on our
4943 stack, we'll delay just a bit to make sure the data is
4944 still valid if that is the case */
4945 msleep(50);
4946 }
4947 }
4948 else
4949 {
4950 hddLog(VOS_TRACE_LEVEL_ERROR,
4951 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004952 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004953 VOS_ASSERT(0);
4954 /* continue -- need to clean up as much as possible */
4955 }
4956 }
4957
Yue Ma0d4891e2013-08-06 17:01:45 -07004958 hdd_debugfs_exit(pHddCtx);
4959
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 // Unregister the Net Device Notifier
4961 unregister_netdevice_notifier(&hdd_netdev_notifier);
4962
Jeff Johnson295189b2012-06-20 16:38:30 -07004963 hdd_stop_all_adapters( pHddCtx );
4964
Jeff Johnson295189b2012-06-20 16:38:30 -07004965#ifdef WLAN_BTAMP_FEATURE
4966 vosStatus = WLANBAP_Stop(pVosContext);
4967 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4968 {
4969 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4970 "%s: Failed to stop BAP",__func__);
4971 }
4972#endif //WLAN_BTAMP_FEATURE
4973
4974 //Stop all the modules
4975 vosStatus = vos_stop( pVosContext );
4976 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4977 {
4978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4979 "%s: Failed to stop VOSS",__func__);
4980 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4981 }
4982
Jeff Johnson295189b2012-06-20 16:38:30 -07004983 //Assert Deep sleep signal now to put Libra HW in lowest power state
4984 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4985 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4986
4987 //Vote off any PMIC voltage supplies
4988 vos_chipPowerDown(NULL, NULL, NULL);
4989
4990 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4991
Leo Chang59cdc7e2013-07-10 10:08:21 -07004992
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004995
4996 //Close the scheduler before calling vos_close to make sure no thread is
4997 // scheduled after the each module close is called i.e after all the data
4998 // structures are freed.
4999 vosStatus = vos_sched_close( pVosContext );
5000 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5001 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5002 "%s: Failed to close VOSS Scheduler",__func__);
5003 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5004 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005005#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005006#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5007 /* Destroy the wake lock */
5008 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5009#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005010 /* Destroy the wake lock */
5011 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005012#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005013
5014 //Close VOSS
5015 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5016 vos_close(pVosContext);
5017
Jeff Johnson295189b2012-06-20 16:38:30 -07005018 //Close Watchdog
5019 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5020 vos_watchdog_close(pVosContext);
5021
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305022 //Clean up HDD Nlink Service
5023 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005024#ifdef WLAN_KD_READY_NOTIFIER
5025 nl_srv_exit(pHddCtx->ptt_pid);
5026#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305027 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005028#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305029
Jeff Johnson295189b2012-06-20 16:38:30 -07005030 /* Cancel the vote for XO Core ON.
5031 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5032 * exited at this point
5033 */
5034 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5035 " when WLAN is turned OFF\n");
5036 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5037 {
5038 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5039 " Not returning failure."
5040 " Power consumed will be high\n");
5041 }
5042
5043 hdd_close_all_adapters( pHddCtx );
5044
5045
5046 //Free up dynamically allocated members inside HDD Adapter
5047 kfree(pHddCtx->cfg_ini);
5048 pHddCtx->cfg_ini= NULL;
5049
5050 /* free the power on lock from platform driver */
5051 if (free_riva_power_on_lock("wlan"))
5052 {
5053 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5054 __func__);
5055 }
5056
Jeff Johnson88ba7742013-02-27 14:36:02 -08005057free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005058 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005059 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005060 if (hdd_is_ssr_required())
5061 {
5062 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005063 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 msleep(5000);
5065 }
5066 hdd_set_ssr_required (VOS_FALSE);
5067}
5068
5069
5070/**---------------------------------------------------------------------------
5071
5072 \brief hdd_update_config_from_nv() - Function to update the contents of
5073 the running configuration with parameters taken from NV storage
5074
5075 \param - pHddCtx - Pointer to the HDD global context
5076
5077 \return - VOS_STATUS_SUCCESS if successful
5078
5079 --------------------------------------------------------------------------*/
5080static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5081{
Jeff Johnson295189b2012-06-20 16:38:30 -07005082 v_BOOL_t itemIsValid = VOS_FALSE;
5083 VOS_STATUS status;
5084 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5085 v_U8_t macLoop;
5086
5087 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5088 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5089 if(status != VOS_STATUS_SUCCESS)
5090 {
5091 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5092 return VOS_STATUS_E_FAILURE;
5093 }
5094
5095 if (itemIsValid == VOS_TRUE)
5096 {
5097 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5098 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5099 VOS_MAX_CONCURRENCY_PERSONA);
5100 if(status != VOS_STATUS_SUCCESS)
5101 {
5102 /* Get MAC from NV fail, not update CFG info
5103 * INI MAC value will be used for MAC setting */
5104 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5105 return VOS_STATUS_E_FAILURE;
5106 }
5107
5108 /* If first MAC is not valid, treat all others are not valid
5109 * Then all MACs will be got from ini file */
5110 if(vos_is_macaddr_zero(&macFromNV[0]))
5111 {
5112 /* MAC address in NV file is not configured yet */
5113 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5114 return VOS_STATUS_E_INVAL;
5115 }
5116
5117 /* Get MAC address from NV, update CFG info */
5118 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5119 {
5120 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5121 {
5122 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5123 /* This MAC is not valid, skip it
5124 * This MAC will be got from ini file */
5125 }
5126 else
5127 {
5128 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5129 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5130 VOS_MAC_ADDR_SIZE);
5131 }
5132 }
5133 }
5134 else
5135 {
5136 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5137 return VOS_STATUS_E_FAILURE;
5138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005139
Jeff Johnson295189b2012-06-20 16:38:30 -07005140
5141 return VOS_STATUS_SUCCESS;
5142}
5143
5144/**---------------------------------------------------------------------------
5145
5146 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5147
5148 \param - pAdapter - Pointer to the HDD
5149
5150 \return - None
5151
5152 --------------------------------------------------------------------------*/
5153VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5154{
5155 eHalStatus halStatus;
5156 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305157 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005158
Jeff Johnson295189b2012-06-20 16:38:30 -07005159
5160 // Send ready indication to the HDD. This will kick off the MAC
5161 // into a 'running' state and should kick off an initial scan.
5162 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5163 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5164 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 "code %08d [x%08x]",__func__, halStatus, halStatus );
5167 return VOS_STATUS_E_FAILURE;
5168 }
5169
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305170 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5172 // And RIVA will crash
5173 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5174 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305175 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5176 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5177
5178
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 return VOS_STATUS_SUCCESS;
5180}
5181
Jeff Johnson295189b2012-06-20 16:38:30 -07005182/* wake lock APIs for HDD */
5183void hdd_prevent_suspend(void)
5184{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005185#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005187#else
5188 wcnss_prevent_suspend();
5189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005190}
5191
5192void hdd_allow_suspend(void)
5193{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005194#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005195 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005196#else
5197 wcnss_allow_suspend();
5198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005199}
5200
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005201void hdd_allow_suspend_timeout(v_U32_t timeout)
5202{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005203#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005204 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005205#else
5206 /* Do nothing as there is no API in wcnss for timeout*/
5207#endif
5208}
5209
Jeff Johnson295189b2012-06-20 16:38:30 -07005210/**---------------------------------------------------------------------------
5211
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005212 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5213 information between Host and Riva
5214
5215 This function gets reported version of FW
5216 It also finds the version of Riva headers used to compile the host
5217 It compares the above two and prints a warning if they are different
5218 It gets the SW and HW version string
5219 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5220 indicating the features they support through a bitmap
5221
5222 \param - pHddCtx - Pointer to HDD context
5223
5224 \return - void
5225
5226 --------------------------------------------------------------------------*/
5227
5228void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5229{
5230
5231 tSirVersionType versionCompiled;
5232 tSirVersionType versionReported;
5233 tSirVersionString versionString;
5234 tANI_U8 fwFeatCapsMsgSupported = 0;
5235 VOS_STATUS vstatus;
5236
5237 /* retrieve and display WCNSS version information */
5238 do {
5239
5240 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5241 &versionCompiled);
5242 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5243 {
5244 hddLog(VOS_TRACE_LEVEL_FATAL,
5245 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005246 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005247 break;
5248 }
5249
5250 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5251 &versionReported);
5252 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5253 {
5254 hddLog(VOS_TRACE_LEVEL_FATAL,
5255 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005256 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005257 break;
5258 }
5259
5260 if ((versionCompiled.major != versionReported.major) ||
5261 (versionCompiled.minor != versionReported.minor) ||
5262 (versionCompiled.version != versionReported.version) ||
5263 (versionCompiled.revision != versionReported.revision))
5264 {
5265 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5266 "Host expected %u.%u.%u.%u\n",
5267 WLAN_MODULE_NAME,
5268 (int)versionReported.major,
5269 (int)versionReported.minor,
5270 (int)versionReported.version,
5271 (int)versionReported.revision,
5272 (int)versionCompiled.major,
5273 (int)versionCompiled.minor,
5274 (int)versionCompiled.version,
5275 (int)versionCompiled.revision);
5276 }
5277 else
5278 {
5279 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5280 WLAN_MODULE_NAME,
5281 (int)versionReported.major,
5282 (int)versionReported.minor,
5283 (int)versionReported.version,
5284 (int)versionReported.revision);
5285 }
5286
5287 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5288 versionString,
5289 sizeof(versionString));
5290 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5291 {
5292 hddLog(VOS_TRACE_LEVEL_FATAL,
5293 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005294 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005295 break;
5296 }
5297
5298 pr_info("%s: WCNSS software version %s\n",
5299 WLAN_MODULE_NAME, versionString);
5300
5301 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5302 versionString,
5303 sizeof(versionString));
5304 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5305 {
5306 hddLog(VOS_TRACE_LEVEL_FATAL,
5307 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005308 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005309 break;
5310 }
5311
5312 pr_info("%s: WCNSS hardware version %s\n",
5313 WLAN_MODULE_NAME, versionString);
5314
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005315 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5316 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005317 send the message only if it the riva is 1.1
5318 minor numbers for different riva branches:
5319 0 -> (1.0)Mainline Build
5320 1 -> (1.1)Mainline Build
5321 2->(1.04) Stability Build
5322 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005323 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005324 ((versionReported.minor>=1) && (versionReported.version>=1)))
5325 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5326 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005327
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005328 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005329 {
5330#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5331 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5332 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5333#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005334 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5335 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5336 {
5337 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5338 }
5339
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005340 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005341 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005342
5343 } while (0);
5344
5345}
5346
5347/**---------------------------------------------------------------------------
5348
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305349 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5350
5351 \param - pHddCtx - Pointer to the hdd context
5352
5353 \return - true if hardware supports 5GHz
5354
5355 --------------------------------------------------------------------------*/
5356static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5357{
5358 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5359 * then hardware support 5Ghz.
5360 */
5361 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5362 {
5363 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5364 return true;
5365 }
5366 else
5367 {
5368 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5369 __func__);
5370 return false;
5371 }
5372}
5373
5374
5375/**---------------------------------------------------------------------------
5376
Jeff Johnson295189b2012-06-20 16:38:30 -07005377 \brief hdd_wlan_startup() - HDD init function
5378
5379 This is the driver startup code executed once a WLAN device has been detected
5380
5381 \param - dev - Pointer to the underlying device
5382
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005383 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005384
5385 --------------------------------------------------------------------------*/
5386
5387int hdd_wlan_startup(struct device *dev )
5388{
5389 VOS_STATUS status;
5390 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005391 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 hdd_context_t *pHddCtx = NULL;
5393 v_CONTEXT_t pVosContext= NULL;
5394#ifdef WLAN_BTAMP_FEATURE
5395 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5396 WLANBAP_ConfigType btAmpConfig;
5397 hdd_config_t *pConfig;
5398#endif
5399 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005401
5402 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 /*
5404 * cfg80211: wiphy allocation
5405 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305406 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005407
5408 if(wiphy == NULL)
5409 {
5410 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005411 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 }
5413
5414 pHddCtx = wiphy_priv(wiphy);
5415
Jeff Johnson295189b2012-06-20 16:38:30 -07005416 //Initialize the adapter context to zeros.
5417 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5418
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005420 hdd_prevent_suspend();
5421 pHddCtx->isLoadUnloadInProgress = TRUE;
5422
5423 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5424
5425 /*Get vos context here bcoz vos_open requires it*/
5426 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5427
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005428 if(pVosContext == NULL)
5429 {
5430 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5431 goto err_free_hdd_context;
5432 }
5433
Jeff Johnson295189b2012-06-20 16:38:30 -07005434 //Save the Global VOSS context in adapter context for future.
5435 pHddCtx->pvosContext = pVosContext;
5436
5437 //Save the adapter context in global context for future.
5438 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5439
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 pHddCtx->parent_dev = dev;
5441
5442 init_completion(&pHddCtx->full_pwr_comp_var);
5443 init_completion(&pHddCtx->standby_comp_var);
5444 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005445 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005446 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +05305447 init_completion(&pHddCtx->driver_crda_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005448
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305449 spin_lock_init(&pHddCtx->schedScan_lock);
5450
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5452
5453 // Load all config first as TL config is needed during vos_open
5454 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5455 if(pHddCtx->cfg_ini == NULL)
5456 {
5457 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5458 goto err_free_hdd_context;
5459 }
5460
5461 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5462
5463 // Read and parse the qcom_cfg.ini file
5464 status = hdd_parse_config_ini( pHddCtx );
5465 if ( VOS_STATUS_SUCCESS != status )
5466 {
5467 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5468 __func__, WLAN_INI_FILE);
5469 goto err_config;
5470 }
5471
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305472 /* INI has been read, initialise the configuredMcastBcastFilter with
5473 * INI value as this will serve as the default value
5474 */
5475 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5476 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5477 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305478
5479 if (false == hdd_is_5g_supported(pHddCtx))
5480 {
5481 //5Ghz is not supported.
5482 if (1 != pHddCtx->cfg_ini->nBandCapability)
5483 {
5484 hddLog(VOS_TRACE_LEVEL_INFO,
5485 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5486 pHddCtx->cfg_ini->nBandCapability = 1;
5487 }
5488 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305489
5490 /* If SNR Monitoring is enabled, FW has to parse all beacons
5491 * for calcaluting and storing the average SNR, so set Nth beacon
5492 * filter to 1 to enable FW to parse all the beaocons
5493 */
5494 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5495 {
5496 /* The log level is deliberately set to WARN as overriding
5497 * nthBeaconFilter to 1 will increase power cosumption and this
5498 * might just prove helpful to detect the power issue.
5499 */
5500 hddLog(VOS_TRACE_LEVEL_WARN,
5501 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5502 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5503 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305505 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305507 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 {
5509 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305510 "%s: wlan_hdd_cfg80211_init return failure", __func__);
5511 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005513
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005514 // Update VOS trace levels based upon the cfg.ini
5515 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5516 pHddCtx->cfg_ini->vosTraceEnableBAP);
5517 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5518 pHddCtx->cfg_ini->vosTraceEnableTL);
5519 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5520 pHddCtx->cfg_ini->vosTraceEnableWDI);
5521 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5522 pHddCtx->cfg_ini->vosTraceEnableHDD);
5523 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5524 pHddCtx->cfg_ini->vosTraceEnableSME);
5525 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5526 pHddCtx->cfg_ini->vosTraceEnablePE);
5527 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5528 pHddCtx->cfg_ini->vosTraceEnableWDA);
5529 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5530 pHddCtx->cfg_ini->vosTraceEnableSYS);
5531 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5532 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005533 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5534 pHddCtx->cfg_ini->vosTraceEnableSAP);
5535 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5536 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005537
Jeff Johnson295189b2012-06-20 16:38:30 -07005538 // Update WDI trace levels based upon the cfg.ini
5539 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5540 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5541 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5542 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5543 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5544 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5545 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5546 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005547
Jeff Johnson88ba7742013-02-27 14:36:02 -08005548 if (VOS_FTM_MODE == hdd_get_conparam())
5549 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5551 {
5552 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5553 goto err_free_hdd_context;
5554 }
5555 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5556 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005557 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005558
Jeff Johnson88ba7742013-02-27 14:36:02 -08005559 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5561 {
5562 status = vos_watchdog_open(pVosContext,
5563 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5564
5565 if(!VOS_IS_STATUS_SUCCESS( status ))
5566 {
5567 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305568 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 }
5570 }
5571
5572 pHddCtx->isLogpInProgress = FALSE;
5573 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5574
Jeff Johnson295189b2012-06-20 16:38:30 -07005575 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5576 if(!VOS_IS_STATUS_SUCCESS(status))
5577 {
5578 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005579 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 }
5581
Jeff Johnson295189b2012-06-20 16:38:30 -07005582 status = vos_open( &pVosContext, 0);
5583 if ( !VOS_IS_STATUS_SUCCESS( status ))
5584 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005585 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5586 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 }
5588
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5590
5591 if ( NULL == pHddCtx->hHal )
5592 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005593 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005594 goto err_vosclose;
5595 }
5596
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005597 status = vos_preStart( pHddCtx->pvosContext );
5598 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5599 {
5600 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5601 goto err_vosclose;
5602 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005603
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005604 /* Note that the vos_preStart() sequence triggers the cfg download.
5605 The cfg download must occur before we update the SME config
5606 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 status = hdd_set_sme_config( pHddCtx );
5608
5609 if ( VOS_STATUS_SUCCESS != status )
5610 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005611 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5612 goto err_vosclose;
5613 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005614
5615 //Initialize the WMM module
5616 status = hdd_wmm_init(pHddCtx);
5617 if (!VOS_IS_STATUS_SUCCESS(status))
5618 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005619 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005620 goto err_vosclose;
5621 }
5622
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 /* In the integrated architecture we update the configuration from
5624 the INI file and from NV before vOSS has been started so that
5625 the final contents are available to send down to the cCPU */
5626
5627 // Apply the cfg.ini to cfg.dat
5628 if (FALSE == hdd_update_config_dat(pHddCtx))
5629 {
5630 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5631 goto err_vosclose;
5632 }
5633
5634 // Apply the NV to cfg.dat
5635 /* Prima Update MAC address only at here */
5636 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5637 {
5638#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5639 /* There was not a valid set of MAC Addresses in NV. See if the
5640 default addresses were modified by the cfg.ini settings. If so,
5641 we'll use them, but if not, we'll autogenerate a set of MAC
5642 addresses based upon the device serial number */
5643
5644 static const v_MACADDR_t default_address =
5645 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5646 unsigned int serialno;
5647 int i;
5648
5649 serialno = wcnss_get_serial_number();
5650 if ((0 != serialno) &&
5651 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5652 sizeof(default_address))))
5653 {
5654 /* cfg.ini has the default address, invoke autogen logic */
5655
5656 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5657 bytes of the serial number that can be used to generate
5658 the other 3 bytes of the MAC address. Mask off all but
5659 the lower 3 bytes (this will also make sure we don't
5660 overflow in the next step) */
5661 serialno &= 0x00FFFFFF;
5662
5663 /* we need a unique address for each session */
5664 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5665
5666 /* autogen all addresses */
5667 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5668 {
5669 /* start with the entire default address */
5670 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5671 /* then replace the lower 3 bytes */
5672 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5673 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5674 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5675
5676 serialno++;
5677 }
5678
5679 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5680 MAC_ADDRESS_STR,
5681 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5682 }
5683 else
5684#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5685 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005686 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 "%s: Invalid MAC address in NV, using MAC from ini file "
5688 MAC_ADDRESS_STR, __func__,
5689 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5690 }
5691 }
5692 {
5693 eHalStatus halStatus;
5694 // Set the MAC Address
5695 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5696 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5697 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5698 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5699
5700 if (!HAL_STATUS_SUCCESS( halStatus ))
5701 {
5702 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5703 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005704 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005705 }
5706 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005707
5708 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5709 Note: Firmware image will be read and downloaded inside vos_start API */
5710 status = vos_start( pHddCtx->pvosContext );
5711 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5712 {
5713 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5714 goto err_vosclose;
5715 }
5716
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005717 /* Exchange capability info between Host and FW and also get versioning info from FW */
5718 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005719
5720 status = hdd_post_voss_start_config( pHddCtx );
5721 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5722 {
5723 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5724 __func__);
5725 goto err_vosstop;
5726 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305727 wlan_hdd_cfg80211_update_reg_info( wiphy );
5728
5729 /* registration of wiphy dev with cfg80211 */
5730 if (0 > wlan_hdd_cfg80211_register(wiphy))
5731 {
5732 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5733 goto err_vosstop;
5734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005735
Jeff Johnson295189b2012-06-20 16:38:30 -07005736 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5737 {
5738 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5739 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5740 }
5741 else
5742 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5744 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5745 if (pAdapter != NULL)
5746 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305747 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005748 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305749 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5750 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5751 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005752
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305753 /* Generate the P2P Device Address. This consists of the device's
5754 * primary MAC address with the locally administered bit set.
5755 */
5756 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005757 }
5758 else
5759 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305760 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5761 if (p2p_dev_addr != NULL)
5762 {
5763 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5764 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5765 }
5766 else
5767 {
5768 hddLog(VOS_TRACE_LEVEL_FATAL,
5769 "%s: Failed to allocate mac_address for p2p_device",
5770 __func__);
5771 goto err_close_adapter;
5772 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005773 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005774
5775 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5776 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5777 if ( NULL == pP2pAdapter )
5778 {
5779 hddLog(VOS_TRACE_LEVEL_FATAL,
5780 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005781 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005782 goto err_close_adapter;
5783 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005784 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005786
5787 if( pAdapter == NULL )
5788 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005789 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5790 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005792
Jeff Johnson295189b2012-06-20 16:38:30 -07005793#ifdef WLAN_BTAMP_FEATURE
5794 vStatus = WLANBAP_Open(pVosContext);
5795 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5796 {
5797 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5798 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005799 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005800 }
5801
5802 vStatus = BSL_Init(pVosContext);
5803 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5804 {
5805 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5806 "%s: Failed to Init BSL",__func__);
5807 goto err_bap_close;
5808 }
5809 vStatus = WLANBAP_Start(pVosContext);
5810 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5811 {
5812 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5813 "%s: Failed to start TL",__func__);
5814 goto err_bap_close;
5815 }
5816
5817 pConfig = pHddCtx->cfg_ini;
5818 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5819 status = WLANBAP_SetConfig(&btAmpConfig);
5820
5821#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005822
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005823#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5824 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5825 {
5826 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5827 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5828 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5829 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5830 }
5831#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005832#ifdef FEATURE_WLAN_SCAN_PNO
5833 /*SME must send channel update configuration to RIVA*/
5834 sme_UpdateChannelConfig(pHddCtx->hHal);
5835#endif
5836
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 /* Register with platform driver as client for Suspend/Resume */
5838 status = hddRegisterPmOps(pHddCtx);
5839 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5840 {
5841 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5842#ifdef WLAN_BTAMP_FEATURE
5843 goto err_bap_stop;
5844#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005845 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005846#endif //WLAN_BTAMP_FEATURE
5847 }
5848
Yue Ma0d4891e2013-08-06 17:01:45 -07005849 /* Open debugfs interface */
5850 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5851 {
5852 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5853 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07005854 }
5855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 /* Register TM level change handler function to the platform */
5857 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5858 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5859 {
5860 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5861 goto err_unregister_pmops;
5862 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005863
5864 /* register for riva power on lock to platform driver */
5865 if (req_riva_power_on_lock("wlan"))
5866 {
5867 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5868 __func__);
5869 goto err_unregister_pmops;
5870 }
5871
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 // register net device notifier for device change notification
5873 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5874
5875 if(ret < 0)
5876 {
5877 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5878 goto err_free_power_on_lock;
5879 }
5880
5881 //Initialize the nlink service
5882 if(nl_srv_init() != 0)
5883 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305884 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 goto err_reg_netdev;
5886 }
5887
5888 //Initialize the BTC service
5889 if(btc_activate_service(pHddCtx) != 0)
5890 {
5891 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5892 goto err_nl_srv;
5893 }
5894
5895#ifdef PTT_SOCK_SVC_ENABLE
5896 //Initialize the PTT service
5897 if(ptt_sock_activate_svc(pHddCtx) != 0)
5898 {
5899 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5900 goto err_nl_srv;
5901 }
5902#endif
5903
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005907 /* Action frame registered in one adapter which will
5908 * applicable to all interfaces
5909 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005910 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005912
5913 mutex_init(&pHddCtx->sap_lock);
5914
5915 pHddCtx->isLoadUnloadInProgress = FALSE;
5916
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005917#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005918#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5919 /* Initialize the wake lcok */
5920 wake_lock_init(&pHddCtx->rx_wake_lock,
5921 WAKE_LOCK_SUSPEND,
5922 "qcom_rx_wakelock");
5923#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005924 /* Initialize the wake lcok */
5925 wake_lock_init(&pHddCtx->sap_wake_lock,
5926 WAKE_LOCK_SUSPEND,
5927 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005928#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005929
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005930 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5931 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005932
5933 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5934 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305935
Jeff Johnsone7245742012-09-05 17:12:55 -07005936 // Initialize the restart logic
5937 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305938
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005939 //Register the traffic monitor timer now
5940 if ( pHddCtx->cfg_ini->dynSplitscan)
5941 {
5942 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
5943 VOS_TIMER_TYPE_SW,
5944 hdd_tx_rx_pkt_cnt_stat_timer_handler,
5945 (void *)pHddCtx);
5946 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 goto success;
5948
5949err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005950#ifdef WLAN_KD_READY_NOTIFIER
5951 nl_srv_exit(pHddCtx->ptt_pid);
5952#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005954#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005955err_reg_netdev:
5956 unregister_netdevice_notifier(&hdd_netdev_notifier);
5957
5958err_free_power_on_lock:
5959 free_riva_power_on_lock("wlan");
5960
5961err_unregister_pmops:
5962 hddDevTmUnregisterNotifyCallback(pHddCtx);
5963 hddDeregisterPmOps(pHddCtx);
5964
Yue Ma0d4891e2013-08-06 17:01:45 -07005965 hdd_debugfs_exit(pHddCtx);
5966
Jeff Johnson295189b2012-06-20 16:38:30 -07005967#ifdef WLAN_BTAMP_FEATURE
5968err_bap_stop:
5969 WLANBAP_Stop(pVosContext);
5970#endif
5971
5972#ifdef WLAN_BTAMP_FEATURE
5973err_bap_close:
5974 WLANBAP_Close(pVosContext);
5975#endif
5976
Jeff Johnson295189b2012-06-20 16:38:30 -07005977err_close_adapter:
5978 hdd_close_all_adapters( pHddCtx );
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305979 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005980
5981err_vosstop:
5982 vos_stop(pVosContext);
5983
5984err_vosclose:
5985 status = vos_sched_close( pVosContext );
5986 if (!VOS_IS_STATUS_SUCCESS(status)) {
5987 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5988 "%s: Failed to close VOSS Scheduler", __func__);
5989 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5990 }
5991 vos_close(pVosContext );
5992
Jeff Johnson295189b2012-06-20 16:38:30 -07005993err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005994 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005995
5996err_wdclose:
5997 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5998 vos_watchdog_close(pVosContext);
5999
Jeff Johnson295189b2012-06-20 16:38:30 -07006000err_config:
6001 kfree(pHddCtx->cfg_ini);
6002 pHddCtx->cfg_ini= NULL;
6003
6004err_free_hdd_context:
6005 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 wiphy_free(wiphy) ;
6007 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 VOS_BUG(1);
6009
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006010 if (hdd_is_ssr_required())
6011 {
6012 /* WDI timeout had happened during load, so SSR is needed here */
6013 subsystem_restart("wcnss");
6014 msleep(5000);
6015 }
6016 hdd_set_ssr_required (VOS_FALSE);
6017
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006018 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006019
6020success:
6021 EXIT();
6022 return 0;
6023}
6024
6025/**---------------------------------------------------------------------------
6026
Jeff Johnson32d95a32012-09-10 13:15:23 -07006027 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
Jeff Johnson32d95a32012-09-10 13:15:23 -07006029 This is the driver entry point - called in different timeline depending
6030 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006031
6032 \param - None
6033
6034 \return - 0 for success, non zero for failure
6035
6036 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006037static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006038{
6039 VOS_STATUS status;
6040 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006041 struct device *dev = NULL;
6042 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006043#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6044 int max_retries = 0;
6045#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006046
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306047#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6048 vos_wconn_trace_init();
6049#endif
6050
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 ENTER();
6052
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006053#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006055#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006056
6057 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6058 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6059
6060 //Power Up Libra WLAN card first if not already powered up
6061 status = vos_chipPowerUp(NULL,NULL,NULL);
6062 if (!VOS_IS_STATUS_SUCCESS(status))
6063 {
6064 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6065 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306066#ifdef WLAN_OPEN_SOURCE
6067 wake_lock_destroy(&wlan_wake_lock);
6068#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006069 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006070 }
6071
Jeff Johnson295189b2012-06-20 16:38:30 -07006072#ifdef ANI_BUS_TYPE_PCI
6073
6074 dev = wcnss_wlan_get_device();
6075
6076#endif // ANI_BUS_TYPE_PCI
6077
6078#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006079
6080#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6081 /* wait until WCNSS driver downloads NV */
6082 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6083 msleep(1000);
6084 }
6085 if (max_retries >= 5) {
6086 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306087#ifdef WLAN_OPEN_SOURCE
6088 wake_lock_destroy(&wlan_wake_lock);
6089#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006090 return -ENODEV;
6091 }
6092#endif
6093
Jeff Johnson295189b2012-06-20 16:38:30 -07006094 dev = wcnss_wlan_get_device();
6095#endif // ANI_BUS_TYPE_PLATFORM
6096
6097
6098 do {
6099 if (NULL == dev) {
6100 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6101 ret_status = -1;
6102 break;
6103 }
6104
6105#ifdef MEMORY_DEBUG
6106 vos_mem_init();
6107#endif
6108
6109#ifdef TIMER_MANAGER
6110 vos_timer_manager_init();
6111#endif
6112
6113 /* Preopen VOSS so that it is ready to start at least SAL */
6114 status = vos_preOpen(&pVosContext);
6115
6116 if (!VOS_IS_STATUS_SUCCESS(status))
6117 {
6118 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6119 ret_status = -1;
6120 break;
6121 }
6122
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006123#ifndef MODULE
6124 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6125 */
6126 hdd_set_conparam((v_UINT_t)con_mode);
6127#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006128
6129 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006130 if (hdd_wlan_startup(dev))
6131 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006133 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006134 vos_preClose( &pVosContext );
6135 ret_status = -1;
6136 break;
6137 }
6138
6139 /* Cancel the vote for XO Core ON
6140 * This is done here for safety purposes in case we re-initialize without turning
6141 * it OFF in any error scenario.
6142 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006143 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006145 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006146 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6147 {
6148 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6149 " Power consumed will be high\n");
6150 }
6151 } while (0);
6152
6153 if (0 != ret_status)
6154 {
6155 //Assert Deep sleep signal now to put Libra HW in lowest power state
6156 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6157 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6158
6159 //Vote off any PMIC voltage supplies
6160 vos_chipPowerDown(NULL, NULL, NULL);
6161#ifdef TIMER_MANAGER
6162 vos_timer_exit();
6163#endif
6164#ifdef MEMORY_DEBUG
6165 vos_mem_exit();
6166#endif
6167
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006168#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006169 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6172 }
6173 else
6174 {
6175 //Send WLAN UP indication to Nlink Service
6176 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6177
6178 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006179 }
6180
6181 EXIT();
6182
6183 return ret_status;
6184}
6185
Jeff Johnson32d95a32012-09-10 13:15:23 -07006186/**---------------------------------------------------------------------------
6187
6188 \brief hdd_module_init() - Init Function
6189
6190 This is the driver entry point (invoked when module is loaded using insmod)
6191
6192 \param - None
6193
6194 \return - 0 for success, non zero for failure
6195
6196 --------------------------------------------------------------------------*/
6197#ifdef MODULE
6198static int __init hdd_module_init ( void)
6199{
6200 return hdd_driver_init();
6201}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006202#else /* #ifdef MODULE */
6203static int __init hdd_module_init ( void)
6204{
6205 /* Driver initialization is delayed to fwpath_changed_handler */
6206 return 0;
6207}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006208#endif /* #ifdef MODULE */
6209
Jeff Johnson295189b2012-06-20 16:38:30 -07006210
6211/**---------------------------------------------------------------------------
6212
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006213 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006214
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006215 This is the driver exit point (invoked when module is unloaded using rmmod
6216 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006217
6218 \param - None
6219
6220 \return - None
6221
6222 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006223static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006224{
6225 hdd_context_t *pHddCtx = NULL;
6226 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006227 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006228
6229 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6230
6231 //Get the global vos context
6232 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6233
6234 if(!pVosContext)
6235 {
6236 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6237 goto done;
6238 }
6239
6240 //Get the HDD context.
6241 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6242
6243 if(!pHddCtx)
6244 {
6245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6246 }
6247 else
6248 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006249 while(isWDresetInProgress()) {
6250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6251 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006252 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006253
6254 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6256 "%s:SSR never completed, fatal error", __func__);
6257 VOS_BUG(0);
6258 }
6259 }
6260
Jeff Johnson295189b2012-06-20 16:38:30 -07006261
6262 pHddCtx->isLoadUnloadInProgress = TRUE;
6263 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6264
6265 //Do all the cleanup before deregistering the driver
6266 hdd_wlan_exit(pHddCtx);
6267 }
6268
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 vos_preClose( &pVosContext );
6270
6271#ifdef TIMER_MANAGER
6272 vos_timer_exit();
6273#endif
6274#ifdef MEMORY_DEBUG
6275 vos_mem_exit();
6276#endif
6277
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306278#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6279 vos_wconn_trace_exit();
6280#endif
6281
Jeff Johnson295189b2012-06-20 16:38:30 -07006282done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006283#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006285#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6287}
6288
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006289/**---------------------------------------------------------------------------
6290
6291 \brief hdd_module_exit() - Exit function
6292
6293 This is the driver exit point (invoked when module is unloaded using rmmod)
6294
6295 \param - None
6296
6297 \return - None
6298
6299 --------------------------------------------------------------------------*/
6300static void __exit hdd_module_exit(void)
6301{
6302 hdd_driver_exit();
6303}
6304
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006305#ifdef MODULE
6306static int fwpath_changed_handler(const char *kmessage,
6307 struct kernel_param *kp)
6308{
Jeff Johnson76052702013-04-16 13:55:05 -07006309 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006310}
6311
6312static int con_mode_handler(const char *kmessage,
6313 struct kernel_param *kp)
6314{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006315 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006316}
6317#else /* #ifdef MODULE */
6318/**---------------------------------------------------------------------------
6319
Jeff Johnson76052702013-04-16 13:55:05 -07006320 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006321
Jeff Johnson76052702013-04-16 13:55:05 -07006322 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006323 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006324 - invoked when module parameter fwpath is modified from userspace to signal
6325 initializing the WLAN driver or when con_mode is modified from userspace
6326 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006327
6328 \return - 0 for success, non zero for failure
6329
6330 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006331static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006332{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006333 int ret_status;
6334
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006335 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006336 ret_status = hdd_driver_init();
6337 wlan_hdd_inited = ret_status ? 0 : 1;
6338 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006339 }
6340
6341 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006342
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006343 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006344
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006345 ret_status = hdd_driver_init();
6346 wlan_hdd_inited = ret_status ? 0 : 1;
6347 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006348}
6349
Jeff Johnson295189b2012-06-20 16:38:30 -07006350/**---------------------------------------------------------------------------
6351
Jeff Johnson76052702013-04-16 13:55:05 -07006352 \brief fwpath_changed_handler() - Handler Function
6353
6354 Handle changes to the fwpath parameter
6355
6356 \return - 0 for success, non zero for failure
6357
6358 --------------------------------------------------------------------------*/
6359static int fwpath_changed_handler(const char *kmessage,
6360 struct kernel_param *kp)
6361{
6362 int ret;
6363
6364 ret = param_set_copystring(kmessage, kp);
6365 if (0 == ret)
6366 ret = kickstart_driver();
6367 return ret;
6368}
6369
6370/**---------------------------------------------------------------------------
6371
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006372 \brief con_mode_handler() -
6373
6374 Handler function for module param con_mode when it is changed by userspace
6375 Dynamically linked - do nothing
6376 Statically linked - exit and init driver, as in rmmod and insmod
6377
Jeff Johnson76052702013-04-16 13:55:05 -07006378 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006379
Jeff Johnson76052702013-04-16 13:55:05 -07006380 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006381
6382 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006383static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006384{
Jeff Johnson76052702013-04-16 13:55:05 -07006385 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006386
Jeff Johnson76052702013-04-16 13:55:05 -07006387 ret = param_set_int(kmessage, kp);
6388 if (0 == ret)
6389 ret = kickstart_driver();
6390 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006391}
6392#endif /* #ifdef MODULE */
6393
6394/**---------------------------------------------------------------------------
6395
Jeff Johnson295189b2012-06-20 16:38:30 -07006396 \brief hdd_get_conparam() -
6397
6398 This is the driver exit point (invoked when module is unloaded using rmmod)
6399
6400 \param - None
6401
6402 \return - tVOS_CON_MODE
6403
6404 --------------------------------------------------------------------------*/
6405tVOS_CON_MODE hdd_get_conparam ( void )
6406{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006407#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006408 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006409#else
6410 return (tVOS_CON_MODE)curr_con_mode;
6411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006412}
6413void hdd_set_conparam ( v_UINT_t newParam )
6414{
6415 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006416#ifndef MODULE
6417 curr_con_mode = con_mode;
6418#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006419}
6420/**---------------------------------------------------------------------------
6421
6422 \brief hdd_softap_sta_deauth() - function
6423
6424 This to take counter measure to handle deauth req from HDD
6425
6426 \param - pAdapter - Pointer to the HDD
6427
6428 \param - enable - boolean value
6429
6430 \return - None
6431
6432 --------------------------------------------------------------------------*/
6433
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006434VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006435{
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006437 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006438
6439 ENTER();
6440
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006441 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6442 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006443
6444 //Ignore request to deauth bcmc station
6445 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006446 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006447
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006448 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006449
6450 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006451 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006452}
6453
6454/**---------------------------------------------------------------------------
6455
6456 \brief hdd_softap_sta_disassoc() - function
6457
6458 This to take counter measure to handle deauth req from HDD
6459
6460 \param - pAdapter - Pointer to the HDD
6461
6462 \param - enable - boolean value
6463
6464 \return - None
6465
6466 --------------------------------------------------------------------------*/
6467
6468void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6469{
6470 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6471
6472 ENTER();
6473
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306474 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006475
6476 //Ignore request to disassoc bcmc station
6477 if( pDestMacAddress[0] & 0x1 )
6478 return;
6479
6480 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6481}
6482
6483void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6484{
6485 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6486
6487 ENTER();
6488
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306489 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006490
6491 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6492}
6493
Jeff Johnson295189b2012-06-20 16:38:30 -07006494/**---------------------------------------------------------------------------
6495 *
6496 * \brief hdd_get__concurrency_mode() -
6497 *
6498 *
6499 * \param - None
6500 *
6501 * \return - CONCURRENCY MODE
6502 *
6503 * --------------------------------------------------------------------------*/
6504tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6505{
6506 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6507 hdd_context_t *pHddCtx;
6508
6509 if (NULL != pVosContext)
6510 {
6511 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6512 if (NULL != pHddCtx)
6513 {
6514 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6515 }
6516 }
6517
6518 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006519 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006520 return VOS_STA;
6521}
6522
6523/* Decide whether to allow/not the apps power collapse.
6524 * Allow apps power collapse if we are in connected state.
6525 * if not, allow only if we are in IMPS */
6526v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6527{
6528 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006529 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006530 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006531 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6532 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6533 hdd_adapter_t *pAdapter = NULL;
6534 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006535 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006536
Jeff Johnson295189b2012-06-20 16:38:30 -07006537 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6538 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006539
Yathish9f22e662012-12-10 14:21:35 -08006540 concurrent_state = hdd_get_concurrency_mode();
6541
6542#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6543 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6544 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6545 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6546 return TRUE;
6547#endif
6548
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 /*loop through all adapters. TBD fix for Concurrency */
6550 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6551 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6552 {
6553 pAdapter = pAdapterNode->pAdapter;
6554 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6555 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6556 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006557 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006558 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006559 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006560 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6561 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006563 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006564 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6565 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006566 return FALSE;
6567 }
6568 }
6569 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6570 pAdapterNode = pNext;
6571 }
6572 return TRUE;
6573}
6574
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006575/* Decides whether to send suspend notification to Riva
6576 * if any adapter is in BMPS; then it is required */
6577v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6578{
6579 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6580 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6581
6582 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6583 {
6584 return TRUE;
6585 }
6586 return FALSE;
6587}
6588
Jeff Johnson295189b2012-06-20 16:38:30 -07006589void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6590{
6591 switch(mode)
6592 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006593 case VOS_STA_MODE:
6594 case VOS_P2P_CLIENT_MODE:
6595 case VOS_P2P_GO_MODE:
6596 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006597 pHddCtx->concurrency_mode |= (1 << mode);
6598 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006599 break;
6600 default:
6601 break;
6602
6603 }
6604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6605 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6606}
6607
6608
6609void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6610{
6611 switch(mode)
6612 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006613 case VOS_STA_MODE:
6614 case VOS_P2P_CLIENT_MODE:
6615 case VOS_P2P_GO_MODE:
6616 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006617 pHddCtx->no_of_sessions[mode]--;
6618 if (!(pHddCtx->no_of_sessions[mode]))
6619 pHddCtx->concurrency_mode &= (~(1 << mode));
6620 break;
6621 default:
6622 break;
6623 }
6624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6625 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6626}
6627
Jeff Johnsone7245742012-09-05 17:12:55 -07006628/**---------------------------------------------------------------------------
6629 *
6630 * \brief wlan_hdd_restart_init
6631 *
6632 * This function initalizes restart timer/flag. An internal function.
6633 *
6634 * \param - pHddCtx
6635 *
6636 * \return - None
6637 *
6638 * --------------------------------------------------------------------------*/
6639
6640static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6641{
6642 /* Initialize */
6643 pHddCtx->hdd_restart_retries = 0;
6644 atomic_set(&pHddCtx->isRestartInProgress, 0);
6645 vos_timer_init(&pHddCtx->hdd_restart_timer,
6646 VOS_TIMER_TYPE_SW,
6647 wlan_hdd_restart_timer_cb,
6648 pHddCtx);
6649}
6650/**---------------------------------------------------------------------------
6651 *
6652 * \brief wlan_hdd_restart_deinit
6653 *
6654 * This function cleans up the resources used. An internal function.
6655 *
6656 * \param - pHddCtx
6657 *
6658 * \return - None
6659 *
6660 * --------------------------------------------------------------------------*/
6661
6662static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6663{
6664
6665 VOS_STATUS vos_status;
6666 /* Block any further calls */
6667 atomic_set(&pHddCtx->isRestartInProgress, 1);
6668 /* Cleanup */
6669 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6670 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006671 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006672 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6673 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006674 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006675
6676}
6677
6678/**---------------------------------------------------------------------------
6679 *
6680 * \brief wlan_hdd_framework_restart
6681 *
6682 * This function uses a cfg80211 API to start a framework initiated WLAN
6683 * driver module unload/load.
6684 *
6685 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6686 *
6687 *
6688 * \param - pHddCtx
6689 *
6690 * \return - VOS_STATUS_SUCCESS: Success
6691 * VOS_STATUS_E_EMPTY: Adapter is Empty
6692 * VOS_STATUS_E_NOMEM: No memory
6693
6694 * --------------------------------------------------------------------------*/
6695
6696static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6697{
6698 VOS_STATUS status = VOS_STATUS_SUCCESS;
6699 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006700 int len = (sizeof (struct ieee80211_mgmt));
6701 struct ieee80211_mgmt *mgmt = NULL;
6702
6703 /* Prepare the DEAUTH managment frame with reason code */
6704 mgmt = kzalloc(len, GFP_KERNEL);
6705 if(mgmt == NULL)
6706 {
6707 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6708 "%s: memory allocation failed (%d bytes)", __func__, len);
6709 return VOS_STATUS_E_NOMEM;
6710 }
6711 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006712
6713 /* Iterate over all adapters/devices */
6714 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6715 do
6716 {
6717 if( (status == VOS_STATUS_SUCCESS) &&
6718 pAdapterNode &&
6719 pAdapterNode->pAdapter)
6720 {
6721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6722 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6723 pAdapterNode->pAdapter->dev->name,
6724 pAdapterNode->pAdapter->device_mode,
6725 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006726 /*
6727 * CFG80211 event to restart the driver
6728 *
6729 * 'cfg80211_send_unprot_deauth' sends a
6730 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6731 * of SME(Linux Kernel) state machine.
6732 *
6733 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6734 * the driver.
6735 *
6736 */
6737
6738 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006739 }
6740 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6741 pAdapterNode = pNext;
6742 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6743
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006744
6745 /* Free the allocated management frame */
6746 kfree(mgmt);
6747
Jeff Johnsone7245742012-09-05 17:12:55 -07006748 /* Retry until we unload or reach max count */
6749 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6750 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6751
6752 return status;
6753
6754}
6755/**---------------------------------------------------------------------------
6756 *
6757 * \brief wlan_hdd_restart_timer_cb
6758 *
6759 * Restart timer callback. An internal function.
6760 *
6761 * \param - User data:
6762 *
6763 * \return - None
6764 *
6765 * --------------------------------------------------------------------------*/
6766
6767void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6768{
6769 hdd_context_t *pHddCtx = usrDataForCallback;
6770 wlan_hdd_framework_restart(pHddCtx);
6771 return;
6772
6773}
6774
6775
6776/**---------------------------------------------------------------------------
6777 *
6778 * \brief wlan_hdd_restart_driver
6779 *
6780 * This function sends an event to supplicant to restart the WLAN driver.
6781 *
6782 * This function is called from vos_wlanRestart.
6783 *
6784 * \param - pHddCtx
6785 *
6786 * \return - VOS_STATUS_SUCCESS: Success
6787 * VOS_STATUS_E_EMPTY: Adapter is Empty
6788 * VOS_STATUS_E_ALREADY: Request already in progress
6789
6790 * --------------------------------------------------------------------------*/
6791VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6792{
6793 VOS_STATUS status = VOS_STATUS_SUCCESS;
6794
6795 /* A tight check to make sure reentrancy */
6796 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6797 {
6798 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6799 "%s: WLAN restart is already in progress", __func__);
6800
6801 return VOS_STATUS_E_ALREADY;
6802 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006803 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006804#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006805 wcnss_reset_intr();
6806#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006807
Jeff Johnsone7245742012-09-05 17:12:55 -07006808 return status;
6809}
6810
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006811/*
6812 * API to find if there is any STA or P2P-Client is connected
6813 */
6814VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6815{
6816 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6817}
Jeff Johnsone7245742012-09-05 17:12:55 -07006818
Jeff Johnson295189b2012-06-20 16:38:30 -07006819//Register the module init/exit functions
6820module_init(hdd_module_init);
6821module_exit(hdd_module_exit);
6822
6823MODULE_LICENSE("Dual BSD/GPL");
6824MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6825MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6826
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006827module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6828 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006829
Jeff Johnson76052702013-04-16 13:55:05 -07006830module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006831 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);