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