blob: 6770234249cbe1623c59c1e453ca38d3d2b093dc [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700126#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700127
128#ifdef MODULE
129#define WLAN_MODULE_NAME module_name(THIS_MODULE)
130#else
131#define WLAN_MODULE_NAME "wlan"
132#endif
133
134#ifdef TIMER_MANAGER
135#define TIMER_MANAGER_STR " +TIMER_MANAGER"
136#else
137#define TIMER_MANAGER_STR ""
138#endif
139
140#ifdef MEMORY_DEBUG
141#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
142#else
143#define MEMORY_DEBUG_STR ""
144#endif
145
146/* the Android framework expects this param even though we don't use it */
147#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700148static char fwpath_buffer[BUF_LEN];
149static struct kparam_string fwpath = {
150 .string = fwpath_buffer,
151 .maxlen = BUF_LEN,
152};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700153#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700154static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Jeff Johnsone7245742012-09-05 17:12:55 -0700157/*
158 * The rate at which the driver sends RESTART event to supplicant
159 * once the function 'vos_wlanRestart()' is called
160 *
161 */
162#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
163#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700164
165/*
166 * Size of Driver command strings from upper layer
167 */
168#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
169#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
170
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700171/*
172 * Driver miracast parameters 0-Disabled
173 * 1-Source, 2-Sink
174 */
175#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
176#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
177
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800178#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700179static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700180#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700181/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700182static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700185static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
186static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
188void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800189void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700190
Jeff Johnson295189b2012-06-20 16:38:30 -0700191v_U16_t hdd_select_queue(struct net_device *dev,
192 struct sk_buff *skb);
193
194#ifdef WLAN_FEATURE_PACKET_FILTERING
195static void hdd_set_multicast_list(struct net_device *dev);
196#endif
197
198void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700199int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700200
201extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800202#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
203void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
204static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700205static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
206 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
207 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700208static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
209 tANI_U8 *pTargetApBssid,
210 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700212static int hdd_netdev_notifier_call(struct notifier_block * nb,
213 unsigned long state,
214 void *ndev)
215{
216 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219#ifdef WLAN_BTAMP_FEATURE
220 VOS_STATUS status;
221 hdd_context_t *pHddCtx;
222#endif
223
224 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700226 (strncmp(dev->name, "p2p", 3)))
227 return NOTIFY_DONE;
228
229 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 return NOTIFY_DONE;
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700233 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 VOS_ASSERT(0);
239 return NOTIFY_DONE;
240 }
241
Jeff Johnson27cee452013-03-27 11:10:24 -0700242 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
243 if (NULL == pHddCtx)
244 {
245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
246 VOS_ASSERT(0);
247 return NOTIFY_DONE;
248 }
249
250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
251 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252
253 switch (state) {
254 case NETDEV_REGISTER:
255 break;
256
257 case NETDEV_UNREGISTER:
258 break;
259
260 case NETDEV_UP:
261 break;
262
263 case NETDEV_DOWN:
264 break;
265
266 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700267 if(TRUE == pAdapter->isLinkUpSvcNeeded)
268 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 break;
270
271 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700272 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 {
274 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800275 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530276 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800278 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
280 if(!result)
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800283 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700284 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 }
286 }
287 else
288 {
289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700290 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 }
292#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 status = WLANBAP_StopAmp();
295 if(VOS_STATUS_SUCCESS != status )
296 {
297 pHddCtx->isAmpAllowed = VOS_TRUE;
298 hddLog(VOS_TRACE_LEVEL_FATAL,
299 "%s: Failed to stop AMP", __func__);
300 }
301 else
302 {
303 //a state m/c implementation in PAL is TBD to avoid this delay
304 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700305 if ( pHddCtx->isAmpAllowed )
306 {
307 WLANBAP_DeregisterFromHCI();
308 pHddCtx->isAmpAllowed = VOS_FALSE;
309 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311#endif //WLAN_BTAMP_FEATURE
312 break;
313
314 default:
315 break;
316 }
317
318 return NOTIFY_DONE;
319}
320
321struct notifier_block hdd_netdev_notifier = {
322 .notifier_call = hdd_netdev_notifier_call,
323};
324
325/*---------------------------------------------------------------------------
326 * Function definitions
327 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700328void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
329void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700330//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700331static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700332#ifndef MODULE
333/* current con_mode - used only for statically linked driver
334 * con_mode is changed by userspace to indicate a mode change which will
335 * result in calling the module exit and init functions. The module
336 * exit function will clean up based on the value of con_mode prior to it
337 * being changed by userspace. So curr_con_mode records the current con_mode
338 * for exit when con_mode becomes the next mode for init
339 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700340static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700341#endif
342
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800343/**---------------------------------------------------------------------------
344
345 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
346
347 Called immediately after the cfg.ini is read in order to configure
348 the desired trace levels.
349
350 \param - moduleId - module whose trace level is being configured
351 \param - bitmask - bitmask of log levels to be enabled
352
353 \return - void
354
355 --------------------------------------------------------------------------*/
356static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
357{
358 wpt_tracelevel level;
359
360 /* if the bitmask is the default value, then a bitmask was not
361 specified in cfg.ini, so leave the logging level alone (it
362 will remain at the "compiled in" default value) */
363 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
364 {
365 return;
366 }
367
368 /* a mask was specified. start by disabling all logging */
369 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
370
371 /* now cycle through the bitmask until all "set" bits are serviced */
372 level = VOS_TRACE_LEVEL_FATAL;
373 while (0 != bitmask)
374 {
375 if (bitmask & 1)
376 {
377 vos_trace_setValue(moduleId, level, 1);
378 }
379 level++;
380 bitmask >>= 1;
381 }
382}
383
384
Jeff Johnson295189b2012-06-20 16:38:30 -0700385/**---------------------------------------------------------------------------
386
387 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
388
389 Called immediately after the cfg.ini is read in order to configure
390 the desired trace levels in the WDI.
391
392 \param - moduleId - module whose trace level is being configured
393 \param - bitmask - bitmask of log levels to be enabled
394
395 \return - void
396
397 --------------------------------------------------------------------------*/
398static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
399{
400 wpt_tracelevel level;
401
402 /* if the bitmask is the default value, then a bitmask was not
403 specified in cfg.ini, so leave the logging level alone (it
404 will remain at the "compiled in" default value) */
405 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
406 {
407 return;
408 }
409
410 /* a mask was specified. start by disabling all logging */
411 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
412
413 /* now cycle through the bitmask until all "set" bits are serviced */
414 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
415 while (0 != bitmask)
416 {
417 if (bitmask & 1)
418 {
419 wpalTraceSetLevel(moduleId, level, 1);
420 }
421 level++;
422 bitmask >>= 1;
423 }
424}
Jeff Johnson295189b2012-06-20 16:38:30 -0700425
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530426/*
427 * FUNCTION: wlan_hdd_validate_context
428 * This function is used to check the HDD context
429 */
430int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
431{
432 ENTER();
433
434 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
435 {
436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: HDD context is Null", __func__);
438 return -ENODEV;
439 }
440
441 if (pHddCtx->isLogpInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: LOGP in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447
448 if (pHddCtx->isLoadUnloadInProgress)
449 {
450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
451 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
452 return -EAGAIN;
453 }
454 return 0;
455}
456
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530457void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
458{
459 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
460 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
461 hdd_config_t *cfg_param;
462 eCsrPhyMode phyMode;
463
464 if (NULL == pHddCtx)
465 {
466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
467 "HDD Context is null !!");
468 return ;
469 }
470
471 cfg_param = pHddCtx->cfg_ini;
472
473 if (NULL == cfg_param)
474 {
475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
476 "cfg_params not available !!");
477 return ;
478 }
479
480 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
481
482 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
483 {
484 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
485 (eCSR_DOT11_MODE_11ac == phyMode) ||
486 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
489 "Setting phymode to 11n!!");
490 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
491 }
492 }
493 else
494 {
495 /*New country Supports 11ac as well resetting value back from .ini*/
496 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
497 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
498 return ;
499 }
500
501 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
502 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
503 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
504 {
505 VOS_STATUS vosStatus;
506
507 // need to issue a disconnect to CSR.
508 INIT_COMPLETION(pAdapter->disconnect_comp_var);
509 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
510 pAdapter->sessionId,
511 eCSR_DISCONNECT_REASON_UNSPECIFIED );
512
513 if (VOS_STATUS_SUCCESS == vosStatus)
514 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
515 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
516
517 }
518}
519
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700520void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
521{
522 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
523 hdd_config_t *cfg_param;
524
525 if (NULL == pHddCtx)
526 {
527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
528 "HDD Context is null !!");
529 return ;
530 }
531
532 cfg_param = pHddCtx->cfg_ini;
533
534 if (NULL == cfg_param)
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
537 "cfg_params not available !!");
538 return ;
539 }
540
541 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
542 {
543 /*New country doesn't support DFS */
544 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
545 }
546 else
547 {
548 /*New country Supports DFS as well resetting value back from .ini*/
549 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
550 }
551
552}
553
Jeff Johnson295189b2012-06-20 16:38:30 -0700554int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
555{
556 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
557 hdd_priv_data_t priv_data;
558 tANI_U8 *command = NULL;
559 int ret = 0;
560
561 if (NULL == pAdapter)
562 {
563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700564 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 ret = -ENODEV;
566 goto exit;
567 }
568
Jeff Johnsone7245742012-09-05 17:12:55 -0700569 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700570 {
571 ret = -EINVAL;
572 goto exit;
573 }
574
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700575 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
576 {
577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
578 "%s:LOGP in Progress. Ignore!!!", __func__);
579 ret = -EBUSY;
580 goto exit;
581 }
582
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
584 {
585 ret = -EFAULT;
586 goto exit;
587 }
588
589 command = kmalloc(priv_data.total_len, GFP_KERNEL);
590 if (!command)
591 {
592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700593 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 ret = -ENOMEM;
595 goto exit;
596 }
597
598 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
599 {
600 ret = -EFAULT;
601 goto exit;
602 }
603
604 if ((SIOCDEVPRIVATE + 1) == cmd)
605 {
606 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
607
608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700609 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700610
611 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
612 {
613 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
614 sizeof(tSirMacAddr)))
615 {
616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700617 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700618 ret = -EFAULT;
619 }
620 }
Amar Singhal0974e402013-02-12 14:27:46 -0800621 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 {
Amar Singhal0974e402013-02-12 14:27:46 -0800623 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700624 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800625
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800627
628 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800631 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800633 ret = hdd_setBand_helper(dev, ptr);
634 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700635 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
636 {
637 char *country_code;
638
639 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700640
641 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700643 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530644 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700645 if( 0 != ret )
646 {
647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
648 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
649
650 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700651 }
652 /*
653 command should be a string having format
654 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
655 */
Amar Singhal0974e402013-02-12 14:27:46 -0800656 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700657 {
Amar Singhal0974e402013-02-12 14:27:46 -0800658 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700659
660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700661 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700662
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800663 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700664 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800665 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
666 {
667 int suspend = 0;
668 tANI_U8 *ptr = (tANI_U8*)command + 15;
669
670 suspend = *ptr - '0';
671 hdd_set_wlan_suspend_mode(suspend);
672 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800673#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
674 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
675 {
676 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700677 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800678 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
679 eHalStatus status = eHAL_STATUS_SUCCESS;
680
681 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
682 value = value + 15;
683
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700684 /* Convert the value from ascii to integer */
685 ret = kstrtos8(value, 10, &rssi);
686 if (ret < 0)
687 {
688 /* If the input value is greater than max value of datatype, then also
689 kstrtou8 fails */
690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
691 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
692 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
693 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
694 ret = -EINVAL;
695 goto exit;
696 }
697
Srinivas Girigowdade697412013-02-14 16:31:48 -0800698 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700699
Srinivas Girigowdade697412013-02-14 16:31:48 -0800700 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
701 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
702 {
703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
704 "Neighbor lookup threshold value %d is out of range"
705 " (Min: %d Max: %d)", lookUpThreshold,
706 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
707 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
708 ret = -EINVAL;
709 goto exit;
710 }
711
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
713 "%s: Received Command to Set Roam trigger"
714 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
715
716 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
717 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
718 if (eHAL_STATUS_SUCCESS != status)
719 {
720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
721 "%s: Failed to set roam trigger, try again", __func__);
722 ret = -EPERM;
723 goto exit;
724 }
725
726 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
727 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
728 }
729 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
730 {
731 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
732 int rssi = (-1) * lookUpThreshold;
733 char extra[32];
734 tANI_U8 len = 0;
735
736 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
737 if (copy_to_user(priv_data.buf, &extra, len + 1))
738 {
739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
740 "%s: failed to copy data to user buffer", __func__);
741 ret = -EFAULT;
742 goto exit;
743 }
744 }
745 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
746 {
747 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700748 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700749 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700750
Srinivas Girigowdade697412013-02-14 16:31:48 -0800751 /* input refresh period is in terms of seconds */
752 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
753 value = value + 18;
754 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if (ret < 0)
757 {
758 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700759 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700761 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800762 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700763 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
764 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800765 ret = -EINVAL;
766 goto exit;
767 }
768
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700769 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
770 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800771 {
772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700773 "Roam scan period value %d is out of range"
774 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700775 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
776 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800777 ret = -EINVAL;
778 goto exit;
779 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700780 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800781
782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
783 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700784 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700786 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
787 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800788 }
789 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
790 {
791 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
792 char extra[32];
793 tANI_U8 len = 0;
794
795 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
796 /* Returned value is in units of seconds */
797 if (copy_to_user(priv_data.buf, &extra, len + 1))
798 {
799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
800 "%s: failed to copy data to user buffer", __func__);
801 ret = -EFAULT;
802 goto exit;
803 }
804 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
806 {
807 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700808 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700809 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700810
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700811 /* input refresh period is in terms of seconds */
812 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
813 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700814
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700816 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700817 if (ret < 0)
818 {
819 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700820 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700822 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700823 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
825 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
826 ret = -EINVAL;
827 goto exit;
828 }
829
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700830 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
831 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
832 {
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
834 "Neighbor scan results refresh period value %d is out of range"
835 " (Min: %d Max: %d)", roamScanRefreshPeriod,
836 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
837 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
838 ret = -EINVAL;
839 goto exit;
840 }
841 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
842
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
844 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700845 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846
847 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
848 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
849 }
850 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
851 {
852 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
853 char extra[32];
854 tANI_U8 len = 0;
855
856 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
857 /* Returned value is in units of seconds */
858 if (copy_to_user(priv_data.buf, &extra, len + 1))
859 {
860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
861 "%s: failed to copy data to user buffer", __func__);
862 ret = -EFAULT;
863 goto exit;
864 }
865 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700866#ifdef FEATURE_WLAN_LFR
867 /* SETROAMMODE */
868 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
869 {
870 tANI_U8 *value = command;
871 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
872
873 /* Move pointer to ahead of SETROAMMODE<delimiter> */
874 value = value + SIZE_OF_SETROAMMODE + 1;
875
876 /* Convert the value from ascii to integer */
877 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
878 if (ret < 0)
879 {
880 /* If the input value is greater than max value of datatype, then also
881 kstrtou8 fails */
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: kstrtou8 failed range [%d - %d]", __func__,
884 CFG_LFR_FEATURE_ENABLED_MIN,
885 CFG_LFR_FEATURE_ENABLED_MAX);
886 ret = -EINVAL;
887 goto exit;
888 }
889 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
890 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
891 {
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "Roam Mode value %d is out of range"
894 " (Min: %d Max: %d)", roamMode,
895 CFG_LFR_FEATURE_ENABLED_MIN,
896 CFG_LFR_FEATURE_ENABLED_MAX);
897 ret = -EINVAL;
898 goto exit;
899 }
900
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
902 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
903 /*
904 * Note that
905 * SETROAMMODE 0 is to enable LFR while
906 * SETROAMMODE 1 is to disable LFR, but
907 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
908 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
909 */
910 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
911 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
912 else
913 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
914
915 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
916 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
917 }
918 /* GETROAMMODE */
919 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
920 {
921 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
922 char extra[32];
923 tANI_U8 len = 0;
924
925 /*
926 * roamMode value shall be inverted because the sementics is different.
927 */
928 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
929 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
930 else
931 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
932
933 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
934 if (copy_to_user(priv_data.buf, &extra, len + 1))
935 {
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
937 "%s: failed to copy data to user buffer", __func__);
938 ret = -EFAULT;
939 goto exit;
940 }
941 }
942#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800943#endif
944#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
945 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
946 {
947 tANI_U8 *value = command;
948 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
949
950 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
951 value = value + 13;
952 /* Convert the value from ascii to integer */
953 ret = kstrtou8(value, 10, &roamRssiDiff);
954 if (ret < 0)
955 {
956 /* If the input value is greater than max value of datatype, then also
957 kstrtou8 fails */
958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
959 "%s: kstrtou8 failed range [%d - %d]", __func__,
960 CFG_ROAM_RSSI_DIFF_MIN,
961 CFG_ROAM_RSSI_DIFF_MAX);
962 ret = -EINVAL;
963 goto exit;
964 }
965
966 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
967 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
968 {
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
970 "Roam rssi diff value %d is out of range"
971 " (Min: %d Max: %d)", roamRssiDiff,
972 CFG_ROAM_RSSI_DIFF_MIN,
973 CFG_ROAM_RSSI_DIFF_MAX);
974 ret = -EINVAL;
975 goto exit;
976 }
977
978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
979 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
980
981 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
982 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
983 }
984 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
987 char extra[32];
988 tANI_U8 len = 0;
989
990 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
991 if (copy_to_user(priv_data.buf, &extra, len + 1))
992 {
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
994 "%s: failed to copy data to user buffer", __func__);
995 ret = -EFAULT;
996 goto exit;
997 }
998 }
999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "GETBAND", 7) == 0)
1002 {
1003 int band = -1;
1004 char extra[32];
1005 tANI_U8 len = 0;
1006 hdd_getBand_helper(pHddCtx, &band);
1007
1008 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1009 if (copy_to_user(priv_data.buf, &extra, len + 1))
1010 {
1011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1012 "%s: failed to copy data to user buffer", __func__);
1013 ret = -EFAULT;
1014 goto exit;
1015 }
1016 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001017 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1018 {
1019 tANI_U8 *value = command;
1020 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1021 tANI_U8 numChannels = 0;
1022 eHalStatus status = eHAL_STATUS_SUCCESS;
1023
1024 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1025 if (eHAL_STATUS_SUCCESS != status)
1026 {
1027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1028 "%s: Failed to parse channel list information", __func__);
1029 ret = -EINVAL;
1030 goto exit;
1031 }
1032
1033 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1034 {
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1036 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1037 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1038 ret = -EINVAL;
1039 goto exit;
1040 }
1041 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1042 numChannels);
1043 if (eHAL_STATUS_SUCCESS != status)
1044 {
1045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: Failed to update channel list information", __func__);
1047 ret = -EINVAL;
1048 goto exit;
1049 }
1050 }
1051 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1052 {
1053 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1054 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001055 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001056 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001057 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001058
1059 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1060 ChannelList, &numChannels ))
1061 {
1062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1063 "%s: failed to get roam scan channel list", __func__);
1064 ret = -EFAULT;
1065 goto exit;
1066 }
1067 /* output channel list is of the format
1068 [Number of roam scan channels][Channel1][Channel2]... */
1069 /* copy the number of channels in the 0th index */
1070 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1071 for (j = 0; (j < numChannels); j++)
1072 {
1073 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1074 }
1075
1076 if (copy_to_user(priv_data.buf, &extra, len + 1))
1077 {
1078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s: failed to copy data to user buffer", __func__);
1080 ret = -EFAULT;
1081 goto exit;
1082 }
1083 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001084 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1085 {
1086 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1087 char extra[32];
1088 tANI_U8 len = 0;
1089
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001090 /* Check if the features OKC/CCX/11R are supported simultaneously,
1091 then this operation is not permitted (return FAILURE) */
1092 if (ccxMode &&
1093 hdd_is_okc_mode_enabled(pHddCtx) &&
1094 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1095 {
1096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1097 "%s: OKC/CCX/11R are supported simultaneously"
1098 " hence this operation is not permitted!", __func__);
1099 ret = -EPERM;
1100 goto exit;
1101 }
1102
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001103 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1104 if (copy_to_user(priv_data.buf, &extra, len + 1))
1105 {
1106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1107 "%s: failed to copy data to user buffer", __func__);
1108 ret = -EFAULT;
1109 goto exit;
1110 }
1111 }
1112 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1113 {
1114 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1115 char extra[32];
1116 tANI_U8 len = 0;
1117
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001118 /* Check if the features OKC/CCX/11R are supported simultaneously,
1119 then this operation is not permitted (return FAILURE) */
1120 if (okcMode &&
1121 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1122 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1125 "%s: OKC/CCX/11R are supported simultaneously"
1126 " hence this operation is not permitted!", __func__);
1127 ret = -EPERM;
1128 goto exit;
1129 }
1130
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001131 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1132 if (copy_to_user(priv_data.buf, &extra, len + 1))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: failed to copy data to user buffer", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001140 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001141 {
1142 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1143 char extra[32];
1144 tANI_U8 len = 0;
1145
1146 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1147 if (copy_to_user(priv_data.buf, &extra, len + 1))
1148 {
1149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: failed to copy data to user buffer", __func__);
1151 ret = -EFAULT;
1152 goto exit;
1153 }
1154 }
1155 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1156 {
1157 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1158 char extra[32];
1159 tANI_U8 len = 0;
1160
1161 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1162 if (copy_to_user(priv_data.buf, &extra, len + 1))
1163 {
1164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: failed to copy data to user buffer", __func__);
1166 ret = -EFAULT;
1167 goto exit;
1168 }
1169 }
1170 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1171 {
1172 tANI_U8 *value = command;
1173 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1174
1175 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1176 value = value + 26;
1177 /* Convert the value from ascii to integer */
1178 ret = kstrtou8(value, 10, &minTime);
1179 if (ret < 0)
1180 {
1181 /* If the input value is greater than max value of datatype, then also
1182 kstrtou8 fails */
1183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: kstrtou8 failed range [%d - %d]", __func__,
1185 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1186 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1187 ret = -EINVAL;
1188 goto exit;
1189 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001190 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1191 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1192 {
1193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "scan min channel time value %d is out of range"
1195 " (Min: %d Max: %d)", minTime,
1196 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1197 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1198 ret = -EINVAL;
1199 goto exit;
1200 }
1201
1202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1203 "%s: Received Command to change channel min time = %d", __func__, minTime);
1204
1205 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1206 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1207 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001208 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1209 {
1210 tANI_U8 *value = command;
1211 tANI_U8 channel = 0;
1212 tANI_U8 dwellTime = 0;
1213 tANI_U8 bufLen = 0;
1214 tANI_U8 *buf = NULL;
1215 tSirMacAddr targetApBssid;
1216 eHalStatus status = eHAL_STATUS_SUCCESS;
1217 struct ieee80211_channel chan;
1218 tANI_U8 finalLen = 0;
1219 tANI_U8 *finalBuf = NULL;
1220 tANI_U8 temp = 0;
1221 u64 cookie;
1222 hdd_station_ctx_t *pHddStaCtx = NULL;
1223 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1224
1225 /* if not associated, no need to send action frame */
1226 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1227 {
1228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1229 ret = -EINVAL;
1230 goto exit;
1231 }
1232
1233 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1234 &dwellTime, &buf, &bufLen);
1235 if (eHAL_STATUS_SUCCESS != status)
1236 {
1237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "%s: Failed to parse send action frame data", __func__);
1239 ret = -EINVAL;
1240 goto exit;
1241 }
1242
1243 /* if the target bssid is different from currently associated AP,
1244 then no need to send action frame */
1245 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1246 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1247 {
1248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1249 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001250 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001251 goto exit;
1252 }
1253
1254 /* if the channel number is different from operating channel then
1255 no need to send action frame */
1256 if (channel != pHddStaCtx->conn_info.operationChannel)
1257 {
1258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1259 "%s: channel(%d) is different from operating channel(%d)",
1260 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1261 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001262 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001263 goto exit;
1264 }
1265 chan.center_freq = sme_ChnToFreq(channel);
1266
1267 finalLen = bufLen + 24;
1268 finalBuf = vos_mem_malloc(finalLen);
1269 if (NULL == finalBuf)
1270 {
1271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1272 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001273 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001274 goto exit;
1275 }
1276 vos_mem_zero(finalBuf, finalLen);
1277
1278 /* Fill subtype */
1279 temp = SIR_MAC_MGMT_ACTION << 4;
1280 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1281
1282 /* Fill type */
1283 temp = SIR_MAC_MGMT_FRAME;
1284 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1285
1286 /* Fill destination address (bssid of the AP) */
1287 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1288
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001289 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001290 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1291
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001292 /* Fill BSSID (AP mac address) */
1293 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001294
1295 /* Fill received buffer from 24th address */
1296 vos_mem_copy(finalBuf + 24, buf, bufLen);
1297
Jeff Johnson11c33152013-04-16 17:52:40 -07001298 /* done with the parsed buffer */
1299 vos_mem_free(buf);
1300
Yue Maf49ba872013-08-19 12:04:25 -07001301 wlan_hdd_action( NULL,
1302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1303 &(pAdapter->wdev),
1304#else
1305 dev,
1306#endif
1307 &chan, 0,
1308#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1309 NL80211_CHAN_HT20, 1,
1310#endif
1311 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001312 1, &cookie );
1313 vos_mem_free(finalBuf);
1314 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001315 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1316 {
1317 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1318 char extra[32];
1319 tANI_U8 len = 0;
1320
1321 /* value is interms of msec */
1322 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1323 if (copy_to_user(priv_data.buf, &extra, len + 1))
1324 {
1325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1326 "%s: failed to copy data to user buffer", __func__);
1327 ret = -EFAULT;
1328 goto exit;
1329 }
1330 }
1331 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1332 {
1333 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001334 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001335 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001336
1337 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1338 value = value + 19;
1339 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001340 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001341 if (ret < 0)
1342 {
1343 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001344 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001346 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001347 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1348 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1349 ret = -EINVAL;
1350 goto exit;
1351 }
1352
1353 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1354 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1355 {
1356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1357 "lfr mode value %d is out of range"
1358 " (Min: %d Max: %d)", maxTime,
1359 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1360 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1361 ret = -EINVAL;
1362 goto exit;
1363 }
1364
1365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1366 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1367
1368 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001369
1370 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1371 * where RFS is the RF Switching time. It is twice RFS to consider the
1372 * time to go off channel and return to the home channel. */
1373 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1374 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1375 {
1376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1377 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1378 " Hence enforcing home away time to disable (0)",
1379 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1380 homeAwayTime = 0;
1381 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1382 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1383 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001384 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1385 }
1386 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1387 {
1388 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1389 char extra[32];
1390 tANI_U8 len = 0;
1391
1392 /* value is interms of msec */
1393 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1394 if (copy_to_user(priv_data.buf, &extra, len + 1))
1395 {
1396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1397 "%s: failed to copy data to user buffer", __func__);
1398 ret = -EFAULT;
1399 goto exit;
1400 }
1401 }
1402 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1403 {
1404 tANI_U8 *value = command;
1405 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1406
1407 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1408 value = value + 16;
1409 /* Convert the value from ascii to integer */
1410 ret = kstrtou16(value, 10, &val);
1411 if (ret < 0)
1412 {
1413 /* If the input value is greater than max value of datatype, then also
1414 kstrtou16 fails */
1415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1416 "%s: kstrtou16 failed range [%d - %d]", __func__,
1417 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1418 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1419 ret = -EINVAL;
1420 goto exit;
1421 }
1422
1423 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1424 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1425 {
1426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1427 "scan home time value %d is out of range"
1428 " (Min: %d Max: %d)", val,
1429 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1430 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1431 ret = -EINVAL;
1432 goto exit;
1433 }
1434
1435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1436 "%s: Received Command to change scan home time = %d", __func__, val);
1437
1438 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1439 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1440 }
1441 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1442 {
1443 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1444 char extra[32];
1445 tANI_U8 len = 0;
1446
1447 /* value is interms of msec */
1448 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1449 if (copy_to_user(priv_data.buf, &extra, len + 1))
1450 {
1451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1452 "%s: failed to copy data to user buffer", __func__);
1453 ret = -EFAULT;
1454 goto exit;
1455 }
1456 }
1457 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1458 {
1459 tANI_U8 *value = command;
1460 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1461
1462 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1463 value = value + 17;
1464 /* Convert the value from ascii to integer */
1465 ret = kstrtou8(value, 10, &val);
1466 if (ret < 0)
1467 {
1468 /* If the input value is greater than max value of datatype, then also
1469 kstrtou8 fails */
1470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1471 "%s: kstrtou8 failed range [%d - %d]", __func__,
1472 CFG_ROAM_INTRA_BAND_MIN,
1473 CFG_ROAM_INTRA_BAND_MAX);
1474 ret = -EINVAL;
1475 goto exit;
1476 }
1477
1478 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1479 (val > CFG_ROAM_INTRA_BAND_MAX))
1480 {
1481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1482 "intra band mode value %d is out of range"
1483 " (Min: %d Max: %d)", val,
1484 CFG_ROAM_INTRA_BAND_MIN,
1485 CFG_ROAM_INTRA_BAND_MAX);
1486 ret = -EINVAL;
1487 goto exit;
1488 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1490 "%s: Received Command to change intra band = %d", __func__, val);
1491
1492 pHddCtx->cfg_ini->nRoamIntraBand = val;
1493 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1494 }
1495 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1496 {
1497 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1498 char extra[32];
1499 tANI_U8 len = 0;
1500
1501 /* value is interms of msec */
1502 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1503 if (copy_to_user(priv_data.buf, &extra, len + 1))
1504 {
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: failed to copy data to user buffer", __func__);
1507 ret = -EFAULT;
1508 goto exit;
1509 }
1510 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001511 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1512 {
1513 tANI_U8 *value = command;
1514 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1515
1516 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1517 value = value + 15;
1518 /* Convert the value from ascii to integer */
1519 ret = kstrtou8(value, 10, &nProbes);
1520 if (ret < 0)
1521 {
1522 /* If the input value is greater than max value of datatype, then also
1523 kstrtou8 fails */
1524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1525 "%s: kstrtou8 failed range [%d - %d]", __func__,
1526 CFG_ROAM_SCAN_N_PROBES_MIN,
1527 CFG_ROAM_SCAN_N_PROBES_MAX);
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
1532 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1533 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1534 {
1535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1536 "NProbes value %d is out of range"
1537 " (Min: %d Max: %d)", nProbes,
1538 CFG_ROAM_SCAN_N_PROBES_MIN,
1539 CFG_ROAM_SCAN_N_PROBES_MAX);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
1543
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1545 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1546
1547 pHddCtx->cfg_ini->nProbes = nProbes;
1548 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1549 }
1550 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1551 {
1552 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1553 char extra[32];
1554 tANI_U8 len = 0;
1555
1556 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1557 if (copy_to_user(priv_data.buf, &extra, len + 1))
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1560 "%s: failed to copy data to user buffer", __func__);
1561 ret = -EFAULT;
1562 goto exit;
1563 }
1564 }
1565 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1566 {
1567 tANI_U8 *value = command;
1568 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001569 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001570
1571 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1572 /* input value is in units of msec */
1573 value = value + 20;
1574 /* Convert the value from ascii to integer */
1575 ret = kstrtou16(value, 10, &homeAwayTime);
1576 if (ret < 0)
1577 {
1578 /* If the input value is greater than max value of datatype, then also
1579 kstrtou8 fails */
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: kstrtou8 failed range [%d - %d]", __func__,
1582 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1583 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1584 ret = -EINVAL;
1585 goto exit;
1586 }
1587
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001588 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1589 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1590 {
1591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "homeAwayTime value %d is out of range"
1593 " (Min: %d Max: %d)", homeAwayTime,
1594 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1595 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1596 ret = -EINVAL;
1597 goto exit;
1598 }
1599
1600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1601 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1602
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001603 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1604 * where RFS is the RF Switching time. It is twice RFS to consider the
1605 * time to go off channel and return to the home channel. */
1606 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1607 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1610 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1611 " Hence enforcing home away time to disable (0)",
1612 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1613 homeAwayTime = 0;
1614 }
1615
1616 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1617 {
1618 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1619 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1620 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001621 }
1622 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1623 {
1624 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1625 char extra[32];
1626 tANI_U8 len = 0;
1627
1628 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1629 if (copy_to_user(priv_data.buf, &extra, len + 1))
1630 {
1631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s: failed to copy data to user buffer", __func__);
1633 ret = -EFAULT;
1634 goto exit;
1635 }
1636 }
1637 else if (strncmp(command, "REASSOC", 7) == 0)
1638 {
1639 tANI_U8 *value = command;
1640 tANI_U8 channel = 0;
1641 tSirMacAddr targetApBssid;
1642 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001643#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1644 tCsrHandoffRequest handoffInfo;
1645#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001646 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001647 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1648
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001649 /* if not associated, no need to proceed with reassoc */
1650 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1651 {
1652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1653 ret = -EINVAL;
1654 goto exit;
1655 }
1656
1657 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1658 if (eHAL_STATUS_SUCCESS != status)
1659 {
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: Failed to parse reassoc command data", __func__);
1662 ret = -EINVAL;
1663 goto exit;
1664 }
1665
1666 /* if the target bssid is same as currently associated AP,
1667 then no need to proceed with reassoc */
1668 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1669 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1670 {
1671 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1672 ret = -EINVAL;
1673 goto exit;
1674 }
1675
1676 /* Check channel number is a valid channel number */
1677 if(VOS_STATUS_SUCCESS !=
1678 wlan_hdd_validate_operation_channel(pAdapter, channel))
1679 {
1680 hddLog(VOS_TRACE_LEVEL_ERROR,
1681 "%s: Invalid Channel [%d] \n", __func__, channel);
1682 return -EINVAL;
1683 }
1684
1685 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001686#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1687 handoffInfo.channel = channel;
1688 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1689 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1690#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001691 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001692#endif
1693#ifdef FEATURE_WLAN_LFR
1694 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1695 {
1696 tANI_U8 *value = command;
1697 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1698
1699 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1700 value = value + 12;
1701 /* Convert the value from ascii to integer */
1702 ret = kstrtou8(value, 10, &lfrMode);
1703 if (ret < 0)
1704 {
1705 /* If the input value is greater than max value of datatype, then also
1706 kstrtou8 fails */
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: kstrtou8 failed range [%d - %d]", __func__,
1709 CFG_LFR_FEATURE_ENABLED_MIN,
1710 CFG_LFR_FEATURE_ENABLED_MAX);
1711 ret = -EINVAL;
1712 goto exit;
1713 }
1714
1715 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1716 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1717 {
1718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1719 "lfr mode value %d is out of range"
1720 " (Min: %d Max: %d)", lfrMode,
1721 CFG_LFR_FEATURE_ENABLED_MIN,
1722 CFG_LFR_FEATURE_ENABLED_MAX);
1723 ret = -EINVAL;
1724 goto exit;
1725 }
1726
1727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1728 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1729
1730 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1731 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1732 }
1733#endif
1734#ifdef WLAN_FEATURE_VOWIFI_11R
1735 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1736 {
1737 tANI_U8 *value = command;
1738 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1739
1740 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1741 value = value + 18;
1742 /* Convert the value from ascii to integer */
1743 ret = kstrtou8(value, 10, &ft);
1744 if (ret < 0)
1745 {
1746 /* If the input value is greater than max value of datatype, then also
1747 kstrtou8 fails */
1748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1749 "%s: kstrtou8 failed range [%d - %d]", __func__,
1750 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1751 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1757 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1758 {
1759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1760 "ft mode value %d is out of range"
1761 " (Min: %d Max: %d)", ft,
1762 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1763 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1764 ret = -EINVAL;
1765 goto exit;
1766 }
1767
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1769 "%s: Received Command to change ft mode = %d", __func__, ft);
1770
1771 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1772 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1773 }
1774#endif
1775#ifdef FEATURE_WLAN_CCX
1776 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1777 {
1778 tANI_U8 *value = command;
1779 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1780
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001781 /* Check if the features OKC/CCX/11R are supported simultaneously,
1782 then this operation is not permitted (return FAILURE) */
1783 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1784 hdd_is_okc_mode_enabled(pHddCtx) &&
1785 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1786 {
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1788 "%s: OKC/CCX/11R are supported simultaneously"
1789 " hence this operation is not permitted!", __func__);
1790 ret = -EPERM;
1791 goto exit;
1792 }
1793
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001794 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1795 value = value + 11;
1796 /* Convert the value from ascii to integer */
1797 ret = kstrtou8(value, 10, &ccxMode);
1798 if (ret < 0)
1799 {
1800 /* If the input value is greater than max value of datatype, then also
1801 kstrtou8 fails */
1802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1803 "%s: kstrtou8 failed range [%d - %d]", __func__,
1804 CFG_CCX_FEATURE_ENABLED_MIN,
1805 CFG_CCX_FEATURE_ENABLED_MAX);
1806 ret = -EINVAL;
1807 goto exit;
1808 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001809 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1810 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "Ccx mode value %d is out of range"
1814 " (Min: %d Max: %d)", ccxMode,
1815 CFG_CCX_FEATURE_ENABLED_MIN,
1816 CFG_CCX_FEATURE_ENABLED_MAX);
1817 ret = -EINVAL;
1818 goto exit;
1819 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1821 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1822
1823 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1824 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1825 }
1826#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001827 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1828 {
1829 tANI_U8 *value = command;
1830 tANI_BOOLEAN roamScanControl = 0;
1831
1832 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1833 value = value + 19;
1834 /* Convert the value from ascii to integer */
1835 ret = kstrtou8(value, 10, &roamScanControl);
1836 if (ret < 0)
1837 {
1838 /* If the input value is greater than max value of datatype, then also
1839 kstrtou8 fails */
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1841 "%s: kstrtou8 failed ", __func__);
1842 ret = -EINVAL;
1843 goto exit;
1844 }
1845
1846 if (0 != roamScanControl)
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "roam scan control invalid value = %d",
1850 roamScanControl);
1851 ret = -EINVAL;
1852 goto exit;
1853 }
1854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1855 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1856
1857 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1858 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001859#ifdef FEATURE_WLAN_OKC
1860 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1861 {
1862 tANI_U8 *value = command;
1863 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1864
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001865 /* Check if the features OKC/CCX/11R are supported simultaneously,
1866 then this operation is not permitted (return FAILURE) */
1867 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1868 hdd_is_okc_mode_enabled(pHddCtx) &&
1869 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1870 {
1871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1872 "%s: OKC/CCX/11R are supported simultaneously"
1873 " hence this operation is not permitted!", __func__);
1874 ret = -EPERM;
1875 goto exit;
1876 }
1877
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001878 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1879 value = value + 11;
1880 /* Convert the value from ascii to integer */
1881 ret = kstrtou8(value, 10, &okcMode);
1882 if (ret < 0)
1883 {
1884 /* If the input value is greater than max value of datatype, then also
1885 kstrtou8 fails */
1886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1887 "%s: kstrtou8 failed range [%d - %d]", __func__,
1888 CFG_OKC_FEATURE_ENABLED_MIN,
1889 CFG_OKC_FEATURE_ENABLED_MAX);
1890 ret = -EINVAL;
1891 goto exit;
1892 }
1893
1894 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1895 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1896 {
1897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1898 "Okc mode value %d is out of range"
1899 " (Min: %d Max: %d)", okcMode,
1900 CFG_OKC_FEATURE_ENABLED_MIN,
1901 CFG_OKC_FEATURE_ENABLED_MAX);
1902 ret = -EINVAL;
1903 goto exit;
1904 }
1905
1906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1907 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1908
1909 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1910 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001911 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1912 {
1913 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1914 char extra[32];
1915 tANI_U8 len = 0;
1916
1917 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1918 if (copy_to_user(priv_data.buf, &extra, len + 1))
1919 {
1920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 "%s: failed to copy data to user buffer", __func__);
1922 ret = -EFAULT;
1923 goto exit;
1924 }
1925 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001926#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301927#ifdef WLAN_FEATURE_PACKET_FILTERING
1928 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1929 {
1930 tANI_U8 filterType = 0;
1931 tANI_U8 *value = command;
1932
1933 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1934 value = value + 22;
1935
1936 /* Convert the value from ascii to integer */
1937 ret = kstrtou8(value, 10, &filterType);
1938 if (ret < 0)
1939 {
1940 /* If the input value is greater than max value of datatype,
1941 * then also kstrtou8 fails
1942 */
1943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1944 "%s: kstrtou8 failed range ", __func__);
1945 ret = -EINVAL;
1946 goto exit;
1947 }
1948
1949 if (filterType != 0 && filterType != 1)
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1952 "%s: Accepted Values are 0 and 1 ", __func__);
1953 ret = -EINVAL;
1954 goto exit;
1955 }
1956 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
1957 pAdapter->sessionId);
1958 }
1959#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05301960 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
1961 {
1962 char *dhcpPhase;
1963 dhcpPhase = command + 12;
1964 if ('1' == *dhcpPhase)
1965 {
1966 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
1967 pAdapter->macAddressCurrent.bytes);
1968 }
1969 else if ('2' == *dhcpPhase)
1970 {
1971 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
1972 pAdapter->macAddressCurrent.bytes);
1973 }
1974 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07001975 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
1976 {
1977 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
1978 }
1979 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
1980 {
1981 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
1982 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05301983 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
1984 {
1985 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1986 char extra[32];
1987 tANI_U8 len = 0;
1988
1989 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
1990 (int)pCfg->nActiveMaxChnTime);
1991 if (copy_to_user(priv_data.buf, &extra, len + 1))
1992 {
1993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1994 "%s: failed to copy data to user buffer", __func__);
1995 ret = -EFAULT;
1996 goto exit;
1997 }
1998 ret = len;
1999 }
2000 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2001 {
2002 tANI_U8 *value = command;
2003 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2004 int val = 0, temp;
2005
2006 value = value + 13;
2007 temp = kstrtou32(value, 10, &val);
2008 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2009 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2010 {
2011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2012 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2013 ret = -EFAULT;
2014 goto exit;
2015 }
2016 pCfg->nActiveMaxChnTime = val;
2017 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002018 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2019 {
2020 tANI_U8 filterType = 0;
2021 tANI_U8 *value;
2022 value = command + 9;
2023
2024 /* Convert the value from ascii to integer */
2025 ret = kstrtou8(value, 10, &filterType);
2026 if (ret < 0)
2027 {
2028 /* If the input value is greater than max value of datatype,
2029 * then also kstrtou8 fails
2030 */
2031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2032 "%s: kstrtou8 failed range ", __func__);
2033 ret = -EINVAL;
2034 goto exit;
2035 }
2036 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2037 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2038 {
2039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2040 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2041 " 2-Sink ", __func__);
2042 ret = -EINVAL;
2043 goto exit;
2044 }
2045 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2046 pHddCtx->drvr_miracast = filterType;
2047 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2048 }
Leo Chang614d2072013-08-22 14:59:44 -07002049 else if (strncmp(command, "SETMCRATE", 9) == 0)
2050 {
2051 int rc;
2052 tANI_U8 *value = command;
2053 int targetRate;
2054
2055 /* Only valid for SAP mode */
2056 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2057 {
2058 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: SAP mode is not running", __func__);
2060 ret = -EFAULT;
2061 goto exit;
2062 }
2063
2064 /* Move pointer to ahead of SETMCRATE<delimiter> */
2065 /* input value is in units of hundred kbps */
2066 value = value + 10;
2067 /* Convert the value from ascii to integer, decimal base */
2068 ret = kstrtouint(value, 10, &targetRate);
2069
2070 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2071 if (rc)
2072 {
2073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "%s: Set MC Rate Fail %d", __func__, rc);
2075 ret = -EFAULT;
2076 goto exit;
2077 }
2078 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002079 else {
2080 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2081 __func__, command);
2082 }
2083
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 }
2085exit:
2086 if (command)
2087 {
2088 kfree(command);
2089 }
2090 return ret;
2091}
2092
Srinivas Girigowdade697412013-02-14 16:31:48 -08002093#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2094void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2095{
2096 eCsrBand band = -1;
2097 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2098 switch (band)
2099 {
2100 case eCSR_BAND_ALL:
2101 *pBand = WLAN_HDD_UI_BAND_AUTO;
2102 break;
2103
2104 case eCSR_BAND_24:
2105 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2106 break;
2107
2108 case eCSR_BAND_5G:
2109 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2110 break;
2111
2112 default:
2113 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2114 *pBand = -1;
2115 break;
2116 }
2117}
2118
2119/**---------------------------------------------------------------------------
2120
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002121 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2122
2123 This function parses the send action frame data passed in the format
2124 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2125
Srinivas Girigowda56076852013-08-20 14:00:50 -07002126 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002127 \param - pTargetApBssid Pointer to target Ap bssid
2128 \param - pChannel Pointer to the Target AP channel
2129 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2130 \param - pBuf Pointer to data
2131 \param - pBufLen Pointer to data length
2132
2133 \return - 0 for success non-zero for failure
2134
2135 --------------------------------------------------------------------------*/
2136VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2137 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2138{
2139 tANI_U8 *inPtr = pValue;
2140 tANI_U8 *dataEnd;
2141 int tempInt;
2142 int j = 0;
2143 int i = 0;
2144 int v = 0;
2145 tANI_U8 tempBuf[32];
2146 tANI_U8 tempByte = 0;
2147
2148 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2149 /*no argument after the command*/
2150 if (NULL == inPtr)
2151 {
2152 return -EINVAL;
2153 }
2154
2155 /*no space after the command*/
2156 else if (SPACE_ASCII_VALUE != *inPtr)
2157 {
2158 return -EINVAL;
2159 }
2160
2161 /*removing empty spaces*/
2162 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2163
2164 /*no argument followed by spaces*/
2165 if ('\0' == *inPtr)
2166 {
2167 return -EINVAL;
2168 }
2169
2170 /*getting the first argument ie the target AP bssid */
2171 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2172 {
2173 return -EINVAL;
2174 }
2175 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2176 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2177 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2178
2179 /* point to the next argument */
2180 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2181 /*no argument after the command*/
2182 if (NULL == inPtr) return -EINVAL;
2183
2184 /*removing empty spaces*/
2185 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2186
2187 /*no argument followed by spaces*/
2188 if ('\0' == *inPtr)
2189 {
2190 return -EINVAL;
2191 }
2192
2193 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002194 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002195 v = kstrtos32(tempBuf, 10, &tempInt);
2196 if ( v < 0) return -EINVAL;
2197
2198 *pChannel = tempInt;
2199
2200 /* point to the next argument */
2201 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2202 /*no argument after the command*/
2203 if (NULL == inPtr) return -EINVAL;
2204 /*removing empty spaces*/
2205 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2206
2207 /*no argument followed by spaces*/
2208 if ('\0' == *inPtr)
2209 {
2210 return -EINVAL;
2211 }
2212
2213 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002214 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002215 v = kstrtos32(tempBuf, 10, &tempInt);
2216 if ( v < 0) return -EINVAL;
2217
2218 *pDwellTime = tempInt;
2219
2220 /* point to the next argument */
2221 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2222 /*no argument after the command*/
2223 if (NULL == inPtr) return -EINVAL;
2224 /*removing empty spaces*/
2225 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2226
2227 /*no argument followed by spaces*/
2228 if ('\0' == *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 /* find the length of data */
2234 dataEnd = inPtr;
2235 while(('\0' != *dataEnd) )
2236 {
2237 dataEnd++;
2238 ++(*pBufLen);
2239 }
2240 if ( *pBufLen <= 0) return -EINVAL;
2241
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002242 /* Allocate the number of bytes based on the number of input characters
2243 whether it is even or odd.
2244 if the number of input characters are even, then we need N/2 byte.
2245 if the number of input characters are odd, then we need do (N+1)/2 to
2246 compensate rounding off.
2247 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2248 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2249 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002250 if (NULL == *pBuf)
2251 {
2252 hddLog(VOS_TRACE_LEVEL_FATAL,
2253 "%s: vos_mem_alloc failed ", __func__);
2254 return -EINVAL;
2255 }
2256
2257 /* the buffer received from the upper layer is character buffer,
2258 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2259 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2260 and f0 in 3rd location */
2261 for (i = 0, j = 0; j < *pBufLen; j += 2)
2262 {
2263 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2264 (*pBuf)[i++] = tempByte;
2265 }
2266 *pBufLen = i;
2267 return VOS_STATUS_SUCCESS;
2268}
2269
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002270/**---------------------------------------------------------------------------
2271
Srinivas Girigowdade697412013-02-14 16:31:48 -08002272 \brief hdd_parse_channellist() - HDD Parse channel list
2273
2274 This function parses the channel list passed in the format
2275 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002276 if the Number of channels (N) does not match with the actual number of channels passed
2277 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2278 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2279 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2280 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002281
2282 \param - pValue Pointer to input channel list
2283 \param - ChannelList Pointer to local output array to record channel list
2284 \param - pNumChannels Pointer to number of roam scan channels
2285
2286 \return - 0 for success non-zero for failure
2287
2288 --------------------------------------------------------------------------*/
2289VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2290{
2291 tANI_U8 *inPtr = pValue;
2292 int tempInt;
2293 int j = 0;
2294 int v = 0;
2295 char buf[32];
2296
2297 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2298 /*no argument after the command*/
2299 if (NULL == inPtr)
2300 {
2301 return -EINVAL;
2302 }
2303
2304 /*no space after the command*/
2305 else if (SPACE_ASCII_VALUE != *inPtr)
2306 {
2307 return -EINVAL;
2308 }
2309
2310 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002311 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002312
2313 /*no argument followed by spaces*/
2314 if ('\0' == *inPtr)
2315 {
2316 return -EINVAL;
2317 }
2318
2319 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002320 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002321 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002322 if ((v < 0) ||
2323 (tempInt <= 0) ||
2324 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2325 {
2326 return -EINVAL;
2327 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002328
2329 *pNumChannels = tempInt;
2330
2331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2332 "Number of channels are: %d", *pNumChannels);
2333
2334 for (j = 0; j < (*pNumChannels); j++)
2335 {
2336 /*inPtr pointing to the beginning of first space after number of channels*/
2337 inPtr = strpbrk( inPtr, " " );
2338 /*no channel list after the number of channels argument*/
2339 if (NULL == inPtr)
2340 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002341 if (0 != j)
2342 {
2343 *pNumChannels = j;
2344 return VOS_STATUS_SUCCESS;
2345 }
2346 else
2347 {
2348 return -EINVAL;
2349 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350 }
2351
2352 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002353 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002354
2355 /*no channel list after the number of channels argument and spaces*/
2356 if ( '\0' == *inPtr )
2357 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002358 if (0 != j)
2359 {
2360 *pNumChannels = j;
2361 return VOS_STATUS_SUCCESS;
2362 }
2363 else
2364 {
2365 return -EINVAL;
2366 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002367 }
2368
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002369 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002371 if ((v < 0) ||
2372 (tempInt <= 0) ||
2373 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2374 {
2375 return -EINVAL;
2376 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 pChannelList[j] = tempInt;
2378
2379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2380 "Channel %d added to preferred channel list",
2381 pChannelList[j] );
2382 }
2383
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384 return VOS_STATUS_SUCCESS;
2385}
2386
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002387
2388/**---------------------------------------------------------------------------
2389
2390 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2391
2392 This function parses the reasoc command data passed in the format
2393 REASSOC<space><bssid><space><channel>
2394
Srinivas Girigowda56076852013-08-20 14:00:50 -07002395 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002396 \param - pTargetApBssid Pointer to target Ap bssid
2397 \param - pChannel Pointer to the Target AP channel
2398
2399 \return - 0 for success non-zero for failure
2400
2401 --------------------------------------------------------------------------*/
2402VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2403{
2404 tANI_U8 *inPtr = pValue;
2405 int tempInt;
2406 int v = 0;
2407 tANI_U8 tempBuf[32];
2408
2409 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2410 /*no argument after the command*/
2411 if (NULL == inPtr)
2412 {
2413 return -EINVAL;
2414 }
2415
2416 /*no space after the command*/
2417 else if (SPACE_ASCII_VALUE != *inPtr)
2418 {
2419 return -EINVAL;
2420 }
2421
2422 /*removing empty spaces*/
2423 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2424
2425 /*no argument followed by spaces*/
2426 if ('\0' == *inPtr)
2427 {
2428 return -EINVAL;
2429 }
2430
2431 /*getting the first argument ie the target AP bssid */
2432 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2433 {
2434 return -EINVAL;
2435 }
2436 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2437 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2438 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2439
2440 /* point to the next argument */
2441 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2442 /*no argument after the command*/
2443 if (NULL == inPtr) return -EINVAL;
2444
2445 /*removing empty spaces*/
2446 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2447
2448 /*no argument followed by spaces*/
2449 if ('\0' == *inPtr)
2450 {
2451 return -EINVAL;
2452 }
2453
2454 /*getting the next argument ie the channel number */
2455 sscanf(inPtr, "%s ", tempBuf);
2456 v = kstrtos32(tempBuf, 10, &tempInt);
2457 if ( v < 0) return -EINVAL;
2458
2459 *pChannel = tempInt;
2460 return VOS_STATUS_SUCCESS;
2461}
2462
2463#endif
2464
Jeff Johnson295189b2012-06-20 16:38:30 -07002465/**---------------------------------------------------------------------------
2466
2467 \brief hdd_open() - HDD Open function
2468
2469 This is called in response to ifconfig up
2470
2471 \param - dev Pointer to net_device structure
2472
2473 \return - 0 for success non-zero for failure
2474
2475 --------------------------------------------------------------------------*/
2476int hdd_open (struct net_device *dev)
2477{
2478 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2479 hdd_context_t *pHddCtx;
2480 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2481 VOS_STATUS status;
2482 v_BOOL_t in_standby = TRUE;
2483
2484 if (NULL == pAdapter)
2485 {
2486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002487 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002488 return -ENODEV;
2489 }
2490
2491 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2492 if (NULL == pHddCtx)
2493 {
2494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002495 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002496 return -ENODEV;
2497 }
2498
2499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2500 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2501 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002502 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2503 {
2504 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302505 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002506 in_standby = FALSE;
2507 break;
2508 }
2509 else
2510 {
2511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2512 pAdapterNode = pNext;
2513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 }
2515
2516 if (TRUE == in_standby)
2517 {
2518 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2519 {
2520 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2521 "wlan out of power save", __func__);
2522 return -EINVAL;
2523 }
2524 }
2525
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002526 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002527 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2528 {
2529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002530 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 /* Enable TX queues only when we are connected */
2532 netif_tx_start_all_queues(dev);
2533 }
2534
2535 return 0;
2536}
2537
2538int hdd_mon_open (struct net_device *dev)
2539{
2540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2541
2542 if(pAdapter == NULL) {
2543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002544 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002545 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002546 }
2547
2548 netif_start_queue(dev);
2549
2550 return 0;
2551}
2552/**---------------------------------------------------------------------------
2553
2554 \brief hdd_stop() - HDD stop function
2555
2556 This is called in response to ifconfig down
2557
2558 \param - dev Pointer to net_device structure
2559
2560 \return - 0 for success non-zero for failure
2561
2562 --------------------------------------------------------------------------*/
2563
2564int hdd_stop (struct net_device *dev)
2565{
2566 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2567 hdd_context_t *pHddCtx;
2568 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2569 VOS_STATUS status;
2570 v_BOOL_t enter_standby = TRUE;
2571
2572 ENTER();
2573
2574 if (NULL == pAdapter)
2575 {
2576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002577 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002578 return -ENODEV;
2579 }
2580
2581 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2582 if (NULL == pHddCtx)
2583 {
2584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002585 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 return -ENODEV;
2587 }
2588
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002589 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2591 netif_tx_disable(pAdapter->dev);
2592 netif_carrier_off(pAdapter->dev);
2593
2594
2595 /* SoftAP ifaces should never go in power save mode
2596 making sure same here. */
2597 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2598 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 )
2601 {
2602 /* SoftAP mode, so return from here */
2603 EXIT();
2604 return 0;
2605 }
2606
2607 /* Find if any iface is up then
2608 if any iface is up then can't put device to sleep/ power save mode. */
2609 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2610 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2611 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002612 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2613 {
2614 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302615 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002616 enter_standby = FALSE;
2617 break;
2618 }
2619 else
2620 {
2621 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2622 pAdapterNode = pNext;
2623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002624 }
2625
2626 if (TRUE == enter_standby)
2627 {
2628 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2629 "entering standby", __func__);
2630 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2631 {
2632 /*log and return success*/
2633 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2634 "wlan in power save", __func__);
2635 }
2636 }
2637
2638 EXIT();
2639 return 0;
2640}
2641
2642/**---------------------------------------------------------------------------
2643
2644 \brief hdd_uninit() - HDD uninit function
2645
2646 This is called during the netdev unregister to uninitialize all data
2647associated with the device
2648
2649 \param - dev Pointer to net_device structure
2650
2651 \return - void
2652
2653 --------------------------------------------------------------------------*/
2654static void hdd_uninit (struct net_device *dev)
2655{
2656 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2657
2658 ENTER();
2659
2660 do
2661 {
2662 if (NULL == pAdapter)
2663 {
2664 hddLog(VOS_TRACE_LEVEL_FATAL,
2665 "%s: NULL pAdapter", __func__);
2666 break;
2667 }
2668
2669 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2670 {
2671 hddLog(VOS_TRACE_LEVEL_FATAL,
2672 "%s: Invalid magic", __func__);
2673 break;
2674 }
2675
2676 if (NULL == pAdapter->pHddCtx)
2677 {
2678 hddLog(VOS_TRACE_LEVEL_FATAL,
2679 "%s: NULL pHddCtx", __func__);
2680 break;
2681 }
2682
2683 if (dev != pAdapter->dev)
2684 {
2685 hddLog(VOS_TRACE_LEVEL_FATAL,
2686 "%s: Invalid device reference", __func__);
2687 /* we haven't validated all cases so let this go for now */
2688 }
2689
2690 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2691
2692 /* after uninit our adapter structure will no longer be valid */
2693 pAdapter->dev = NULL;
2694 pAdapter->magic = 0;
2695 } while (0);
2696
2697 EXIT();
2698}
2699
2700/**---------------------------------------------------------------------------
2701
2702 \brief hdd_release_firmware() -
2703
2704 This function calls the release firmware API to free the firmware buffer.
2705
2706 \param - pFileName Pointer to the File Name.
2707 pCtx - Pointer to the adapter .
2708
2709
2710 \return - 0 for success, non zero for failure
2711
2712 --------------------------------------------------------------------------*/
2713
2714VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2715{
2716 VOS_STATUS status = VOS_STATUS_SUCCESS;
2717 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2718 ENTER();
2719
2720
2721 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2722
2723 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2724
2725 if(pHddCtx->fw) {
2726 release_firmware(pHddCtx->fw);
2727 pHddCtx->fw = NULL;
2728 }
2729 else
2730 status = VOS_STATUS_E_FAILURE;
2731 }
2732 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2733 if(pHddCtx->nv) {
2734 release_firmware(pHddCtx->nv);
2735 pHddCtx->nv = NULL;
2736 }
2737 else
2738 status = VOS_STATUS_E_FAILURE;
2739
2740 }
2741
2742 EXIT();
2743 return status;
2744}
2745
2746/**---------------------------------------------------------------------------
2747
2748 \brief hdd_request_firmware() -
2749
2750 This function reads the firmware file using the request firmware
2751 API and returns the the firmware data and the firmware file size.
2752
2753 \param - pfileName - Pointer to the file name.
2754 - pCtx - Pointer to the adapter .
2755 - ppfw_data - Pointer to the pointer of the firmware data.
2756 - pSize - Pointer to the file size.
2757
2758 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2759
2760 --------------------------------------------------------------------------*/
2761
2762
2763VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2764{
2765 int status;
2766 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2767 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2768 ENTER();
2769
2770 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2771
2772 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2773
2774 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2775 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2776 __func__, pfileName);
2777 retval = VOS_STATUS_E_FAILURE;
2778 }
2779
2780 else {
2781 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2782 *pSize = pHddCtx->fw->size;
2783 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2784 __func__, *pSize);
2785 }
2786 }
2787 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2788
2789 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2790
2791 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2792 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2793 __func__, pfileName);
2794 retval = VOS_STATUS_E_FAILURE;
2795 }
2796
2797 else {
2798 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2799 *pSize = pHddCtx->nv->size;
2800 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2801 __func__, *pSize);
2802 }
2803 }
2804
2805 EXIT();
2806 return retval;
2807}
2808/**---------------------------------------------------------------------------
2809 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2810
2811 This is the function invoked by SME to inform the result of a full power
2812 request issued by HDD
2813
2814 \param - callbackcontext - Pointer to cookie
2815 status - result of request
2816
2817 \return - None
2818
2819--------------------------------------------------------------------------*/
2820void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2821{
2822 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2823
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002824 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 if(&pHddCtx->full_pwr_comp_var)
2826 {
2827 complete(&pHddCtx->full_pwr_comp_var);
2828 }
2829}
2830
2831/**---------------------------------------------------------------------------
2832
2833 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2834
2835 This is the function invoked by SME to inform the result of BMPS
2836 request issued by HDD
2837
2838 \param - callbackcontext - Pointer to cookie
2839 status - result of request
2840
2841 \return - None
2842
2843--------------------------------------------------------------------------*/
2844void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2845{
2846
2847 struct completion *completion_var = (struct completion*) callbackContext;
2848
2849 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2850 if(completion_var != NULL)
2851 {
2852 complete(completion_var);
2853 }
2854}
2855
2856/**---------------------------------------------------------------------------
2857
2858 \brief hdd_get_cfg_file_size() -
2859
2860 This function reads the configuration file using the request firmware
2861 API and returns the configuration file size.
2862
2863 \param - pCtx - Pointer to the adapter .
2864 - pFileName - Pointer to the file name.
2865 - pBufSize - Pointer to the buffer size.
2866
2867 \return - 0 for success, non zero for failure
2868
2869 --------------------------------------------------------------------------*/
2870
2871VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2872{
2873 int status;
2874 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2875
2876 ENTER();
2877
2878 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2879
2880 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2881 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2882 status = VOS_STATUS_E_FAILURE;
2883 }
2884 else {
2885 *pBufSize = pHddCtx->fw->size;
2886 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2887 release_firmware(pHddCtx->fw);
2888 pHddCtx->fw = NULL;
2889 }
2890
2891 EXIT();
2892 return VOS_STATUS_SUCCESS;
2893}
2894
2895/**---------------------------------------------------------------------------
2896
2897 \brief hdd_read_cfg_file() -
2898
2899 This function reads the configuration file using the request firmware
2900 API and returns the cfg data and the buffer size of the configuration file.
2901
2902 \param - pCtx - Pointer to the adapter .
2903 - pFileName - Pointer to the file name.
2904 - pBuffer - Pointer to the data buffer.
2905 - pBufSize - Pointer to the buffer size.
2906
2907 \return - 0 for success, non zero for failure
2908
2909 --------------------------------------------------------------------------*/
2910
2911VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2912 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2913{
2914 int status;
2915 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2916
2917 ENTER();
2918
2919 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2920
2921 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2923 return VOS_STATUS_E_FAILURE;
2924 }
2925 else {
2926 if(*pBufSize != pHddCtx->fw->size) {
2927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2928 "file size", __func__);
2929 release_firmware(pHddCtx->fw);
2930 pHddCtx->fw = NULL;
2931 return VOS_STATUS_E_FAILURE;
2932 }
2933 else {
2934 if(pBuffer) {
2935 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2936 }
2937 release_firmware(pHddCtx->fw);
2938 pHddCtx->fw = NULL;
2939 }
2940 }
2941
2942 EXIT();
2943
2944 return VOS_STATUS_SUCCESS;
2945}
2946
2947/**---------------------------------------------------------------------------
2948
Jeff Johnson295189b2012-06-20 16:38:30 -07002949 \brief hdd_set_mac_address() -
2950
2951 This function sets the user specified mac address using
2952 the command ifconfig wlanX hw ether <mac adress>.
2953
2954 \param - dev - Pointer to the net device.
2955 - addr - Pointer to the sockaddr.
2956 \return - 0 for success, non zero for failure
2957
2958 --------------------------------------------------------------------------*/
2959
2960static int hdd_set_mac_address(struct net_device *dev, void *addr)
2961{
2962 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2963 struct sockaddr *psta_mac_addr = addr;
2964 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2965
2966 ENTER();
2967
2968 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2969
2970#ifdef HDD_SESSIONIZE
2971 // set the MAC address though the STA ID CFG.
2972 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2973 (v_U8_t *)&pAdapter->macAddressCurrent,
2974 sizeof( pAdapter->macAddressCurrent ),
2975 hdd_set_mac_addr_cb, VOS_FALSE );
2976#endif
2977
2978 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2979
2980 EXIT();
2981 return halStatus;
2982}
2983
2984tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2985{
2986 int i;
2987 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2988 {
2989 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2990 break;
2991 }
2992
2993 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2994 return NULL;
2995
2996 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2997 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2998}
2999
3000void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3001{
3002 int i;
3003 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3004 {
3005 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3006 {
3007 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3008 break;
3009 }
3010 }
3011 return;
3012}
3013
3014#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3015 static struct net_device_ops wlan_drv_ops = {
3016 .ndo_open = hdd_open,
3017 .ndo_stop = hdd_stop,
3018 .ndo_uninit = hdd_uninit,
3019 .ndo_start_xmit = hdd_hard_start_xmit,
3020 .ndo_tx_timeout = hdd_tx_timeout,
3021 .ndo_get_stats = hdd_stats,
3022 .ndo_do_ioctl = hdd_ioctl,
3023 .ndo_set_mac_address = hdd_set_mac_address,
3024 .ndo_select_queue = hdd_select_queue,
3025#ifdef WLAN_FEATURE_PACKET_FILTERING
3026#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3027 .ndo_set_rx_mode = hdd_set_multicast_list,
3028#else
3029 .ndo_set_multicast_list = hdd_set_multicast_list,
3030#endif //LINUX_VERSION_CODE
3031#endif
3032 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003033 static struct net_device_ops wlan_mon_drv_ops = {
3034 .ndo_open = hdd_mon_open,
3035 .ndo_stop = hdd_stop,
3036 .ndo_uninit = hdd_uninit,
3037 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3038 .ndo_tx_timeout = hdd_tx_timeout,
3039 .ndo_get_stats = hdd_stats,
3040 .ndo_do_ioctl = hdd_ioctl,
3041 .ndo_set_mac_address = hdd_set_mac_address,
3042 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003043
3044#endif
3045
3046void hdd_set_station_ops( struct net_device *pWlanDev )
3047{
3048#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3049 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3050 pWlanDev->netdev_ops = &wlan_drv_ops;
3051#else
3052 pWlanDev->open = hdd_open;
3053 pWlanDev->stop = hdd_stop;
3054 pWlanDev->uninit = hdd_uninit;
3055 pWlanDev->hard_start_xmit = NULL;
3056 pWlanDev->tx_timeout = hdd_tx_timeout;
3057 pWlanDev->get_stats = hdd_stats;
3058 pWlanDev->do_ioctl = hdd_ioctl;
3059 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3060 pWlanDev->set_mac_address = hdd_set_mac_address;
3061#endif
3062}
3063
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003064static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003065{
3066 struct net_device *pWlanDev = NULL;
3067 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 /*
3069 * cfg80211 initialization and registration....
3070 */
3071 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3072
Jeff Johnson295189b2012-06-20 16:38:30 -07003073 if(pWlanDev != NULL)
3074 {
3075
3076 //Save the pointer to the net_device in the HDD adapter
3077 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3078
Jeff Johnson295189b2012-06-20 16:38:30 -07003079 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3080
3081 pAdapter->dev = pWlanDev;
3082 pAdapter->pHddCtx = pHddCtx;
3083 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3084
3085 init_completion(&pAdapter->session_open_comp_var);
3086 init_completion(&pAdapter->session_close_comp_var);
3087 init_completion(&pAdapter->disconnect_comp_var);
3088 init_completion(&pAdapter->linkup_event_var);
3089 init_completion(&pAdapter->cancel_rem_on_chan_var);
3090 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003091#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3092 init_completion(&pAdapter->offchannel_tx_event);
3093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003094 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003095#ifdef FEATURE_WLAN_TDLS
3096 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003097 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003098 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303099 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003100#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003101 init_completion(&pHddCtx->mc_sus_event_var);
3102 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303103 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003104 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003105
Jeff Johnson295189b2012-06-20 16:38:30 -07003106 pAdapter->isLinkUpSvcNeeded = FALSE;
3107 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3108 //Init the net_device structure
3109 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3110
3111 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3112 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3113 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3114 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3115
3116 hdd_set_station_ops( pAdapter->dev );
3117
3118 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003119 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3120 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3121 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 /* set pWlanDev's parent to underlying device */
3123 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3124 }
3125
3126 return pAdapter;
3127}
3128
3129VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3130{
3131 struct net_device *pWlanDev = pAdapter->dev;
3132 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3133 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3134 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3135
3136 if( rtnl_lock_held )
3137 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003138 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003139 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3140 {
3141 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3142 return VOS_STATUS_E_FAILURE;
3143 }
3144 }
3145 if (register_netdevice(pWlanDev))
3146 {
3147 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3148 return VOS_STATUS_E_FAILURE;
3149 }
3150 }
3151 else
3152 {
3153 if(register_netdev(pWlanDev))
3154 {
3155 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3156 return VOS_STATUS_E_FAILURE;
3157 }
3158 }
3159 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3160
3161 return VOS_STATUS_SUCCESS;
3162}
3163
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003164static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003165{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003166 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003167
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003168 if (NULL == pAdapter)
3169 {
3170 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3171 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003173
3174 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3175 {
3176 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3177 return eHAL_STATUS_NOT_INITIALIZED;
3178 }
3179
3180 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3181
3182 /* need to make sure all of our scheduled work has completed.
3183 * This callback is called from MC thread context, so it is safe to
3184 * to call below flush workqueue API from here.
3185 */
3186 flush_scheduled_work();
3187
3188 /* We can be blocked while waiting for scheduled work to be
3189 * flushed, and the adapter structure can potentially be freed, in
3190 * which case the magic will have been reset. So make sure the
3191 * magic is still good, and hence the adapter structure is still
3192 * valid, before signaling completion */
3193 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3194 {
3195 complete(&pAdapter->session_close_comp_var);
3196 }
3197
Jeff Johnson295189b2012-06-20 16:38:30 -07003198 return eHAL_STATUS_SUCCESS;
3199}
3200
3201VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3202{
3203 struct net_device *pWlanDev = pAdapter->dev;
3204 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3205 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3206 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3207 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3208 int rc = 0;
3209
3210 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003211 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003212 //Open a SME session for future operation
3213 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003214 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3216 {
3217 hddLog(VOS_TRACE_LEVEL_FATAL,
3218 "sme_OpenSession() failed with status code %08d [x%08lx]",
3219 halStatus, halStatus );
3220 status = VOS_STATUS_E_FAILURE;
3221 goto error_sme_open;
3222 }
3223
3224 //Block on a completion variable. Can't wait forever though.
3225 rc = wait_for_completion_interruptible_timeout(
3226 &pAdapter->session_open_comp_var,
3227 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3228 if (!rc)
3229 {
3230 hddLog(VOS_TRACE_LEVEL_FATAL,
3231 "Session is not opened within timeout period code %08d", rc );
3232 status = VOS_STATUS_E_FAILURE;
3233 goto error_sme_open;
3234 }
3235
3236 // Register wireless extensions
3237 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3238 {
3239 hddLog(VOS_TRACE_LEVEL_FATAL,
3240 "hdd_register_wext() failed with status code %08d [x%08lx]",
3241 halStatus, halStatus );
3242 status = VOS_STATUS_E_FAILURE;
3243 goto error_register_wext;
3244 }
3245 //Safe to register the hard_start_xmit function again
3246#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3247 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3248#else
3249 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3250#endif
3251
3252 //Set the Connection State to Not Connected
3253 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3254
3255 //Set the default operation channel
3256 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3257
3258 /* Make the default Auth Type as OPEN*/
3259 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3260
3261 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3262 {
3263 hddLog(VOS_TRACE_LEVEL_FATAL,
3264 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3265 status, status );
3266 goto error_init_txrx;
3267 }
3268
3269 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3270
3271 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3272 {
3273 hddLog(VOS_TRACE_LEVEL_FATAL,
3274 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3275 status, status );
3276 goto error_wmm_init;
3277 }
3278
3279 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3280
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003281#ifdef FEATURE_WLAN_TDLS
3282 if(0 != wlan_hdd_tdls_init(pAdapter))
3283 {
3284 status = VOS_STATUS_E_FAILURE;
3285 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3286 goto error_tdls_init;
3287 }
3288 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3289#endif
3290
Jeff Johnson295189b2012-06-20 16:38:30 -07003291 return VOS_STATUS_SUCCESS;
3292
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003293#ifdef FEATURE_WLAN_TDLS
3294error_tdls_init:
3295 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3296 hdd_wmm_adapter_close(pAdapter);
3297#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003298error_wmm_init:
3299 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3300 hdd_deinit_tx_rx(pAdapter);
3301error_init_txrx:
3302 hdd_UnregisterWext(pWlanDev);
3303error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003304 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003305 {
3306 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003307 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003309 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 {
3311 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003312 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003313 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003314 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 }
3316}
3317error_sme_open:
3318 return status;
3319}
3320
Jeff Johnson295189b2012-06-20 16:38:30 -07003321void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3322{
3323 hdd_cfg80211_state_t *cfgState;
3324
3325 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3326
3327 if( NULL != cfgState->buf )
3328 {
3329 int rc;
3330 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3331 rc = wait_for_completion_interruptible_timeout(
3332 &pAdapter->tx_action_cnf_event,
3333 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3334 if(!rc)
3335 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003336 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003337 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3338 }
3339 }
3340 return;
3341}
Jeff Johnson295189b2012-06-20 16:38:30 -07003342
3343void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3344{
3345 ENTER();
3346 switch ( pAdapter->device_mode )
3347 {
3348 case WLAN_HDD_INFRA_STATION:
3349 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003350 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 {
3352 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3353 {
3354 hdd_deinit_tx_rx( pAdapter );
3355 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3356 }
3357
3358 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3359 {
3360 hdd_wmm_adapter_close( pAdapter );
3361 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3362 }
3363
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003365#ifdef FEATURE_WLAN_TDLS
3366 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3367 {
3368 wlan_hdd_tdls_exit(pAdapter);
3369 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3370 }
3371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003372
3373 break;
3374 }
3375
3376 case WLAN_HDD_SOFTAP:
3377 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003379 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003380
3381 hdd_unregister_hostapd(pAdapter);
3382 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003383 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 break;
3385 }
3386
3387 case WLAN_HDD_MONITOR:
3388 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003389 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003390 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3391 {
3392 hdd_deinit_tx_rx( pAdapter );
3393 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003395 if(NULL != pAdapterforTx)
3396 {
3397 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003399 break;
3400 }
3401
3402
3403 default:
3404 break;
3405 }
3406
3407 EXIT();
3408}
3409
3410void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3411{
3412 struct net_device *pWlanDev = pAdapter->dev;
3413
3414 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3415 if( rtnl_held )
3416 {
3417 unregister_netdevice(pWlanDev);
3418 }
3419 else
3420 {
3421 unregister_netdev(pWlanDev);
3422 }
3423 // note that the pAdapter is no longer valid at this point
3424 // since the memory has been reclaimed
3425 }
3426
3427}
3428
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003429void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3430{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303431 VOS_STATUS status;
3432 hdd_adapter_t *pAdapter = NULL;
3433 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003434
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303435 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003436
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303437 /*loop through all adapters.*/
3438 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003439 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303440 pAdapter = pAdapterNode->pAdapter;
3441 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3442 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003443
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303444 { // we skip this registration for modes other than STA and P2P client modes.
3445 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3446 pAdapterNode = pNext;
3447 continue;
3448 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003449
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303450 //Apply Dynamic DTIM For P2P
3451 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3452 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3453 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3454 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3455 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3456 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3457 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3458 (eConnectionState_Associated ==
3459 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3460 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3461 {
3462 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003463
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303464 powerRequest.uIgnoreDTIM = 1;
3465 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3466
3467 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3468 {
3469 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3470 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3471 }
3472 else
3473 {
3474 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3475 }
3476
3477 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3478 * specified during Enter/Exit BMPS when LCD off*/
3479 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3480 NULL, eANI_BOOLEAN_FALSE);
3481 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3482 NULL, eANI_BOOLEAN_FALSE);
3483
3484 /* switch to the DTIM specified in cfg.ini */
3485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3486 "Switch to DTIM %d", powerRequest.uListenInterval);
3487 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3488 break;
3489
3490 }
3491
3492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3493 pAdapterNode = pNext;
3494 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003495}
3496
3497void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3498{
3499 /*Switch back to DTIM 1*/
3500 tSirSetPowerParamsReq powerRequest = { 0 };
3501
3502 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3503 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003504 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003505
3506 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3507 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3508 NULL, eANI_BOOLEAN_FALSE);
3509 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3510 NULL, eANI_BOOLEAN_FALSE);
3511
3512 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3513 "Switch to DTIM%d",powerRequest.uListenInterval);
3514 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3515
3516}
3517
Jeff Johnson295189b2012-06-20 16:38:30 -07003518VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3519{
3520 VOS_STATUS status = VOS_STATUS_SUCCESS;
3521
3522 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3523 {
3524 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3525 }
3526
3527 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3528 {
3529 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3530 }
3531
3532 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3533 {
3534 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3535 }
3536
3537 return status;
3538}
3539
3540VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3541{
3542 hdd_adapter_t *pAdapter = NULL;
3543 eHalStatus halStatus;
3544 VOS_STATUS status = VOS_STATUS_E_INVAL;
3545 v_BOOL_t disableBmps = FALSE;
3546 v_BOOL_t disableImps = FALSE;
3547
3548 switch(session_type)
3549 {
3550 case WLAN_HDD_INFRA_STATION:
3551 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003552 case WLAN_HDD_P2P_CLIENT:
3553 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 //Exit BMPS -> Is Sta/P2P Client is already connected
3555 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3556 if((NULL != pAdapter)&&
3557 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3558 {
3559 disableBmps = TRUE;
3560 }
3561
3562 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3563 if((NULL != pAdapter)&&
3564 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3565 {
3566 disableBmps = TRUE;
3567 }
3568
3569 //Exit both Bmps and Imps incase of Go/SAP Mode
3570 if((WLAN_HDD_SOFTAP == session_type) ||
3571 (WLAN_HDD_P2P_GO == session_type))
3572 {
3573 disableBmps = TRUE;
3574 disableImps = TRUE;
3575 }
3576
3577 if(TRUE == disableImps)
3578 {
3579 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3580 {
3581 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3582 }
3583 }
3584
3585 if(TRUE == disableBmps)
3586 {
3587 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3588 {
3589 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3590
3591 if(eHAL_STATUS_SUCCESS != halStatus)
3592 {
3593 status = VOS_STATUS_E_FAILURE;
3594 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3595 VOS_ASSERT(0);
3596 return status;
3597 }
3598 }
3599
3600 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3601 {
3602 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3603
3604 if(eHAL_STATUS_SUCCESS != halStatus)
3605 {
3606 status = VOS_STATUS_E_FAILURE;
3607 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3608 VOS_ASSERT(0);
3609 return status;
3610 }
3611 }
3612 }
3613
3614 if((TRUE == disableBmps) ||
3615 (TRUE == disableImps))
3616 {
3617 /* Now, get the chip into Full Power now */
3618 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3619 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3620 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3621
3622 if(halStatus != eHAL_STATUS_SUCCESS)
3623 {
3624 if(halStatus == eHAL_STATUS_PMC_PENDING)
3625 {
3626 //Block on a completion variable. Can't wait forever though
3627 wait_for_completion_interruptible_timeout(
3628 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3629 }
3630 else
3631 {
3632 status = VOS_STATUS_E_FAILURE;
3633 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3634 VOS_ASSERT(0);
3635 return status;
3636 }
3637 }
3638
3639 status = VOS_STATUS_SUCCESS;
3640 }
3641
3642 break;
3643 }
3644 return status;
3645}
3646
3647hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003648 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 tANI_U8 rtnl_held )
3650{
3651 hdd_adapter_t *pAdapter = NULL;
3652 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3653 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3654 VOS_STATUS exitbmpsStatus;
3655
3656 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3657
3658 //Disable BMPS incase of Concurrency
3659 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3660
3661 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3662 {
3663 //Fail to Exit BMPS
3664 VOS_ASSERT(0);
3665 return NULL;
3666 }
3667
3668 switch(session_type)
3669 {
3670 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003672 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 {
3674 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3675
3676 if( NULL == pAdapter )
3677 return NULL;
3678
Jeff Johnsone7245742012-09-05 17:12:55 -07003679 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3680 NL80211_IFTYPE_P2P_CLIENT:
3681 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003682
Jeff Johnson295189b2012-06-20 16:38:30 -07003683 pAdapter->device_mode = session_type;
3684
3685 status = hdd_init_station_mode( pAdapter );
3686 if( VOS_STATUS_SUCCESS != status )
3687 goto err_free_netdev;
3688
3689 status = hdd_register_interface( pAdapter, rtnl_held );
3690 if( VOS_STATUS_SUCCESS != status )
3691 {
3692 hdd_deinit_adapter(pHddCtx, pAdapter);
3693 goto err_free_netdev;
3694 }
3695 //Stop the Interface TX queue.
3696 netif_tx_disable(pAdapter->dev);
3697 //netif_tx_disable(pWlanDev);
3698 netif_carrier_off(pAdapter->dev);
3699
3700 break;
3701 }
3702
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003704 case WLAN_HDD_SOFTAP:
3705 {
3706 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3707 if( NULL == pAdapter )
3708 return NULL;
3709
Jeff Johnson295189b2012-06-20 16:38:30 -07003710 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3711 NL80211_IFTYPE_AP:
3712 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 pAdapter->device_mode = session_type;
3714
3715 status = hdd_init_ap_mode(pAdapter);
3716 if( VOS_STATUS_SUCCESS != status )
3717 goto err_free_netdev;
3718
3719 status = hdd_register_hostapd( pAdapter, rtnl_held );
3720 if( VOS_STATUS_SUCCESS != status )
3721 {
3722 hdd_deinit_adapter(pHddCtx, pAdapter);
3723 goto err_free_netdev;
3724 }
3725
3726 netif_tx_disable(pAdapter->dev);
3727 netif_carrier_off(pAdapter->dev);
3728
3729 hdd_set_conparam( 1 );
3730 break;
3731 }
3732 case WLAN_HDD_MONITOR:
3733 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3735 if( NULL == pAdapter )
3736 return NULL;
3737
3738 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3739 pAdapter->device_mode = session_type;
3740 status = hdd_register_interface( pAdapter, rtnl_held );
3741#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3742 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3743#else
3744 pAdapter->dev->open = hdd_mon_open;
3745 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3746#endif
3747 hdd_init_tx_rx( pAdapter );
3748 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3749 //Set adapter to be used for data tx. It will use either GO or softap.
3750 pAdapter->sessionCtx.monitor.pAdapterForTx =
3751 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3753 {
3754 pAdapter->sessionCtx.monitor.pAdapterForTx =
3755 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3756 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 /* This workqueue will be used to transmit management packet over
3758 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003759 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3760 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3761 return NULL;
3762 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003763
Jeff Johnson295189b2012-06-20 16:38:30 -07003764 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3765 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 }
3767 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 case WLAN_HDD_FTM:
3769 {
3770 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3771
3772 if( NULL == pAdapter )
3773 return NULL;
3774 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3775 * message while loading driver in FTM mode. */
3776 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3777 pAdapter->device_mode = session_type;
3778 status = hdd_register_interface( pAdapter, rtnl_held );
3779 }
3780 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 default:
3782 {
3783 VOS_ASSERT(0);
3784 return NULL;
3785 }
3786 }
3787
3788
3789 if( VOS_STATUS_SUCCESS == status )
3790 {
3791 //Add it to the hdd's session list.
3792 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3793 if( NULL == pHddAdapterNode )
3794 {
3795 status = VOS_STATUS_E_NOMEM;
3796 }
3797 else
3798 {
3799 pHddAdapterNode->pAdapter = pAdapter;
3800 status = hdd_add_adapter_back ( pHddCtx,
3801 pHddAdapterNode );
3802 }
3803 }
3804
3805 if( VOS_STATUS_SUCCESS != status )
3806 {
3807 if( NULL != pAdapter )
3808 {
3809 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3810 pAdapter = NULL;
3811 }
3812 if( NULL != pHddAdapterNode )
3813 {
3814 vos_mem_free( pHddAdapterNode );
3815 }
3816
3817 goto resume_bmps;
3818 }
3819
3820 if(VOS_STATUS_SUCCESS == status)
3821 {
3822 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3823
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003824 //Initialize the WoWL service
3825 if(!hdd_init_wowl(pAdapter))
3826 {
3827 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3828 goto err_free_netdev;
3829 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 return pAdapter;
3832
3833err_free_netdev:
3834 free_netdev(pAdapter->dev);
3835 wlan_hdd_release_intf_addr( pHddCtx,
3836 pAdapter->macAddressCurrent.bytes );
3837
3838resume_bmps:
3839 //If bmps disabled enable it
3840 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3841 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303842 if (pHddCtx->hdd_wlan_suspended)
3843 {
3844 hdd_set_pwrparams(pHddCtx);
3845 }
3846 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003847 }
3848 return NULL;
3849}
3850
3851VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3852 tANI_U8 rtnl_held )
3853{
3854 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3855 VOS_STATUS status;
3856
3857 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3858 if( VOS_STATUS_SUCCESS != status )
3859 return status;
3860
3861 while ( pCurrent->pAdapter != pAdapter )
3862 {
3863 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3864 if( VOS_STATUS_SUCCESS != status )
3865 break;
3866
3867 pCurrent = pNext;
3868 }
3869 pAdapterNode = pCurrent;
3870 if( VOS_STATUS_SUCCESS == status )
3871 {
3872 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3873 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3874 hdd_remove_adapter( pHddCtx, pAdapterNode );
3875 vos_mem_free( pAdapterNode );
3876
Jeff Johnson295189b2012-06-20 16:38:30 -07003877
3878 /* If there is a single session of STA/P2P client, re-enable BMPS */
3879 if ((!vos_concurrent_sessions_running()) &&
3880 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3881 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3882 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303883 if (pHddCtx->hdd_wlan_suspended)
3884 {
3885 hdd_set_pwrparams(pHddCtx);
3886 }
3887 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 }
3889
3890 return VOS_STATUS_SUCCESS;
3891 }
3892
3893 return VOS_STATUS_E_FAILURE;
3894}
3895
3896VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3897{
3898 hdd_adapter_list_node_t *pHddAdapterNode;
3899 VOS_STATUS status;
3900
3901 ENTER();
3902
3903 do
3904 {
3905 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3906 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3907 {
3908 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3909 vos_mem_free( pHddAdapterNode );
3910 }
3911 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3912
3913 EXIT();
3914
3915 return VOS_STATUS_SUCCESS;
3916}
3917
3918void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3919{
3920 v_U8_t addIE[1] = {0};
3921
3922 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3923 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3924 eANI_BOOLEAN_FALSE) )
3925 {
3926 hddLog(LOGE,
3927 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3928 }
3929
3930 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3931 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3932 eANI_BOOLEAN_FALSE) )
3933 {
3934 hddLog(LOGE,
3935 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3936 }
3937
3938 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3939 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3940 eANI_BOOLEAN_FALSE) )
3941 {
3942 hddLog(LOGE,
3943 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3944 }
3945}
3946
3947VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3948{
3949 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3950 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3951 union iwreq_data wrqu;
3952
3953 ENTER();
3954
3955 switch(pAdapter->device_mode)
3956 {
3957 case WLAN_HDD_INFRA_STATION:
3958 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003959 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3961 {
3962 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3963 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3964 pAdapter->sessionId,
3965 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3966 else
3967 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3968 pAdapter->sessionId,
3969 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3970 //success implies disconnect command got queued up successfully
3971 if(halStatus == eHAL_STATUS_SUCCESS)
3972 {
3973 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3974 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3975 }
3976 memset(&wrqu, '\0', sizeof(wrqu));
3977 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3978 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3979 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3980 }
3981 else
3982 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05303983 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003984 }
3985
3986 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3987 {
3988 INIT_COMPLETION(pAdapter->session_close_comp_var);
3989 if (eHAL_STATUS_SUCCESS ==
3990 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3991 hdd_smeCloseSessionCallback, pAdapter))
3992 {
3993 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003994 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003995 &pAdapter->session_close_comp_var,
3996 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3997 }
3998 }
3999
4000 break;
4001
4002 case WLAN_HDD_SOFTAP:
4003 case WLAN_HDD_P2P_GO:
4004 //Any softap specific cleanup here...
4005 mutex_lock(&pHddCtx->sap_lock);
4006 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4007 {
4008 VOS_STATUS status;
4009 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4010
4011 //Stop Bss.
4012 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4013 if (VOS_IS_STATUS_SUCCESS(status))
4014 {
4015 hdd_hostapd_state_t *pHostapdState =
4016 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4017
4018 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4019
4020 if (!VOS_IS_STATUS_SUCCESS(status))
4021 {
4022 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004023 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004024 }
4025 }
4026 else
4027 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004028 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004029 }
4030 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4031
4032 if (eHAL_STATUS_FAILURE ==
4033 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4034 0, NULL, eANI_BOOLEAN_FALSE))
4035 {
4036 hddLog(LOGE,
4037 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004038 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004039 }
4040
4041 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4042 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4043 eANI_BOOLEAN_FALSE) )
4044 {
4045 hddLog(LOGE,
4046 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4047 }
4048
4049 // Reset WNI_CFG_PROBE_RSP Flags
4050 wlan_hdd_reset_prob_rspies(pAdapter);
4051 kfree(pAdapter->sessionCtx.ap.beacon);
4052 pAdapter->sessionCtx.ap.beacon = NULL;
4053 }
4054 mutex_unlock(&pHddCtx->sap_lock);
4055 break;
4056 case WLAN_HDD_MONITOR:
4057 break;
4058 default:
4059 break;
4060 }
4061
4062 EXIT();
4063 return VOS_STATUS_SUCCESS;
4064}
4065
4066VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4067{
4068 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4069 VOS_STATUS status;
4070 hdd_adapter_t *pAdapter;
4071
4072 ENTER();
4073
4074 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4075
4076 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4077 {
4078 pAdapter = pAdapterNode->pAdapter;
4079 netif_tx_disable(pAdapter->dev);
4080 netif_carrier_off(pAdapter->dev);
4081
4082 hdd_stop_adapter( pHddCtx, pAdapter );
4083
4084 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4085 pAdapterNode = pNext;
4086 }
4087
4088 EXIT();
4089
4090 return VOS_STATUS_SUCCESS;
4091}
4092
4093VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4094{
4095 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4096 VOS_STATUS status;
4097 hdd_adapter_t *pAdapter;
4098
4099 ENTER();
4100
4101 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4102
4103 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4104 {
4105 pAdapter = pAdapterNode->pAdapter;
4106 netif_tx_disable(pAdapter->dev);
4107 netif_carrier_off(pAdapter->dev);
4108
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004109 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4110
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 hdd_deinit_tx_rx(pAdapter);
4112 hdd_wmm_adapter_close(pAdapter);
4113
4114 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4115 pAdapterNode = pNext;
4116 }
4117
4118 EXIT();
4119
4120 return VOS_STATUS_SUCCESS;
4121}
4122
4123VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4124{
4125 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4126 VOS_STATUS status;
4127 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304128 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004129
4130 ENTER();
4131
4132 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4133
4134 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4135 {
4136 pAdapter = pAdapterNode->pAdapter;
4137
4138 switch(pAdapter->device_mode)
4139 {
4140 case WLAN_HDD_INFRA_STATION:
4141 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004142 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304143
4144 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4145
Jeff Johnson295189b2012-06-20 16:38:30 -07004146 hdd_init_station_mode(pAdapter);
4147 /* Open the gates for HDD to receive Wext commands */
4148 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004149 pHddCtx->scan_info.mScanPending = FALSE;
4150 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004151
4152 //Trigger the initial scan
4153 hdd_wlan_initial_scan(pAdapter);
4154
4155 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304156 if (eConnectionState_Associated == connState ||
4157 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004158 {
4159 union iwreq_data wrqu;
4160 memset(&wrqu, '\0', sizeof(wrqu));
4161 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4162 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4163 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004164 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004165
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 /* indicate disconnected event to nl80211 */
4167 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4168 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304170 else if (eConnectionState_Connecting == connState)
4171 {
4172 /*
4173 * Indicate connect failure to supplicant if we were in the
4174 * process of connecting
4175 */
4176 cfg80211_connect_result(pAdapter->dev, NULL,
4177 NULL, 0, NULL, 0,
4178 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4179 GFP_KERNEL);
4180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004181 break;
4182
4183 case WLAN_HDD_SOFTAP:
4184 /* softAP can handle SSR */
4185 break;
4186
4187 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004188 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07004189 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07004190 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004191 break;
4192
4193 case WLAN_HDD_MONITOR:
4194 /* monitor interface start */
4195 break;
4196 default:
4197 break;
4198 }
4199
4200 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4201 pAdapterNode = pNext;
4202 }
4203
4204 EXIT();
4205
4206 return VOS_STATUS_SUCCESS;
4207}
4208
4209VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4210{
4211 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4212 hdd_adapter_t *pAdapter;
4213 VOS_STATUS status;
4214 v_U32_t roamId;
4215
4216 ENTER();
4217
4218 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4219
4220 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4221 {
4222 pAdapter = pAdapterNode->pAdapter;
4223
4224 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4225 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4226 {
4227 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4228 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4229
4230 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4231 init_completion(&pAdapter->disconnect_comp_var);
4232 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4233 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4234
4235 wait_for_completion_interruptible_timeout(
4236 &pAdapter->disconnect_comp_var,
4237 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4238
4239 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4240 pHddCtx->isAmpAllowed = VOS_FALSE;
4241 sme_RoamConnect(pHddCtx->hHal,
4242 pAdapter->sessionId, &(pWextState->roamProfile),
4243 &roamId);
4244 }
4245
4246 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4247 pAdapterNode = pNext;
4248 }
4249
4250 EXIT();
4251
4252 return VOS_STATUS_SUCCESS;
4253}
4254
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004255void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4256{
4257 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4258 VOS_STATUS status;
4259 hdd_adapter_t *pAdapter;
4260 hdd_station_ctx_t *pHddStaCtx;
4261 hdd_ap_ctx_t *pHddApCtx;
4262 hdd_hostapd_state_t * pHostapdState;
4263 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4264 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4265 const char *p2pMode = "DEV";
4266 const char *ccMode = "Standalone";
4267 int n;
4268
4269 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4270 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4271 {
4272 pAdapter = pAdapterNode->pAdapter;
4273 switch (pAdapter->device_mode) {
4274 case WLAN_HDD_INFRA_STATION:
4275 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4276 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4277 staChannel = pHddStaCtx->conn_info.operationChannel;
4278 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4279 }
4280 break;
4281 case WLAN_HDD_P2P_CLIENT:
4282 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4283 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4284 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4285 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4286 p2pMode = "CLI";
4287 }
4288 break;
4289 case WLAN_HDD_P2P_GO:
4290 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4291 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4292 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4293 p2pChannel = pHddApCtx->operatingChannel;
4294 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4295 }
4296 p2pMode = "GO";
4297 break;
4298 case WLAN_HDD_SOFTAP:
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 apChannel = pHddApCtx->operatingChannel;
4303 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4304 }
4305 break;
4306 default:
4307 break;
4308 }
4309 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4310 pAdapterNode = pNext;
4311 }
4312 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4313 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4314 }
4315 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4316 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4317 if (p2pChannel > 0) {
4318 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4319 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4320 }
4321 if (apChannel > 0) {
4322 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4323 apChannel, MAC_ADDR_ARRAY(apBssid));
4324 }
4325
4326 if (p2pChannel > 0 && apChannel > 0) {
4327 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4328 }
4329}
4330
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004331bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004332{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004333 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004334}
4335
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004336/* Once SSR is disabled then it cannot be set. */
4337void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004338{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004339 if (HDD_SSR_DISABLED == isSsrRequired)
4340 return;
4341
Jeff Johnson295189b2012-06-20 16:38:30 -07004342 isSsrRequired = value;
4343}
4344
4345VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4346 hdd_adapter_list_node_t** ppAdapterNode)
4347{
4348 VOS_STATUS status;
4349 spin_lock(&pHddCtx->hddAdapters.lock);
4350 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4351 (hdd_list_node_t**) ppAdapterNode );
4352 spin_unlock(&pHddCtx->hddAdapters.lock);
4353 return status;
4354}
4355
4356VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4357 hdd_adapter_list_node_t* pAdapterNode,
4358 hdd_adapter_list_node_t** pNextAdapterNode)
4359{
4360 VOS_STATUS status;
4361 spin_lock(&pHddCtx->hddAdapters.lock);
4362 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4363 (hdd_list_node_t*) pAdapterNode,
4364 (hdd_list_node_t**)pNextAdapterNode );
4365
4366 spin_unlock(&pHddCtx->hddAdapters.lock);
4367 return status;
4368}
4369
4370VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4371 hdd_adapter_list_node_t* pAdapterNode)
4372{
4373 VOS_STATUS status;
4374 spin_lock(&pHddCtx->hddAdapters.lock);
4375 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4376 &pAdapterNode->node );
4377 spin_unlock(&pHddCtx->hddAdapters.lock);
4378 return status;
4379}
4380
4381VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4382 hdd_adapter_list_node_t** ppAdapterNode)
4383{
4384 VOS_STATUS status;
4385 spin_lock(&pHddCtx->hddAdapters.lock);
4386 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4387 (hdd_list_node_t**) ppAdapterNode );
4388 spin_unlock(&pHddCtx->hddAdapters.lock);
4389 return status;
4390}
4391
4392VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4393 hdd_adapter_list_node_t* pAdapterNode)
4394{
4395 VOS_STATUS status;
4396 spin_lock(&pHddCtx->hddAdapters.lock);
4397 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4398 (hdd_list_node_t*) pAdapterNode );
4399 spin_unlock(&pHddCtx->hddAdapters.lock);
4400 return status;
4401}
4402
4403VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4404 hdd_adapter_list_node_t* pAdapterNode)
4405{
4406 VOS_STATUS status;
4407 spin_lock(&pHddCtx->hddAdapters.lock);
4408 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4409 (hdd_list_node_t*) pAdapterNode );
4410 spin_unlock(&pHddCtx->hddAdapters.lock);
4411 return status;
4412}
4413
4414hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4415 tSirMacAddr macAddr )
4416{
4417 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4418 hdd_adapter_t *pAdapter;
4419 VOS_STATUS status;
4420
4421 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4422
4423 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4424 {
4425 pAdapter = pAdapterNode->pAdapter;
4426
4427 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4428 macAddr, sizeof(tSirMacAddr) ) )
4429 {
4430 return pAdapter;
4431 }
4432 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4433 pAdapterNode = pNext;
4434 }
4435
4436 return NULL;
4437
4438}
4439
4440hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4441{
4442 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4443 hdd_adapter_t *pAdapter;
4444 VOS_STATUS status;
4445
4446 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4447
4448 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4449 {
4450 pAdapter = pAdapterNode->pAdapter;
4451
4452 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4453 IFNAMSIZ ) )
4454 {
4455 return pAdapter;
4456 }
4457 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4458 pAdapterNode = pNext;
4459 }
4460
4461 return NULL;
4462
4463}
4464
4465hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4466{
4467 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4468 hdd_adapter_t *pAdapter;
4469 VOS_STATUS status;
4470
4471 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4472
4473 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4474 {
4475 pAdapter = pAdapterNode->pAdapter;
4476
4477 if( pAdapter && (mode == pAdapter->device_mode) )
4478 {
4479 return pAdapter;
4480 }
4481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4482 pAdapterNode = pNext;
4483 }
4484
4485 return NULL;
4486
4487}
4488
4489//Remove this function later
4490hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4491{
4492 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4493 hdd_adapter_t *pAdapter;
4494 VOS_STATUS status;
4495
4496 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4497
4498 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4499 {
4500 pAdapter = pAdapterNode->pAdapter;
4501
4502 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4503 {
4504 return pAdapter;
4505 }
4506
4507 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4508 pAdapterNode = pNext;
4509 }
4510
4511 return NULL;
4512
4513}
4514
Jeff Johnson295189b2012-06-20 16:38:30 -07004515/**---------------------------------------------------------------------------
4516
4517 \brief hdd_set_monitor_tx_adapter() -
4518
4519 This API initializes the adapter to be used while transmitting on monitor
4520 adapter.
4521
4522 \param - pHddCtx - Pointer to the HDD context.
4523 pAdapter - Adapter that will used for TX. This can be NULL.
4524 \return - None.
4525 --------------------------------------------------------------------------*/
4526void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4527{
4528 hdd_adapter_t *pMonAdapter;
4529
4530 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4531
4532 if( NULL != pMonAdapter )
4533 {
4534 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4535 }
4536}
Jeff Johnson295189b2012-06-20 16:38:30 -07004537/**---------------------------------------------------------------------------
4538
4539 \brief hdd_select_queue() -
4540
4541 This API returns the operating channel of the requested device mode
4542
4543 \param - pHddCtx - Pointer to the HDD context.
4544 - mode - Device mode for which operating channel is required
4545 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4546 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4547 \return - channel number. "0" id the requested device is not found OR it is not connected.
4548 --------------------------------------------------------------------------*/
4549v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4550{
4551 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4552 VOS_STATUS status;
4553 hdd_adapter_t *pAdapter;
4554 v_U8_t operatingChannel = 0;
4555
4556 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4557
4558 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4559 {
4560 pAdapter = pAdapterNode->pAdapter;
4561
4562 if( mode == pAdapter->device_mode )
4563 {
4564 switch(pAdapter->device_mode)
4565 {
4566 case WLAN_HDD_INFRA_STATION:
4567 case WLAN_HDD_P2P_CLIENT:
4568 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4569 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4570 break;
4571 case WLAN_HDD_SOFTAP:
4572 case WLAN_HDD_P2P_GO:
4573 /*softap connection info */
4574 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4575 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4576 break;
4577 default:
4578 break;
4579 }
4580
4581 break; //Found the device of interest. break the loop
4582 }
4583
4584 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4585 pAdapterNode = pNext;
4586 }
4587 return operatingChannel;
4588}
4589
4590#ifdef WLAN_FEATURE_PACKET_FILTERING
4591/**---------------------------------------------------------------------------
4592
4593 \brief hdd_set_multicast_list() -
4594
4595 This used to set the multicast address list.
4596
4597 \param - dev - Pointer to the WLAN device.
4598 - skb - Pointer to OS packet (sk_buff).
4599 \return - success/fail
4600
4601 --------------------------------------------------------------------------*/
4602static void hdd_set_multicast_list(struct net_device *dev)
4603{
4604 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 int mc_count;
4606 int i = 0;
4607 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304608
4609 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004610 {
4611 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304612 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 return;
4614 }
4615
4616 if (dev->flags & IFF_ALLMULTI)
4617 {
4618 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004619 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304620 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 }
4622 else
4623 {
4624 mc_count = netdev_mc_count(dev);
4625 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004626 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004627 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4628 {
4629 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004630 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304631 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 return;
4633 }
4634
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304635 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004636
4637 netdev_for_each_mc_addr(ha, dev) {
4638 if (i == mc_count)
4639 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304640 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4641 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4642 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304644 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 i++;
4646 }
4647 }
4648 return;
4649}
4650#endif
4651
4652/**---------------------------------------------------------------------------
4653
4654 \brief hdd_select_queue() -
4655
4656 This function is registered with the Linux OS for network
4657 core to decide which queue to use first.
4658
4659 \param - dev - Pointer to the WLAN device.
4660 - skb - Pointer to OS packet (sk_buff).
4661 \return - ac, Queue Index/access category corresponding to UP in IP header
4662
4663 --------------------------------------------------------------------------*/
4664v_U16_t hdd_select_queue(struct net_device *dev,
4665 struct sk_buff *skb)
4666{
4667 return hdd_wmm_select_queue(dev, skb);
4668}
4669
4670
4671/**---------------------------------------------------------------------------
4672
4673 \brief hdd_wlan_initial_scan() -
4674
4675 This function triggers the initial scan
4676
4677 \param - pAdapter - Pointer to the HDD adapter.
4678
4679 --------------------------------------------------------------------------*/
4680void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4681{
4682 tCsrScanRequest scanReq;
4683 tCsrChannelInfo channelInfo;
4684 eHalStatus halStatus;
4685 unsigned long scanId;
4686 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4687
4688 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4689 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4690 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4691
4692 if(sme_Is11dSupported(pHddCtx->hHal))
4693 {
4694 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4695 if ( HAL_STATUS_SUCCESS( halStatus ) )
4696 {
4697 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4698 if( !scanReq.ChannelInfo.ChannelList )
4699 {
4700 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4701 vos_mem_free(channelInfo.ChannelList);
4702 return;
4703 }
4704 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4705 channelInfo.numOfChannels);
4706 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4707 vos_mem_free(channelInfo.ChannelList);
4708 }
4709
4710 scanReq.scanType = eSIR_PASSIVE_SCAN;
4711 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4712 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4713 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4714 }
4715 else
4716 {
4717 scanReq.scanType = eSIR_ACTIVE_SCAN;
4718 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4719 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4720 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4721 }
4722
4723 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4724 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4725 {
4726 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4727 __func__, halStatus );
4728 }
4729
4730 if(sme_Is11dSupported(pHddCtx->hHal))
4731 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4732}
4733
4734struct fullPowerContext
4735{
4736 struct completion completion;
4737 unsigned int magic;
4738};
4739#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4740
4741/**---------------------------------------------------------------------------
4742
4743 \brief hdd_full_power_callback() - HDD full power callback function
4744
4745 This is the function invoked by SME to inform the result of a full power
4746 request issued by HDD
4747
4748 \param - callbackcontext - Pointer to cookie
4749 \param - status - result of request
4750
4751 \return - None
4752
4753 --------------------------------------------------------------------------*/
4754static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4755{
4756 struct fullPowerContext *pContext = callbackContext;
4757
4758 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304759 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004760
4761 if (NULL == callbackContext)
4762 {
4763 hddLog(VOS_TRACE_LEVEL_ERROR,
4764 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004765 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004766 return;
4767 }
4768
4769 /* there is a race condition that exists between this callback function
4770 and the caller since the caller could time out either before or
4771 while this code is executing. we'll assume the timeout hasn't
4772 occurred, but we'll verify that right before we save our work */
4773
4774 if (POWER_CONTEXT_MAGIC != pContext->magic)
4775 {
4776 /* the caller presumably timed out so there is nothing we can do */
4777 hddLog(VOS_TRACE_LEVEL_WARN,
4778 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004779 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004780 return;
4781 }
4782
4783 /* the race is on. caller could have timed out immediately after
4784 we verified the magic, but if so, caller will wait a short time
4785 for us to notify the caller, so the context will stay valid */
4786 complete(&pContext->completion);
4787}
4788
4789/**---------------------------------------------------------------------------
4790
4791 \brief hdd_wlan_exit() - HDD WLAN exit function
4792
4793 This is the driver exit point (invoked during rmmod)
4794
4795 \param - pHddCtx - Pointer to the HDD Context
4796
4797 \return - None
4798
4799 --------------------------------------------------------------------------*/
4800void hdd_wlan_exit(hdd_context_t *pHddCtx)
4801{
4802 eHalStatus halStatus;
4803 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4804 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304805 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004806 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 struct fullPowerContext powerContext;
4808 long lrc;
4809
4810 ENTER();
4811
Jeff Johnson88ba7742013-02-27 14:36:02 -08004812 if (VOS_FTM_MODE != hdd_get_conparam())
4813 {
4814 // Unloading, restart logic is no more required.
4815 wlan_hdd_restart_deinit(pHddCtx);
4816 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004817
Jeff Johnson295189b2012-06-20 16:38:30 -07004818 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 {
4822 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4823 WLAN_HDD_INFRA_STATION);
4824 if (pAdapter == NULL)
4825 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4826
4827 if (pAdapter != NULL)
4828 {
4829 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4830 hdd_UnregisterWext(pAdapter->dev);
4831 }
4832 }
4833 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004834
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004836 {
4837 wlan_hdd_ftm_close(pHddCtx);
4838 goto free_hdd_ctx;
4839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 //Stop the Interface TX queue.
4841 //netif_tx_disable(pWlanDev);
4842 //netif_carrier_off(pWlanDev);
4843
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4845 {
4846 pAdapter = hdd_get_adapter(pHddCtx,
4847 WLAN_HDD_SOFTAP);
4848 }
4849 else
4850 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004851 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004852 {
4853 pAdapter = hdd_get_adapter(pHddCtx,
4854 WLAN_HDD_INFRA_STATION);
4855 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 /* DeRegister with platform driver as client for Suspend/Resume */
4858 vosStatus = hddDeregisterPmOps(pHddCtx);
4859 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4860 {
4861 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4862 VOS_ASSERT(0);
4863 }
4864
4865 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4866 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4867 {
4868 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4869 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004870
4871 // Cancel any outstanding scan requests. We are about to close all
4872 // of our adapters, but an adapter structure is what SME passes back
4873 // to our callback function. Hence if there are any outstanding scan
4874 // requests then there is a race condition between when the adapter
4875 // is closed and when the callback is invoked. We try to resolve that
4876 // race condition here by canceling any outstanding scans before we
4877 // close the adapters.
4878 // Note that the scans may be cancelled in an asynchronous manner, so
4879 // ideally there needs to be some kind of synchronization. Rather than
4880 // introduce a new synchronization here, we will utilize the fact that
4881 // we are about to Request Full Power, and since that is synchronized,
4882 // the expectation is that by the time Request Full Power has completed,
4883 // all scans will be cancelled.
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05304884 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004885
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004886 //Stop the traffic monitor timer
4887 if ( VOS_TIMER_STATE_RUNNING ==
4888 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4889 {
4890 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4891 }
4892
4893 // Destroy the traffic monitor timer
4894 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4895 &pHddCtx->tx_rx_trafficTmr)))
4896 {
4897 hddLog(VOS_TRACE_LEVEL_ERROR,
4898 "%s: Cannot deallocate Traffic monitor timer", __func__);
4899 }
4900
Jeff Johnson295189b2012-06-20 16:38:30 -07004901 //Disable IMPS/BMPS as we do not want the device to enter any power
4902 //save mode during shutdown
4903 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4904 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4905 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4906
4907 //Ensure that device is in full power as we will touch H/W during vos_Stop
4908 init_completion(&powerContext.completion);
4909 powerContext.magic = POWER_CONTEXT_MAGIC;
4910
4911 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4912 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4913
4914 if (eHAL_STATUS_SUCCESS != halStatus)
4915 {
4916 if (eHAL_STATUS_PMC_PENDING == halStatus)
4917 {
4918 /* request was sent -- wait for the response */
4919 lrc = wait_for_completion_interruptible_timeout(
4920 &powerContext.completion,
4921 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4922 /* either we have a response or we timed out
4923 either way, first invalidate our magic */
4924 powerContext.magic = 0;
4925 if (lrc <= 0)
4926 {
4927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004928 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004929 /* there is a race condition such that the callback
4930 function could be executing at the same time we are. of
4931 primary concern is if the callback function had already
4932 verified the "magic" but hasn't yet set the completion
4933 variable. Since the completion variable is on our
4934 stack, we'll delay just a bit to make sure the data is
4935 still valid if that is the case */
4936 msleep(50);
4937 }
4938 }
4939 else
4940 {
4941 hddLog(VOS_TRACE_LEVEL_ERROR,
4942 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004943 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 VOS_ASSERT(0);
4945 /* continue -- need to clean up as much as possible */
4946 }
4947 }
4948
Yue Ma0d4891e2013-08-06 17:01:45 -07004949 hdd_debugfs_exit(pHddCtx);
4950
Jeff Johnson295189b2012-06-20 16:38:30 -07004951 // Unregister the Net Device Notifier
4952 unregister_netdevice_notifier(&hdd_netdev_notifier);
4953
Jeff Johnson295189b2012-06-20 16:38:30 -07004954 hdd_stop_all_adapters( pHddCtx );
4955
Jeff Johnson295189b2012-06-20 16:38:30 -07004956#ifdef WLAN_BTAMP_FEATURE
4957 vosStatus = WLANBAP_Stop(pVosContext);
4958 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4959 {
4960 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4961 "%s: Failed to stop BAP",__func__);
4962 }
4963#endif //WLAN_BTAMP_FEATURE
4964
4965 //Stop all the modules
4966 vosStatus = vos_stop( pVosContext );
4967 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4968 {
4969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4970 "%s: Failed to stop VOSS",__func__);
4971 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4972 }
4973
Jeff Johnson295189b2012-06-20 16:38:30 -07004974 //Assert Deep sleep signal now to put Libra HW in lowest power state
4975 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4976 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4977
4978 //Vote off any PMIC voltage supplies
4979 vos_chipPowerDown(NULL, NULL, NULL);
4980
4981 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4982
Leo Chang59cdc7e2013-07-10 10:08:21 -07004983
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004986
4987 //Close the scheduler before calling vos_close to make sure no thread is
4988 // scheduled after the each module close is called i.e after all the data
4989 // structures are freed.
4990 vosStatus = vos_sched_close( pVosContext );
4991 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4992 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4993 "%s: Failed to close VOSS Scheduler",__func__);
4994 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4995 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004996#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004997#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4998 /* Destroy the wake lock */
4999 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5000#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005001 /* Destroy the wake lock */
5002 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005003#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005004
5005 //Close VOSS
5006 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5007 vos_close(pVosContext);
5008
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 //Close Watchdog
5010 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5011 vos_watchdog_close(pVosContext);
5012
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305013 //Clean up HDD Nlink Service
5014 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005015#ifdef WLAN_KD_READY_NOTIFIER
5016 nl_srv_exit(pHddCtx->ptt_pid);
5017#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305018 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005019#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305020
Jeff Johnson295189b2012-06-20 16:38:30 -07005021 /* Cancel the vote for XO Core ON.
5022 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5023 * exited at this point
5024 */
5025 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5026 " when WLAN is turned OFF\n");
5027 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5028 {
5029 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5030 " Not returning failure."
5031 " Power consumed will be high\n");
5032 }
5033
5034 hdd_close_all_adapters( pHddCtx );
5035
5036
5037 //Free up dynamically allocated members inside HDD Adapter
5038 kfree(pHddCtx->cfg_ini);
5039 pHddCtx->cfg_ini= NULL;
5040
5041 /* free the power on lock from platform driver */
5042 if (free_riva_power_on_lock("wlan"))
5043 {
5044 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5045 __func__);
5046 }
5047
Jeff Johnson88ba7742013-02-27 14:36:02 -08005048free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005049 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005050 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 if (hdd_is_ssr_required())
5052 {
5053 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005054 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 msleep(5000);
5056 }
5057 hdd_set_ssr_required (VOS_FALSE);
5058}
5059
5060
5061/**---------------------------------------------------------------------------
5062
5063 \brief hdd_update_config_from_nv() - Function to update the contents of
5064 the running configuration with parameters taken from NV storage
5065
5066 \param - pHddCtx - Pointer to the HDD global context
5067
5068 \return - VOS_STATUS_SUCCESS if successful
5069
5070 --------------------------------------------------------------------------*/
5071static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5072{
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 v_BOOL_t itemIsValid = VOS_FALSE;
5074 VOS_STATUS status;
5075 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5076 v_U8_t macLoop;
5077
5078 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5079 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5080 if(status != VOS_STATUS_SUCCESS)
5081 {
5082 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5083 return VOS_STATUS_E_FAILURE;
5084 }
5085
5086 if (itemIsValid == VOS_TRUE)
5087 {
5088 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5089 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5090 VOS_MAX_CONCURRENCY_PERSONA);
5091 if(status != VOS_STATUS_SUCCESS)
5092 {
5093 /* Get MAC from NV fail, not update CFG info
5094 * INI MAC value will be used for MAC setting */
5095 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5096 return VOS_STATUS_E_FAILURE;
5097 }
5098
5099 /* If first MAC is not valid, treat all others are not valid
5100 * Then all MACs will be got from ini file */
5101 if(vos_is_macaddr_zero(&macFromNV[0]))
5102 {
5103 /* MAC address in NV file is not configured yet */
5104 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5105 return VOS_STATUS_E_INVAL;
5106 }
5107
5108 /* Get MAC address from NV, update CFG info */
5109 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5110 {
5111 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5112 {
5113 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5114 /* This MAC is not valid, skip it
5115 * This MAC will be got from ini file */
5116 }
5117 else
5118 {
5119 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5120 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5121 VOS_MAC_ADDR_SIZE);
5122 }
5123 }
5124 }
5125 else
5126 {
5127 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5128 return VOS_STATUS_E_FAILURE;
5129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005130
Jeff Johnson295189b2012-06-20 16:38:30 -07005131
5132 return VOS_STATUS_SUCCESS;
5133}
5134
5135/**---------------------------------------------------------------------------
5136
5137 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5138
5139 \param - pAdapter - Pointer to the HDD
5140
5141 \return - None
5142
5143 --------------------------------------------------------------------------*/
5144VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5145{
5146 eHalStatus halStatus;
5147 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305148 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005149
Jeff Johnson295189b2012-06-20 16:38:30 -07005150
5151 // Send ready indication to the HDD. This will kick off the MAC
5152 // into a 'running' state and should kick off an initial scan.
5153 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5154 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5155 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305156 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 "code %08d [x%08x]",__func__, halStatus, halStatus );
5158 return VOS_STATUS_E_FAILURE;
5159 }
5160
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305161 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005162 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5163 // And RIVA will crash
5164 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5165 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305166 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5167 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5168
5169
Jeff Johnson295189b2012-06-20 16:38:30 -07005170 return VOS_STATUS_SUCCESS;
5171}
5172
Jeff Johnson295189b2012-06-20 16:38:30 -07005173/* wake lock APIs for HDD */
5174void hdd_prevent_suspend(void)
5175{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005176#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005178#else
5179 wcnss_prevent_suspend();
5180#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005181}
5182
5183void hdd_allow_suspend(void)
5184{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005185#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005187#else
5188 wcnss_allow_suspend();
5189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005190}
5191
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005192void hdd_allow_suspend_timeout(v_U32_t timeout)
5193{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005194#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005195 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005196#else
5197 /* Do nothing as there is no API in wcnss for timeout*/
5198#endif
5199}
5200
Jeff Johnson295189b2012-06-20 16:38:30 -07005201/**---------------------------------------------------------------------------
5202
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005203 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5204 information between Host and Riva
5205
5206 This function gets reported version of FW
5207 It also finds the version of Riva headers used to compile the host
5208 It compares the above two and prints a warning if they are different
5209 It gets the SW and HW version string
5210 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5211 indicating the features they support through a bitmap
5212
5213 \param - pHddCtx - Pointer to HDD context
5214
5215 \return - void
5216
5217 --------------------------------------------------------------------------*/
5218
5219void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5220{
5221
5222 tSirVersionType versionCompiled;
5223 tSirVersionType versionReported;
5224 tSirVersionString versionString;
5225 tANI_U8 fwFeatCapsMsgSupported = 0;
5226 VOS_STATUS vstatus;
5227
5228 /* retrieve and display WCNSS version information */
5229 do {
5230
5231 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5232 &versionCompiled);
5233 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5234 {
5235 hddLog(VOS_TRACE_LEVEL_FATAL,
5236 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005237 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005238 break;
5239 }
5240
5241 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5242 &versionReported);
5243 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5244 {
5245 hddLog(VOS_TRACE_LEVEL_FATAL,
5246 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005247 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005248 break;
5249 }
5250
5251 if ((versionCompiled.major != versionReported.major) ||
5252 (versionCompiled.minor != versionReported.minor) ||
5253 (versionCompiled.version != versionReported.version) ||
5254 (versionCompiled.revision != versionReported.revision))
5255 {
5256 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5257 "Host expected %u.%u.%u.%u\n",
5258 WLAN_MODULE_NAME,
5259 (int)versionReported.major,
5260 (int)versionReported.minor,
5261 (int)versionReported.version,
5262 (int)versionReported.revision,
5263 (int)versionCompiled.major,
5264 (int)versionCompiled.minor,
5265 (int)versionCompiled.version,
5266 (int)versionCompiled.revision);
5267 }
5268 else
5269 {
5270 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5271 WLAN_MODULE_NAME,
5272 (int)versionReported.major,
5273 (int)versionReported.minor,
5274 (int)versionReported.version,
5275 (int)versionReported.revision);
5276 }
5277
5278 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5279 versionString,
5280 sizeof(versionString));
5281 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5282 {
5283 hddLog(VOS_TRACE_LEVEL_FATAL,
5284 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005285 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005286 break;
5287 }
5288
5289 pr_info("%s: WCNSS software version %s\n",
5290 WLAN_MODULE_NAME, versionString);
5291
5292 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5293 versionString,
5294 sizeof(versionString));
5295 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5296 {
5297 hddLog(VOS_TRACE_LEVEL_FATAL,
5298 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005299 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005300 break;
5301 }
5302
5303 pr_info("%s: WCNSS hardware version %s\n",
5304 WLAN_MODULE_NAME, versionString);
5305
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005306 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5307 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005308 send the message only if it the riva is 1.1
5309 minor numbers for different riva branches:
5310 0 -> (1.0)Mainline Build
5311 1 -> (1.1)Mainline Build
5312 2->(1.04) Stability Build
5313 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005314 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005315 ((versionReported.minor>=1) && (versionReported.version>=1)))
5316 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5317 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005318
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005319 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005320 {
5321#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5322 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5323 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5324#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005325 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5326 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5327 {
5328 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5329 }
5330
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005331 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005332 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005333
5334 } while (0);
5335
5336}
5337
5338/**---------------------------------------------------------------------------
5339
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305340 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5341
5342 \param - pHddCtx - Pointer to the hdd context
5343
5344 \return - true if hardware supports 5GHz
5345
5346 --------------------------------------------------------------------------*/
5347static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5348{
5349 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5350 * then hardware support 5Ghz.
5351 */
5352 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5353 {
5354 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5355 return true;
5356 }
5357 else
5358 {
5359 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5360 __func__);
5361 return false;
5362 }
5363}
5364
5365
5366/**---------------------------------------------------------------------------
5367
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 \brief hdd_wlan_startup() - HDD init function
5369
5370 This is the driver startup code executed once a WLAN device has been detected
5371
5372 \param - dev - Pointer to the underlying device
5373
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005374 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005375
5376 --------------------------------------------------------------------------*/
5377
5378int hdd_wlan_startup(struct device *dev )
5379{
5380 VOS_STATUS status;
5381 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005382 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 hdd_context_t *pHddCtx = NULL;
5384 v_CONTEXT_t pVosContext= NULL;
5385#ifdef WLAN_BTAMP_FEATURE
5386 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5387 WLANBAP_ConfigType btAmpConfig;
5388 hdd_config_t *pConfig;
5389#endif
5390 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005392
5393 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005394 /*
5395 * cfg80211: wiphy allocation
5396 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305397 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005398
5399 if(wiphy == NULL)
5400 {
5401 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005402 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 }
5404
5405 pHddCtx = wiphy_priv(wiphy);
5406
Jeff Johnson295189b2012-06-20 16:38:30 -07005407 //Initialize the adapter context to zeros.
5408 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5409
Jeff Johnson295189b2012-06-20 16:38:30 -07005410 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 hdd_prevent_suspend();
5412 pHddCtx->isLoadUnloadInProgress = TRUE;
5413
5414 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5415
5416 /*Get vos context here bcoz vos_open requires it*/
5417 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5418
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005419 if(pVosContext == NULL)
5420 {
5421 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5422 goto err_free_hdd_context;
5423 }
5424
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 //Save the Global VOSS context in adapter context for future.
5426 pHddCtx->pvosContext = pVosContext;
5427
5428 //Save the adapter context in global context for future.
5429 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5430
Jeff Johnson295189b2012-06-20 16:38:30 -07005431 pHddCtx->parent_dev = dev;
5432
5433 init_completion(&pHddCtx->full_pwr_comp_var);
5434 init_completion(&pHddCtx->standby_comp_var);
5435 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005436 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005437 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhalfddc28c2013-09-05 13:03:40 -07005438 init_completion(&pHddCtx->linux_reg_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005439
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305440 spin_lock_init(&pHddCtx->schedScan_lock);
5441
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5443
5444 // Load all config first as TL config is needed during vos_open
5445 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5446 if(pHddCtx->cfg_ini == NULL)
5447 {
5448 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5449 goto err_free_hdd_context;
5450 }
5451
5452 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5453
5454 // Read and parse the qcom_cfg.ini file
5455 status = hdd_parse_config_ini( pHddCtx );
5456 if ( VOS_STATUS_SUCCESS != status )
5457 {
5458 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5459 __func__, WLAN_INI_FILE);
5460 goto err_config;
5461 }
5462
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305463 /* INI has been read, initialise the configuredMcastBcastFilter with
5464 * INI value as this will serve as the default value
5465 */
5466 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5467 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5468 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305469
5470 if (false == hdd_is_5g_supported(pHddCtx))
5471 {
5472 //5Ghz is not supported.
5473 if (1 != pHddCtx->cfg_ini->nBandCapability)
5474 {
5475 hddLog(VOS_TRACE_LEVEL_INFO,
5476 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5477 pHddCtx->cfg_ini->nBandCapability = 1;
5478 }
5479 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305480
5481 /* If SNR Monitoring is enabled, FW has to parse all beacons
5482 * for calcaluting and storing the average SNR, so set Nth beacon
5483 * filter to 1 to enable FW to parse all the beaocons
5484 */
5485 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5486 {
5487 /* The log level is deliberately set to WARN as overriding
5488 * nthBeaconFilter to 1 will increase power cosumption and this
5489 * might just prove helpful to detect the power issue.
5490 */
5491 hddLog(VOS_TRACE_LEVEL_WARN,
5492 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5493 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5494 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305496 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305498 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 {
5500 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305501 "%s: wlan_hdd_cfg80211_init return failure", __func__);
5502 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07005503 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005504
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005505 // Update VOS trace levels based upon the cfg.ini
5506 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5507 pHddCtx->cfg_ini->vosTraceEnableBAP);
5508 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5509 pHddCtx->cfg_ini->vosTraceEnableTL);
5510 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5511 pHddCtx->cfg_ini->vosTraceEnableWDI);
5512 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5513 pHddCtx->cfg_ini->vosTraceEnableHDD);
5514 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5515 pHddCtx->cfg_ini->vosTraceEnableSME);
5516 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5517 pHddCtx->cfg_ini->vosTraceEnablePE);
5518 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5519 pHddCtx->cfg_ini->vosTraceEnableWDA);
5520 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5521 pHddCtx->cfg_ini->vosTraceEnableSYS);
5522 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5523 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005524 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5525 pHddCtx->cfg_ini->vosTraceEnableSAP);
5526 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5527 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005528
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 // Update WDI trace levels based upon the cfg.ini
5530 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5531 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5532 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5533 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5534 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5535 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5536 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5537 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005538
Jeff Johnson88ba7742013-02-27 14:36:02 -08005539 if (VOS_FTM_MODE == hdd_get_conparam())
5540 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005541 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5542 {
5543 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5544 goto err_free_hdd_context;
5545 }
5546 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5547 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005548 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005549
Jeff Johnson88ba7742013-02-27 14:36:02 -08005550 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5552 {
5553 status = vos_watchdog_open(pVosContext,
5554 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5555
5556 if(!VOS_IS_STATUS_SUCCESS( status ))
5557 {
5558 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305559 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 }
5561 }
5562
5563 pHddCtx->isLogpInProgress = FALSE;
5564 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5565
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5567 if(!VOS_IS_STATUS_SUCCESS(status))
5568 {
5569 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 }
5572
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 status = vos_open( &pVosContext, 0);
5574 if ( !VOS_IS_STATUS_SUCCESS( status ))
5575 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005576 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5577 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 }
5579
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5581
5582 if ( NULL == pHddCtx->hHal )
5583 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005584 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 goto err_vosclose;
5586 }
5587
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005588 status = vos_preStart( pHddCtx->pvosContext );
5589 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5590 {
5591 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5592 goto err_vosclose;
5593 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005594
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005595 /* Note that the vos_preStart() sequence triggers the cfg download.
5596 The cfg download must occur before we update the SME config
5597 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 status = hdd_set_sme_config( pHddCtx );
5599
5600 if ( VOS_STATUS_SUCCESS != status )
5601 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005602 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5603 goto err_vosclose;
5604 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005605
5606 //Initialize the WMM module
5607 status = hdd_wmm_init(pHddCtx);
5608 if (!VOS_IS_STATUS_SUCCESS(status))
5609 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005610 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005611 goto err_vosclose;
5612 }
5613
Jeff Johnson295189b2012-06-20 16:38:30 -07005614 /* In the integrated architecture we update the configuration from
5615 the INI file and from NV before vOSS has been started so that
5616 the final contents are available to send down to the cCPU */
5617
5618 // Apply the cfg.ini to cfg.dat
5619 if (FALSE == hdd_update_config_dat(pHddCtx))
5620 {
5621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5622 goto err_vosclose;
5623 }
5624
5625 // Apply the NV to cfg.dat
5626 /* Prima Update MAC address only at here */
5627 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5628 {
5629#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5630 /* There was not a valid set of MAC Addresses in NV. See if the
5631 default addresses were modified by the cfg.ini settings. If so,
5632 we'll use them, but if not, we'll autogenerate a set of MAC
5633 addresses based upon the device serial number */
5634
5635 static const v_MACADDR_t default_address =
5636 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5637 unsigned int serialno;
5638 int i;
5639
5640 serialno = wcnss_get_serial_number();
5641 if ((0 != serialno) &&
5642 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5643 sizeof(default_address))))
5644 {
5645 /* cfg.ini has the default address, invoke autogen logic */
5646
5647 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5648 bytes of the serial number that can be used to generate
5649 the other 3 bytes of the MAC address. Mask off all but
5650 the lower 3 bytes (this will also make sure we don't
5651 overflow in the next step) */
5652 serialno &= 0x00FFFFFF;
5653
5654 /* we need a unique address for each session */
5655 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5656
5657 /* autogen all addresses */
5658 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5659 {
5660 /* start with the entire default address */
5661 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5662 /* then replace the lower 3 bytes */
5663 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5664 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5665 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5666
5667 serialno++;
5668 }
5669
5670 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5671 MAC_ADDRESS_STR,
5672 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5673 }
5674 else
5675#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5676 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005677 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005678 "%s: Invalid MAC address in NV, using MAC from ini file "
5679 MAC_ADDRESS_STR, __func__,
5680 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5681 }
5682 }
5683 {
5684 eHalStatus halStatus;
5685 // Set the MAC Address
5686 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5687 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5688 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5689 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5690
5691 if (!HAL_STATUS_SUCCESS( halStatus ))
5692 {
5693 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5694 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005695 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005696 }
5697 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005698
5699 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5700 Note: Firmware image will be read and downloaded inside vos_start API */
5701 status = vos_start( pHddCtx->pvosContext );
5702 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5703 {
5704 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5705 goto err_vosclose;
5706 }
5707
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005708 /* Exchange capability info between Host and FW and also get versioning info from FW */
5709 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005710
5711 status = hdd_post_voss_start_config( pHddCtx );
5712 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5713 {
5714 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5715 __func__);
5716 goto err_vosstop;
5717 }
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305718 wlan_hdd_cfg80211_update_reg_info( wiphy );
5719
5720 /* registration of wiphy dev with cfg80211 */
5721 if (0 > wlan_hdd_cfg80211_register(wiphy))
5722 {
5723 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5724 goto err_vosstop;
5725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005726
Jeff Johnson295189b2012-06-20 16:38:30 -07005727 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5728 {
5729 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5730 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5731 }
5732 else
5733 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005734 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5735 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5736 if (pAdapter != NULL)
5737 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305738 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305740 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5741 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5742 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005743
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305744 /* Generate the P2P Device Address. This consists of the device's
5745 * primary MAC address with the locally administered bit set.
5746 */
5747 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005748 }
5749 else
5750 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305751 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5752 if (p2p_dev_addr != NULL)
5753 {
5754 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5755 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5756 }
5757 else
5758 {
5759 hddLog(VOS_TRACE_LEVEL_FATAL,
5760 "%s: Failed to allocate mac_address for p2p_device",
5761 __func__);
5762 goto err_close_adapter;
5763 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005765
5766 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5767 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5768 if ( NULL == pP2pAdapter )
5769 {
5770 hddLog(VOS_TRACE_LEVEL_FATAL,
5771 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005772 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005773 goto err_close_adapter;
5774 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005775 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005777
5778 if( pAdapter == NULL )
5779 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005780 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5781 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005782 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005783
Jeff Johnson295189b2012-06-20 16:38:30 -07005784#ifdef WLAN_BTAMP_FEATURE
5785 vStatus = WLANBAP_Open(pVosContext);
5786 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5787 {
5788 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5789 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005790 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 }
5792
5793 vStatus = BSL_Init(pVosContext);
5794 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5795 {
5796 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5797 "%s: Failed to Init BSL",__func__);
5798 goto err_bap_close;
5799 }
5800 vStatus = WLANBAP_Start(pVosContext);
5801 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5802 {
5803 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5804 "%s: Failed to start TL",__func__);
5805 goto err_bap_close;
5806 }
5807
5808 pConfig = pHddCtx->cfg_ini;
5809 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5810 status = WLANBAP_SetConfig(&btAmpConfig);
5811
5812#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005813
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005814#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5815 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5816 {
5817 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5818 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5819 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5820 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5821 }
5822#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005823#ifdef FEATURE_WLAN_SCAN_PNO
5824 /*SME must send channel update configuration to RIVA*/
5825 sme_UpdateChannelConfig(pHddCtx->hHal);
5826#endif
5827
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 /* Register with platform driver as client for Suspend/Resume */
5829 status = hddRegisterPmOps(pHddCtx);
5830 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5831 {
5832 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5833#ifdef WLAN_BTAMP_FEATURE
5834 goto err_bap_stop;
5835#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005836 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005837#endif //WLAN_BTAMP_FEATURE
5838 }
5839
Yue Ma0d4891e2013-08-06 17:01:45 -07005840 /* Open debugfs interface */
5841 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5842 {
5843 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5844 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07005845 }
5846
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 /* Register TM level change handler function to the platform */
5848 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5849 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5850 {
5851 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5852 goto err_unregister_pmops;
5853 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005854
5855 /* register for riva power on lock to platform driver */
5856 if (req_riva_power_on_lock("wlan"))
5857 {
5858 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5859 __func__);
5860 goto err_unregister_pmops;
5861 }
5862
Jeff Johnson295189b2012-06-20 16:38:30 -07005863 // register net device notifier for device change notification
5864 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5865
5866 if(ret < 0)
5867 {
5868 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5869 goto err_free_power_on_lock;
5870 }
5871
5872 //Initialize the nlink service
5873 if(nl_srv_init() != 0)
5874 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305875 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 goto err_reg_netdev;
5877 }
5878
5879 //Initialize the BTC service
5880 if(btc_activate_service(pHddCtx) != 0)
5881 {
5882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5883 goto err_nl_srv;
5884 }
5885
5886#ifdef PTT_SOCK_SVC_ENABLE
5887 //Initialize the PTT service
5888 if(ptt_sock_activate_svc(pHddCtx) != 0)
5889 {
5890 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5891 goto err_nl_srv;
5892 }
5893#endif
5894
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005896 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005898 /* Action frame registered in one adapter which will
5899 * applicable to all interfaces
5900 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005901 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005903
5904 mutex_init(&pHddCtx->sap_lock);
5905
5906 pHddCtx->isLoadUnloadInProgress = FALSE;
5907
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005908#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005909#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5910 /* Initialize the wake lcok */
5911 wake_lock_init(&pHddCtx->rx_wake_lock,
5912 WAKE_LOCK_SUSPEND,
5913 "qcom_rx_wakelock");
5914#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005915 /* Initialize the wake lcok */
5916 wake_lock_init(&pHddCtx->sap_wake_lock,
5917 WAKE_LOCK_SUSPEND,
5918 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005919#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005920
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005921 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5922 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005923
5924 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5925 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305926
Jeff Johnsone7245742012-09-05 17:12:55 -07005927 // Initialize the restart logic
5928 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305929
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005930 //Register the traffic monitor timer now
5931 if ( pHddCtx->cfg_ini->dynSplitscan)
5932 {
5933 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
5934 VOS_TIMER_TYPE_SW,
5935 hdd_tx_rx_pkt_cnt_stat_timer_handler,
5936 (void *)pHddCtx);
5937 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 goto success;
5939
5940err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005941#ifdef WLAN_KD_READY_NOTIFIER
5942 nl_srv_exit(pHddCtx->ptt_pid);
5943#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005945#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005946err_reg_netdev:
5947 unregister_netdevice_notifier(&hdd_netdev_notifier);
5948
5949err_free_power_on_lock:
5950 free_riva_power_on_lock("wlan");
5951
5952err_unregister_pmops:
5953 hddDevTmUnregisterNotifyCallback(pHddCtx);
5954 hddDeregisterPmOps(pHddCtx);
5955
Yue Ma0d4891e2013-08-06 17:01:45 -07005956 hdd_debugfs_exit(pHddCtx);
5957
Jeff Johnson295189b2012-06-20 16:38:30 -07005958#ifdef WLAN_BTAMP_FEATURE
5959err_bap_stop:
5960 WLANBAP_Stop(pVosContext);
5961#endif
5962
5963#ifdef WLAN_BTAMP_FEATURE
5964err_bap_close:
5965 WLANBAP_Close(pVosContext);
5966#endif
5967
Jeff Johnson295189b2012-06-20 16:38:30 -07005968err_close_adapter:
5969 hdd_close_all_adapters( pHddCtx );
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05305970 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005971
5972err_vosstop:
5973 vos_stop(pVosContext);
5974
5975err_vosclose:
5976 status = vos_sched_close( pVosContext );
5977 if (!VOS_IS_STATUS_SUCCESS(status)) {
5978 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5979 "%s: Failed to close VOSS Scheduler", __func__);
5980 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5981 }
5982 vos_close(pVosContext );
5983
Jeff Johnson295189b2012-06-20 16:38:30 -07005984err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005985 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005986
5987err_wdclose:
5988 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5989 vos_watchdog_close(pVosContext);
5990
Jeff Johnson295189b2012-06-20 16:38:30 -07005991err_config:
5992 kfree(pHddCtx->cfg_ini);
5993 pHddCtx->cfg_ini= NULL;
5994
5995err_free_hdd_context:
5996 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 wiphy_free(wiphy) ;
5998 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005999 VOS_BUG(1);
6000
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006001 if (hdd_is_ssr_required())
6002 {
6003 /* WDI timeout had happened during load, so SSR is needed here */
6004 subsystem_restart("wcnss");
6005 msleep(5000);
6006 }
6007 hdd_set_ssr_required (VOS_FALSE);
6008
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006009 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006010
6011success:
6012 EXIT();
6013 return 0;
6014}
6015
6016/**---------------------------------------------------------------------------
6017
Jeff Johnson32d95a32012-09-10 13:15:23 -07006018 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006019
Jeff Johnson32d95a32012-09-10 13:15:23 -07006020 This is the driver entry point - called in different timeline depending
6021 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006022
6023 \param - None
6024
6025 \return - 0 for success, non zero for failure
6026
6027 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006028static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006029{
6030 VOS_STATUS status;
6031 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 struct device *dev = NULL;
6033 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006034#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6035 int max_retries = 0;
6036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006037
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306038#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6039 vos_wconn_trace_init();
6040#endif
6041
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 ENTER();
6043
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006044#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006046#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006047
6048 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6049 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6050
6051 //Power Up Libra WLAN card first if not already powered up
6052 status = vos_chipPowerUp(NULL,NULL,NULL);
6053 if (!VOS_IS_STATUS_SUCCESS(status))
6054 {
6055 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6056 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306057#ifdef WLAN_OPEN_SOURCE
6058 wake_lock_destroy(&wlan_wake_lock);
6059#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006060 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006061 }
6062
Jeff Johnson295189b2012-06-20 16:38:30 -07006063#ifdef ANI_BUS_TYPE_PCI
6064
6065 dev = wcnss_wlan_get_device();
6066
6067#endif // ANI_BUS_TYPE_PCI
6068
6069#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006070
6071#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6072 /* wait until WCNSS driver downloads NV */
6073 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6074 msleep(1000);
6075 }
6076 if (max_retries >= 5) {
6077 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306078#ifdef WLAN_OPEN_SOURCE
6079 wake_lock_destroy(&wlan_wake_lock);
6080#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006081 return -ENODEV;
6082 }
6083#endif
6084
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 dev = wcnss_wlan_get_device();
6086#endif // ANI_BUS_TYPE_PLATFORM
6087
6088
6089 do {
6090 if (NULL == dev) {
6091 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6092 ret_status = -1;
6093 break;
6094 }
6095
6096#ifdef MEMORY_DEBUG
6097 vos_mem_init();
6098#endif
6099
6100#ifdef TIMER_MANAGER
6101 vos_timer_manager_init();
6102#endif
6103
6104 /* Preopen VOSS so that it is ready to start at least SAL */
6105 status = vos_preOpen(&pVosContext);
6106
6107 if (!VOS_IS_STATUS_SUCCESS(status))
6108 {
6109 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6110 ret_status = -1;
6111 break;
6112 }
6113
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006114#ifndef MODULE
6115 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6116 */
6117 hdd_set_conparam((v_UINT_t)con_mode);
6118#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006119
6120 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006121 if (hdd_wlan_startup(dev))
6122 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006124 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 vos_preClose( &pVosContext );
6126 ret_status = -1;
6127 break;
6128 }
6129
6130 /* Cancel the vote for XO Core ON
6131 * This is done here for safety purposes in case we re-initialize without turning
6132 * it OFF in any error scenario.
6133 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006134 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006136 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6138 {
6139 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6140 " Power consumed will be high\n");
6141 }
6142 } while (0);
6143
6144 if (0 != ret_status)
6145 {
6146 //Assert Deep sleep signal now to put Libra HW in lowest power state
6147 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6148 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6149
6150 //Vote off any PMIC voltage supplies
6151 vos_chipPowerDown(NULL, NULL, NULL);
6152#ifdef TIMER_MANAGER
6153 vos_timer_exit();
6154#endif
6155#ifdef MEMORY_DEBUG
6156 vos_mem_exit();
6157#endif
6158
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6163 }
6164 else
6165 {
6166 //Send WLAN UP indication to Nlink Service
6167 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6168
6169 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 }
6171
6172 EXIT();
6173
6174 return ret_status;
6175}
6176
Jeff Johnson32d95a32012-09-10 13:15:23 -07006177/**---------------------------------------------------------------------------
6178
6179 \brief hdd_module_init() - Init Function
6180
6181 This is the driver entry point (invoked when module is loaded using insmod)
6182
6183 \param - None
6184
6185 \return - 0 for success, non zero for failure
6186
6187 --------------------------------------------------------------------------*/
6188#ifdef MODULE
6189static int __init hdd_module_init ( void)
6190{
6191 return hdd_driver_init();
6192}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006193#else /* #ifdef MODULE */
6194static int __init hdd_module_init ( void)
6195{
6196 /* Driver initialization is delayed to fwpath_changed_handler */
6197 return 0;
6198}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006199#endif /* #ifdef MODULE */
6200
Jeff Johnson295189b2012-06-20 16:38:30 -07006201
6202/**---------------------------------------------------------------------------
6203
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006204 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006205
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006206 This is the driver exit point (invoked when module is unloaded using rmmod
6207 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006208
6209 \param - None
6210
6211 \return - None
6212
6213 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006214static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006215{
6216 hdd_context_t *pHddCtx = NULL;
6217 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006218 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006219
6220 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6221
6222 //Get the global vos context
6223 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6224
6225 if(!pVosContext)
6226 {
6227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6228 goto done;
6229 }
6230
6231 //Get the HDD context.
6232 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6233
6234 if(!pHddCtx)
6235 {
6236 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6237 }
6238 else
6239 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006240 while(isWDresetInProgress()) {
6241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6242 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006243 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006244
6245 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6247 "%s:SSR never completed, fatal error", __func__);
6248 VOS_BUG(0);
6249 }
6250 }
6251
Jeff Johnson295189b2012-06-20 16:38:30 -07006252
6253 pHddCtx->isLoadUnloadInProgress = TRUE;
6254 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6255
6256 //Do all the cleanup before deregistering the driver
6257 hdd_wlan_exit(pHddCtx);
6258 }
6259
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 vos_preClose( &pVosContext );
6261
6262#ifdef TIMER_MANAGER
6263 vos_timer_exit();
6264#endif
6265#ifdef MEMORY_DEBUG
6266 vos_mem_exit();
6267#endif
6268
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306269#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6270 vos_wconn_trace_exit();
6271#endif
6272
Jeff Johnson295189b2012-06-20 16:38:30 -07006273done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006274#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006276#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006277 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6278}
6279
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006280/**---------------------------------------------------------------------------
6281
6282 \brief hdd_module_exit() - Exit function
6283
6284 This is the driver exit point (invoked when module is unloaded using rmmod)
6285
6286 \param - None
6287
6288 \return - None
6289
6290 --------------------------------------------------------------------------*/
6291static void __exit hdd_module_exit(void)
6292{
6293 hdd_driver_exit();
6294}
6295
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006296#ifdef MODULE
6297static int fwpath_changed_handler(const char *kmessage,
6298 struct kernel_param *kp)
6299{
Jeff Johnson76052702013-04-16 13:55:05 -07006300 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006301}
6302
6303static int con_mode_handler(const char *kmessage,
6304 struct kernel_param *kp)
6305{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006306 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006307}
6308#else /* #ifdef MODULE */
6309/**---------------------------------------------------------------------------
6310
Jeff Johnson76052702013-04-16 13:55:05 -07006311 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006312
Jeff Johnson76052702013-04-16 13:55:05 -07006313 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006314 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006315 - invoked when module parameter fwpath is modified from userspace to signal
6316 initializing the WLAN driver or when con_mode is modified from userspace
6317 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006318
6319 \return - 0 for success, non zero for failure
6320
6321 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006322static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006323{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006324 int ret_status;
6325
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006326 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006327 ret_status = hdd_driver_init();
6328 wlan_hdd_inited = ret_status ? 0 : 1;
6329 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006330 }
6331
6332 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006333
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006334 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006335
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
Jeff Johnson295189b2012-06-20 16:38:30 -07006341/**---------------------------------------------------------------------------
6342
Jeff Johnson76052702013-04-16 13:55:05 -07006343 \brief fwpath_changed_handler() - Handler Function
6344
6345 Handle changes to the fwpath parameter
6346
6347 \return - 0 for success, non zero for failure
6348
6349 --------------------------------------------------------------------------*/
6350static int fwpath_changed_handler(const char *kmessage,
6351 struct kernel_param *kp)
6352{
6353 int ret;
6354
6355 ret = param_set_copystring(kmessage, kp);
6356 if (0 == ret)
6357 ret = kickstart_driver();
6358 return ret;
6359}
6360
6361/**---------------------------------------------------------------------------
6362
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006363 \brief con_mode_handler() -
6364
6365 Handler function for module param con_mode when it is changed by userspace
6366 Dynamically linked - do nothing
6367 Statically linked - exit and init driver, as in rmmod and insmod
6368
Jeff Johnson76052702013-04-16 13:55:05 -07006369 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006370
Jeff Johnson76052702013-04-16 13:55:05 -07006371 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006372
6373 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006374static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006375{
Jeff Johnson76052702013-04-16 13:55:05 -07006376 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006377
Jeff Johnson76052702013-04-16 13:55:05 -07006378 ret = param_set_int(kmessage, kp);
6379 if (0 == ret)
6380 ret = kickstart_driver();
6381 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006382}
6383#endif /* #ifdef MODULE */
6384
6385/**---------------------------------------------------------------------------
6386
Jeff Johnson295189b2012-06-20 16:38:30 -07006387 \brief hdd_get_conparam() -
6388
6389 This is the driver exit point (invoked when module is unloaded using rmmod)
6390
6391 \param - None
6392
6393 \return - tVOS_CON_MODE
6394
6395 --------------------------------------------------------------------------*/
6396tVOS_CON_MODE hdd_get_conparam ( void )
6397{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006398#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006399 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006400#else
6401 return (tVOS_CON_MODE)curr_con_mode;
6402#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006403}
6404void hdd_set_conparam ( v_UINT_t newParam )
6405{
6406 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006407#ifndef MODULE
6408 curr_con_mode = con_mode;
6409#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006410}
6411/**---------------------------------------------------------------------------
6412
6413 \brief hdd_softap_sta_deauth() - function
6414
6415 This to take counter measure to handle deauth req from HDD
6416
6417 \param - pAdapter - Pointer to the HDD
6418
6419 \param - enable - boolean value
6420
6421 \return - None
6422
6423 --------------------------------------------------------------------------*/
6424
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006425VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006426{
Jeff Johnson295189b2012-06-20 16:38:30 -07006427 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006428 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006429
6430 ENTER();
6431
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006432 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6433 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006434
6435 //Ignore request to deauth bcmc station
6436 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006437 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006438
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006439 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006440
6441 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006442 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006443}
6444
6445/**---------------------------------------------------------------------------
6446
6447 \brief hdd_softap_sta_disassoc() - function
6448
6449 This to take counter measure to handle deauth req from HDD
6450
6451 \param - pAdapter - Pointer to the HDD
6452
6453 \param - enable - boolean value
6454
6455 \return - None
6456
6457 --------------------------------------------------------------------------*/
6458
6459void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6460{
6461 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6462
6463 ENTER();
6464
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306465 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006466
6467 //Ignore request to disassoc bcmc station
6468 if( pDestMacAddress[0] & 0x1 )
6469 return;
6470
6471 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6472}
6473
6474void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6475{
6476 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6477
6478 ENTER();
6479
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306480 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006481
6482 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6483}
6484
Jeff Johnson295189b2012-06-20 16:38:30 -07006485/**---------------------------------------------------------------------------
6486 *
6487 * \brief hdd_get__concurrency_mode() -
6488 *
6489 *
6490 * \param - None
6491 *
6492 * \return - CONCURRENCY MODE
6493 *
6494 * --------------------------------------------------------------------------*/
6495tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6496{
6497 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6498 hdd_context_t *pHddCtx;
6499
6500 if (NULL != pVosContext)
6501 {
6502 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6503 if (NULL != pHddCtx)
6504 {
6505 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6506 }
6507 }
6508
6509 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006510 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006511 return VOS_STA;
6512}
6513
6514/* Decide whether to allow/not the apps power collapse.
6515 * Allow apps power collapse if we are in connected state.
6516 * if not, allow only if we are in IMPS */
6517v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6518{
6519 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006520 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006521 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6523 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6524 hdd_adapter_t *pAdapter = NULL;
6525 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006526 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006527
Jeff Johnson295189b2012-06-20 16:38:30 -07006528 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6529 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006530
Yathish9f22e662012-12-10 14:21:35 -08006531 concurrent_state = hdd_get_concurrency_mode();
6532
6533#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6534 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6535 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6536 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6537 return TRUE;
6538#endif
6539
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 /*loop through all adapters. TBD fix for Concurrency */
6541 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6542 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6543 {
6544 pAdapter = pAdapterNode->pAdapter;
6545 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6546 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6547 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006548 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006550 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006551 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6552 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006553 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006554 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006555 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6556 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 return FALSE;
6558 }
6559 }
6560 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6561 pAdapterNode = pNext;
6562 }
6563 return TRUE;
6564}
6565
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006566/* Decides whether to send suspend notification to Riva
6567 * if any adapter is in BMPS; then it is required */
6568v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6569{
6570 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6571 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6572
6573 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6574 {
6575 return TRUE;
6576 }
6577 return FALSE;
6578}
6579
Jeff Johnson295189b2012-06-20 16:38:30 -07006580void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6581{
6582 switch(mode)
6583 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006584 case VOS_STA_MODE:
6585 case VOS_P2P_CLIENT_MODE:
6586 case VOS_P2P_GO_MODE:
6587 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006588 pHddCtx->concurrency_mode |= (1 << mode);
6589 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006590 break;
6591 default:
6592 break;
6593
6594 }
6595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6596 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6597}
6598
6599
6600void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6601{
6602 switch(mode)
6603 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006604 case VOS_STA_MODE:
6605 case VOS_P2P_CLIENT_MODE:
6606 case VOS_P2P_GO_MODE:
6607 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006608 pHddCtx->no_of_sessions[mode]--;
6609 if (!(pHddCtx->no_of_sessions[mode]))
6610 pHddCtx->concurrency_mode &= (~(1 << mode));
6611 break;
6612 default:
6613 break;
6614 }
6615 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6616 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6617}
6618
Jeff Johnsone7245742012-09-05 17:12:55 -07006619/**---------------------------------------------------------------------------
6620 *
6621 * \brief wlan_hdd_restart_init
6622 *
6623 * This function initalizes restart timer/flag. An internal function.
6624 *
6625 * \param - pHddCtx
6626 *
6627 * \return - None
6628 *
6629 * --------------------------------------------------------------------------*/
6630
6631static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6632{
6633 /* Initialize */
6634 pHddCtx->hdd_restart_retries = 0;
6635 atomic_set(&pHddCtx->isRestartInProgress, 0);
6636 vos_timer_init(&pHddCtx->hdd_restart_timer,
6637 VOS_TIMER_TYPE_SW,
6638 wlan_hdd_restart_timer_cb,
6639 pHddCtx);
6640}
6641/**---------------------------------------------------------------------------
6642 *
6643 * \brief wlan_hdd_restart_deinit
6644 *
6645 * This function cleans up the resources used. An internal function.
6646 *
6647 * \param - pHddCtx
6648 *
6649 * \return - None
6650 *
6651 * --------------------------------------------------------------------------*/
6652
6653static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6654{
6655
6656 VOS_STATUS vos_status;
6657 /* Block any further calls */
6658 atomic_set(&pHddCtx->isRestartInProgress, 1);
6659 /* Cleanup */
6660 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6661 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006662 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006663 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6664 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006665 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006666
6667}
6668
6669/**---------------------------------------------------------------------------
6670 *
6671 * \brief wlan_hdd_framework_restart
6672 *
6673 * This function uses a cfg80211 API to start a framework initiated WLAN
6674 * driver module unload/load.
6675 *
6676 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6677 *
6678 *
6679 * \param - pHddCtx
6680 *
6681 * \return - VOS_STATUS_SUCCESS: Success
6682 * VOS_STATUS_E_EMPTY: Adapter is Empty
6683 * VOS_STATUS_E_NOMEM: No memory
6684
6685 * --------------------------------------------------------------------------*/
6686
6687static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6688{
6689 VOS_STATUS status = VOS_STATUS_SUCCESS;
6690 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006691 int len = (sizeof (struct ieee80211_mgmt));
6692 struct ieee80211_mgmt *mgmt = NULL;
6693
6694 /* Prepare the DEAUTH managment frame with reason code */
6695 mgmt = kzalloc(len, GFP_KERNEL);
6696 if(mgmt == NULL)
6697 {
6698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6699 "%s: memory allocation failed (%d bytes)", __func__, len);
6700 return VOS_STATUS_E_NOMEM;
6701 }
6702 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006703
6704 /* Iterate over all adapters/devices */
6705 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6706 do
6707 {
6708 if( (status == VOS_STATUS_SUCCESS) &&
6709 pAdapterNode &&
6710 pAdapterNode->pAdapter)
6711 {
6712 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6713 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6714 pAdapterNode->pAdapter->dev->name,
6715 pAdapterNode->pAdapter->device_mode,
6716 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006717 /*
6718 * CFG80211 event to restart the driver
6719 *
6720 * 'cfg80211_send_unprot_deauth' sends a
6721 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6722 * of SME(Linux Kernel) state machine.
6723 *
6724 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6725 * the driver.
6726 *
6727 */
6728
6729 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006730 }
6731 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6732 pAdapterNode = pNext;
6733 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6734
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006735
6736 /* Free the allocated management frame */
6737 kfree(mgmt);
6738
Jeff Johnsone7245742012-09-05 17:12:55 -07006739 /* Retry until we unload or reach max count */
6740 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6741 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6742
6743 return status;
6744
6745}
6746/**---------------------------------------------------------------------------
6747 *
6748 * \brief wlan_hdd_restart_timer_cb
6749 *
6750 * Restart timer callback. An internal function.
6751 *
6752 * \param - User data:
6753 *
6754 * \return - None
6755 *
6756 * --------------------------------------------------------------------------*/
6757
6758void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6759{
6760 hdd_context_t *pHddCtx = usrDataForCallback;
6761 wlan_hdd_framework_restart(pHddCtx);
6762 return;
6763
6764}
6765
6766
6767/**---------------------------------------------------------------------------
6768 *
6769 * \brief wlan_hdd_restart_driver
6770 *
6771 * This function sends an event to supplicant to restart the WLAN driver.
6772 *
6773 * This function is called from vos_wlanRestart.
6774 *
6775 * \param - pHddCtx
6776 *
6777 * \return - VOS_STATUS_SUCCESS: Success
6778 * VOS_STATUS_E_EMPTY: Adapter is Empty
6779 * VOS_STATUS_E_ALREADY: Request already in progress
6780
6781 * --------------------------------------------------------------------------*/
6782VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6783{
6784 VOS_STATUS status = VOS_STATUS_SUCCESS;
6785
6786 /* A tight check to make sure reentrancy */
6787 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6788 {
6789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6790 "%s: WLAN restart is already in progress", __func__);
6791
6792 return VOS_STATUS_E_ALREADY;
6793 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006794 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006795#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006796 wcnss_reset_intr();
6797#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006798
Jeff Johnsone7245742012-09-05 17:12:55 -07006799 return status;
6800}
6801
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006802/*
6803 * API to find if there is any STA or P2P-Client is connected
6804 */
6805VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6806{
6807 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6808}
Jeff Johnsone7245742012-09-05 17:12:55 -07006809
Jeff Johnson295189b2012-06-20 16:38:30 -07006810//Register the module init/exit functions
6811module_init(hdd_module_init);
6812module_exit(hdd_module_exit);
6813
6814MODULE_LICENSE("Dual BSD/GPL");
6815MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6816MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6817
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006818module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6819 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006820
Jeff Johnson76052702013-04-16 13:55:05 -07006821module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006822 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);