blob: ea0bbc1f167dcfddcb1fdfd57e9714e8bbcd3cd2 [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;
607
608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700609 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700610
611 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
612 {
613 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
614 sizeof(tSirMacAddr)))
615 {
616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700617 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700618 ret = -EFAULT;
619 }
620 }
Amar Singhal0974e402013-02-12 14:27:46 -0800621 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 {
Amar Singhal0974e402013-02-12 14:27:46 -0800623 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700624 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800625
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800627
628 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800631 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800633 ret = hdd_setBand_helper(dev, ptr);
634 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700635 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
636 {
637 char *country_code;
638
639 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700640
641 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700643 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530644 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700645 if( 0 != ret )
646 {
647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
648 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
649
650 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700651 }
652 /*
653 command should be a string having format
654 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
655 */
Amar Singhal0974e402013-02-12 14:27:46 -0800656 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700657 {
Amar Singhal0974e402013-02-12 14:27:46 -0800658 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700659
660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700661 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700662
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800663 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700664 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800665 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
666 {
667 int suspend = 0;
668 tANI_U8 *ptr = (tANI_U8*)command + 15;
669
670 suspend = *ptr - '0';
671 hdd_set_wlan_suspend_mode(suspend);
672 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800673#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
674 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
675 {
676 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700677 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800678 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
679 eHalStatus status = eHAL_STATUS_SUCCESS;
680
681 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
682 value = value + 15;
683
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700684 /* Convert the value from ascii to integer */
685 ret = kstrtos8(value, 10, &rssi);
686 if (ret < 0)
687 {
688 /* If the input value is greater than max value of datatype, then also
689 kstrtou8 fails */
690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
691 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
692 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
693 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
694 ret = -EINVAL;
695 goto exit;
696 }
697
Srinivas Girigowdade697412013-02-14 16:31:48 -0800698 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700699
Srinivas Girigowdade697412013-02-14 16:31:48 -0800700 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
701 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
702 {
703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
704 "Neighbor lookup threshold value %d is out of range"
705 " (Min: %d Max: %d)", lookUpThreshold,
706 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
707 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
708 ret = -EINVAL;
709 goto exit;
710 }
711
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
713 "%s: Received Command to Set Roam trigger"
714 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
715
716 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
717 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
718 if (eHAL_STATUS_SUCCESS != status)
719 {
720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
721 "%s: Failed to set roam trigger, try again", __func__);
722 ret = -EPERM;
723 goto exit;
724 }
725
726 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
727 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
728 }
729 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
730 {
731 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
732 int rssi = (-1) * lookUpThreshold;
733 char extra[32];
734 tANI_U8 len = 0;
735
736 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
737 if (copy_to_user(priv_data.buf, &extra, len + 1))
738 {
739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
740 "%s: failed to copy data to user buffer", __func__);
741 ret = -EFAULT;
742 goto exit;
743 }
744 }
745 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
746 {
747 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700748 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700749 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700750
Srinivas Girigowdade697412013-02-14 16:31:48 -0800751 /* input refresh period is in terms of seconds */
752 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
753 value = value + 18;
754 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if (ret < 0)
757 {
758 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700759 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700761 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800762 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700763 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
764 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800765 ret = -EINVAL;
766 goto exit;
767 }
768
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700769 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
770 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800771 {
772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700773 "Roam scan period value %d is out of range"
774 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700775 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
776 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800777 ret = -EINVAL;
778 goto exit;
779 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700780 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800781
782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
783 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700784 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700786 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
787 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800788 }
789 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
790 {
791 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
792 char extra[32];
793 tANI_U8 len = 0;
794
795 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
796 /* Returned value is in units of seconds */
797 if (copy_to_user(priv_data.buf, &extra, len + 1))
798 {
799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
800 "%s: failed to copy data to user buffer", __func__);
801 ret = -EFAULT;
802 goto exit;
803 }
804 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
806 {
807 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700808 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700809 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700810
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700811 /* input refresh period is in terms of seconds */
812 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
813 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700814
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700816 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700817 if (ret < 0)
818 {
819 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700820 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700822 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700823 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
825 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
826 ret = -EINVAL;
827 goto exit;
828 }
829
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700830 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
831 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
832 {
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
834 "Neighbor scan results refresh period value %d is out of range"
835 " (Min: %d Max: %d)", roamScanRefreshPeriod,
836 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
837 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
838 ret = -EINVAL;
839 goto exit;
840 }
841 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
842
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
844 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700845 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846
847 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
848 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
849 }
850 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
851 {
852 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
853 char extra[32];
854 tANI_U8 len = 0;
855
856 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
857 /* Returned value is in units of seconds */
858 if (copy_to_user(priv_data.buf, &extra, len + 1))
859 {
860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
861 "%s: failed to copy data to user buffer", __func__);
862 ret = -EFAULT;
863 goto exit;
864 }
865 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700866#ifdef FEATURE_WLAN_LFR
867 /* SETROAMMODE */
868 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
869 {
870 tANI_U8 *value = command;
871 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
872
873 /* Move pointer to ahead of SETROAMMODE<delimiter> */
874 value = value + SIZE_OF_SETROAMMODE + 1;
875
876 /* Convert the value from ascii to integer */
877 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
878 if (ret < 0)
879 {
880 /* If the input value is greater than max value of datatype, then also
881 kstrtou8 fails */
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: kstrtou8 failed range [%d - %d]", __func__,
884 CFG_LFR_FEATURE_ENABLED_MIN,
885 CFG_LFR_FEATURE_ENABLED_MAX);
886 ret = -EINVAL;
887 goto exit;
888 }
889 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
890 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
891 {
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "Roam Mode value %d is out of range"
894 " (Min: %d Max: %d)", roamMode,
895 CFG_LFR_FEATURE_ENABLED_MIN,
896 CFG_LFR_FEATURE_ENABLED_MAX);
897 ret = -EINVAL;
898 goto exit;
899 }
900
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
902 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
903 /*
904 * Note that
905 * SETROAMMODE 0 is to enable LFR while
906 * SETROAMMODE 1 is to disable LFR, but
907 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
908 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
909 */
910 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
911 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
912 else
913 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
914
915 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
916 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
917 }
918 /* GETROAMMODE */
919 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
920 {
921 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
922 char extra[32];
923 tANI_U8 len = 0;
924
925 /*
926 * roamMode value shall be inverted because the sementics is different.
927 */
928 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
929 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
930 else
931 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
932
933 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
934 if (copy_to_user(priv_data.buf, &extra, len + 1))
935 {
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
937 "%s: failed to copy data to user buffer", __func__);
938 ret = -EFAULT;
939 goto exit;
940 }
941 }
942#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800943#endif
944#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
945 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
946 {
947 tANI_U8 *value = command;
948 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
949
950 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
951 value = value + 13;
952 /* Convert the value from ascii to integer */
953 ret = kstrtou8(value, 10, &roamRssiDiff);
954 if (ret < 0)
955 {
956 /* If the input value is greater than max value of datatype, then also
957 kstrtou8 fails */
958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
959 "%s: kstrtou8 failed range [%d - %d]", __func__,
960 CFG_ROAM_RSSI_DIFF_MIN,
961 CFG_ROAM_RSSI_DIFF_MAX);
962 ret = -EINVAL;
963 goto exit;
964 }
965
966 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
967 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
968 {
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
970 "Roam rssi diff value %d is out of range"
971 " (Min: %d Max: %d)", roamRssiDiff,
972 CFG_ROAM_RSSI_DIFF_MIN,
973 CFG_ROAM_RSSI_DIFF_MAX);
974 ret = -EINVAL;
975 goto exit;
976 }
977
978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
979 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
980
981 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
982 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
983 }
984 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
987 char extra[32];
988 tANI_U8 len = 0;
989
990 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
991 if (copy_to_user(priv_data.buf, &extra, len + 1))
992 {
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
994 "%s: failed to copy data to user buffer", __func__);
995 ret = -EFAULT;
996 goto exit;
997 }
998 }
999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "GETBAND", 7) == 0)
1002 {
1003 int band = -1;
1004 char extra[32];
1005 tANI_U8 len = 0;
1006 hdd_getBand_helper(pHddCtx, &band);
1007
1008 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1009 if (copy_to_user(priv_data.buf, &extra, len + 1))
1010 {
1011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1012 "%s: failed to copy data to user buffer", __func__);
1013 ret = -EFAULT;
1014 goto exit;
1015 }
1016 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001017 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1018 {
1019 tANI_U8 *value = command;
1020 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1021 tANI_U8 numChannels = 0;
1022 eHalStatus status = eHAL_STATUS_SUCCESS;
1023
1024 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1025 if (eHAL_STATUS_SUCCESS != status)
1026 {
1027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1028 "%s: Failed to parse channel list information", __func__);
1029 ret = -EINVAL;
1030 goto exit;
1031 }
1032
1033 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1034 {
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1036 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1037 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1038 ret = -EINVAL;
1039 goto exit;
1040 }
1041 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1042 numChannels);
1043 if (eHAL_STATUS_SUCCESS != status)
1044 {
1045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: Failed to update channel list information", __func__);
1047 ret = -EINVAL;
1048 goto exit;
1049 }
1050 }
1051 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1052 {
1053 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1054 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001055 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001056 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001057 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001058
1059 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1060 ChannelList, &numChannels ))
1061 {
1062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1063 "%s: failed to get roam scan channel list", __func__);
1064 ret = -EFAULT;
1065 goto exit;
1066 }
1067 /* output channel list is of the format
1068 [Number of roam scan channels][Channel1][Channel2]... */
1069 /* copy the number of channels in the 0th index */
1070 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1071 for (j = 0; (j < numChannels); j++)
1072 {
1073 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1074 }
1075
1076 if (copy_to_user(priv_data.buf, &extra, len + 1))
1077 {
1078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s: failed to copy data to user buffer", __func__);
1080 ret = -EFAULT;
1081 goto exit;
1082 }
1083 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001084 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1085 {
1086 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1087 char extra[32];
1088 tANI_U8 len = 0;
1089
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001090 /* Check if the features OKC/CCX/11R are supported simultaneously,
1091 then this operation is not permitted (return FAILURE) */
1092 if (ccxMode &&
1093 hdd_is_okc_mode_enabled(pHddCtx) &&
1094 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1095 {
1096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1097 "%s: OKC/CCX/11R are supported simultaneously"
1098 " hence this operation is not permitted!", __func__);
1099 ret = -EPERM;
1100 goto exit;
1101 }
1102
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001103 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1104 if (copy_to_user(priv_data.buf, &extra, len + 1))
1105 {
1106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1107 "%s: failed to copy data to user buffer", __func__);
1108 ret = -EFAULT;
1109 goto exit;
1110 }
1111 }
1112 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1113 {
1114 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1115 char extra[32];
1116 tANI_U8 len = 0;
1117
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001118 /* Check if the features OKC/CCX/11R are supported simultaneously,
1119 then this operation is not permitted (return FAILURE) */
1120 if (okcMode &&
1121 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1122 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1125 "%s: OKC/CCX/11R are supported simultaneously"
1126 " hence this operation is not permitted!", __func__);
1127 ret = -EPERM;
1128 goto exit;
1129 }
1130
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001131 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1132 if (copy_to_user(priv_data.buf, &extra, len + 1))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: failed to copy data to user buffer", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001140 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001141 {
1142 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1143 char extra[32];
1144 tANI_U8 len = 0;
1145
1146 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1147 if (copy_to_user(priv_data.buf, &extra, len + 1))
1148 {
1149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: failed to copy data to user buffer", __func__);
1151 ret = -EFAULT;
1152 goto exit;
1153 }
1154 }
1155 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1156 {
1157 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1158 char extra[32];
1159 tANI_U8 len = 0;
1160
1161 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1162 if (copy_to_user(priv_data.buf, &extra, len + 1))
1163 {
1164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: failed to copy data to user buffer", __func__);
1166 ret = -EFAULT;
1167 goto exit;
1168 }
1169 }
1170 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1171 {
1172 tANI_U8 *value = command;
1173 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1174
1175 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1176 value = value + 26;
1177 /* Convert the value from ascii to integer */
1178 ret = kstrtou8(value, 10, &minTime);
1179 if (ret < 0)
1180 {
1181 /* If the input value is greater than max value of datatype, then also
1182 kstrtou8 fails */
1183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: kstrtou8 failed range [%d - %d]", __func__,
1185 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1186 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1187 ret = -EINVAL;
1188 goto exit;
1189 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001190 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1191 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1192 {
1193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "scan min channel time value %d is out of range"
1195 " (Min: %d Max: %d)", minTime,
1196 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1197 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1198 ret = -EINVAL;
1199 goto exit;
1200 }
1201
1202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1203 "%s: Received Command to change channel min time = %d", __func__, minTime);
1204
1205 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1206 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1207 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001208 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1209 {
1210 tANI_U8 *value = command;
1211 tANI_U8 channel = 0;
1212 tANI_U8 dwellTime = 0;
1213 tANI_U8 bufLen = 0;
1214 tANI_U8 *buf = NULL;
1215 tSirMacAddr targetApBssid;
1216 eHalStatus status = eHAL_STATUS_SUCCESS;
1217 struct ieee80211_channel chan;
1218 tANI_U8 finalLen = 0;
1219 tANI_U8 *finalBuf = NULL;
1220 tANI_U8 temp = 0;
1221 u64 cookie;
1222 hdd_station_ctx_t *pHddStaCtx = NULL;
1223 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1224
1225 /* if not associated, no need to send action frame */
1226 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1227 {
1228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1229 ret = -EINVAL;
1230 goto exit;
1231 }
1232
1233 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1234 &dwellTime, &buf, &bufLen);
1235 if (eHAL_STATUS_SUCCESS != status)
1236 {
1237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "%s: Failed to parse send action frame data", __func__);
1239 ret = -EINVAL;
1240 goto exit;
1241 }
1242
1243 /* if the target bssid is different from currently associated AP,
1244 then no need to send action frame */
1245 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1246 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1247 {
1248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1249 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001250 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001251 goto exit;
1252 }
1253
1254 /* if the channel number is different from operating channel then
1255 no need to send action frame */
1256 if (channel != pHddStaCtx->conn_info.operationChannel)
1257 {
1258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1259 "%s: channel(%d) is different from operating channel(%d)",
1260 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1261 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001262 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001263 goto exit;
1264 }
1265 chan.center_freq = sme_ChnToFreq(channel);
1266
1267 finalLen = bufLen + 24;
1268 finalBuf = vos_mem_malloc(finalLen);
1269 if (NULL == finalBuf)
1270 {
1271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1272 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001273 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001274 goto exit;
1275 }
1276 vos_mem_zero(finalBuf, finalLen);
1277
1278 /* Fill subtype */
1279 temp = SIR_MAC_MGMT_ACTION << 4;
1280 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1281
1282 /* Fill type */
1283 temp = SIR_MAC_MGMT_FRAME;
1284 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1285
1286 /* Fill destination address (bssid of the AP) */
1287 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1288
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001289 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001290 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1291
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001292 /* Fill BSSID (AP mac address) */
1293 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001294
1295 /* Fill received buffer from 24th address */
1296 vos_mem_copy(finalBuf + 24, buf, bufLen);
1297
Jeff Johnson11c33152013-04-16 17:52:40 -07001298 /* done with the parsed buffer */
1299 vos_mem_free(buf);
1300
Yue Maf49ba872013-08-19 12:04:25 -07001301 wlan_hdd_action( NULL,
1302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1303 &(pAdapter->wdev),
1304#else
1305 dev,
1306#endif
1307 &chan, 0,
1308#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1309 NL80211_CHAN_HT20, 1,
1310#endif
1311 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001312 1, &cookie );
1313 vos_mem_free(finalBuf);
1314 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001315 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1316 {
1317 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1318 char extra[32];
1319 tANI_U8 len = 0;
1320
1321 /* value is interms of msec */
1322 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1323 if (copy_to_user(priv_data.buf, &extra, len + 1))
1324 {
1325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1326 "%s: failed to copy data to user buffer", __func__);
1327 ret = -EFAULT;
1328 goto exit;
1329 }
1330 }
1331 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1332 {
1333 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001334 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001335 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001336
1337 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1338 value = value + 19;
1339 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001340 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001341 if (ret < 0)
1342 {
1343 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001344 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001346 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001347 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1348 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1349 ret = -EINVAL;
1350 goto exit;
1351 }
1352
1353 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1354 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1355 {
1356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1357 "lfr mode value %d is out of range"
1358 " (Min: %d Max: %d)", maxTime,
1359 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1360 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1361 ret = -EINVAL;
1362 goto exit;
1363 }
1364
1365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1366 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1367
1368 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001369
1370 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1371 * where RFS is the RF Switching time. It is twice RFS to consider the
1372 * time to go off channel and return to the home channel. */
1373 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1374 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1375 {
1376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1377 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1378 " Hence enforcing home away time to disable (0)",
1379 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1380 homeAwayTime = 0;
1381 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1382 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1383 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001384 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1385 }
1386 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1387 {
1388 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1389 char extra[32];
1390 tANI_U8 len = 0;
1391
1392 /* value is interms of msec */
1393 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1394 if (copy_to_user(priv_data.buf, &extra, len + 1))
1395 {
1396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1397 "%s: failed to copy data to user buffer", __func__);
1398 ret = -EFAULT;
1399 goto exit;
1400 }
1401 }
1402 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1403 {
1404 tANI_U8 *value = command;
1405 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1406
1407 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1408 value = value + 16;
1409 /* Convert the value from ascii to integer */
1410 ret = kstrtou16(value, 10, &val);
1411 if (ret < 0)
1412 {
1413 /* If the input value is greater than max value of datatype, then also
1414 kstrtou16 fails */
1415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1416 "%s: kstrtou16 failed range [%d - %d]", __func__,
1417 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1418 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1419 ret = -EINVAL;
1420 goto exit;
1421 }
1422
1423 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1424 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1425 {
1426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1427 "scan home time value %d is out of range"
1428 " (Min: %d Max: %d)", val,
1429 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1430 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1431 ret = -EINVAL;
1432 goto exit;
1433 }
1434
1435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1436 "%s: Received Command to change scan home time = %d", __func__, val);
1437
1438 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1439 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1440 }
1441 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1442 {
1443 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1444 char extra[32];
1445 tANI_U8 len = 0;
1446
1447 /* value is interms of msec */
1448 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1449 if (copy_to_user(priv_data.buf, &extra, len + 1))
1450 {
1451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1452 "%s: failed to copy data to user buffer", __func__);
1453 ret = -EFAULT;
1454 goto exit;
1455 }
1456 }
1457 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1458 {
1459 tANI_U8 *value = command;
1460 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1461
1462 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1463 value = value + 17;
1464 /* Convert the value from ascii to integer */
1465 ret = kstrtou8(value, 10, &val);
1466 if (ret < 0)
1467 {
1468 /* If the input value is greater than max value of datatype, then also
1469 kstrtou8 fails */
1470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1471 "%s: kstrtou8 failed range [%d - %d]", __func__,
1472 CFG_ROAM_INTRA_BAND_MIN,
1473 CFG_ROAM_INTRA_BAND_MAX);
1474 ret = -EINVAL;
1475 goto exit;
1476 }
1477
1478 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1479 (val > CFG_ROAM_INTRA_BAND_MAX))
1480 {
1481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1482 "intra band mode value %d is out of range"
1483 " (Min: %d Max: %d)", val,
1484 CFG_ROAM_INTRA_BAND_MIN,
1485 CFG_ROAM_INTRA_BAND_MAX);
1486 ret = -EINVAL;
1487 goto exit;
1488 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1490 "%s: Received Command to change intra band = %d", __func__, val);
1491
1492 pHddCtx->cfg_ini->nRoamIntraBand = val;
1493 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1494 }
1495 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1496 {
1497 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1498 char extra[32];
1499 tANI_U8 len = 0;
1500
1501 /* value is interms of msec */
1502 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1503 if (copy_to_user(priv_data.buf, &extra, len + 1))
1504 {
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: failed to copy data to user buffer", __func__);
1507 ret = -EFAULT;
1508 goto exit;
1509 }
1510 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001511 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1512 {
1513 tANI_U8 *value = command;
1514 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1515
1516 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1517 value = value + 15;
1518 /* Convert the value from ascii to integer */
1519 ret = kstrtou8(value, 10, &nProbes);
1520 if (ret < 0)
1521 {
1522 /* If the input value is greater than max value of datatype, then also
1523 kstrtou8 fails */
1524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1525 "%s: kstrtou8 failed range [%d - %d]", __func__,
1526 CFG_ROAM_SCAN_N_PROBES_MIN,
1527 CFG_ROAM_SCAN_N_PROBES_MAX);
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
1532 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1533 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1534 {
1535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1536 "NProbes value %d is out of range"
1537 " (Min: %d Max: %d)", nProbes,
1538 CFG_ROAM_SCAN_N_PROBES_MIN,
1539 CFG_ROAM_SCAN_N_PROBES_MAX);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
1543
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1545 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1546
1547 pHddCtx->cfg_ini->nProbes = nProbes;
1548 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1549 }
1550 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1551 {
1552 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1553 char extra[32];
1554 tANI_U8 len = 0;
1555
1556 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1557 if (copy_to_user(priv_data.buf, &extra, len + 1))
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1560 "%s: failed to copy data to user buffer", __func__);
1561 ret = -EFAULT;
1562 goto exit;
1563 }
1564 }
1565 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1566 {
1567 tANI_U8 *value = command;
1568 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001569 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001570
1571 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1572 /* input value is in units of msec */
1573 value = value + 20;
1574 /* Convert the value from ascii to integer */
1575 ret = kstrtou16(value, 10, &homeAwayTime);
1576 if (ret < 0)
1577 {
1578 /* If the input value is greater than max value of datatype, then also
1579 kstrtou8 fails */
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: kstrtou8 failed range [%d - %d]", __func__,
1582 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1583 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1584 ret = -EINVAL;
1585 goto exit;
1586 }
1587
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001588 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1589 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1590 {
1591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "homeAwayTime value %d is out of range"
1593 " (Min: %d Max: %d)", homeAwayTime,
1594 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1595 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1596 ret = -EINVAL;
1597 goto exit;
1598 }
1599
1600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1601 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1602
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001603 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1604 * where RFS is the RF Switching time. It is twice RFS to consider the
1605 * time to go off channel and return to the home channel. */
1606 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1607 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1610 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1611 " Hence enforcing home away time to disable (0)",
1612 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1613 homeAwayTime = 0;
1614 }
1615
1616 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1617 {
1618 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1619 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1620 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001621 }
1622 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1623 {
1624 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1625 char extra[32];
1626 tANI_U8 len = 0;
1627
1628 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1629 if (copy_to_user(priv_data.buf, &extra, len + 1))
1630 {
1631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s: failed to copy data to user buffer", __func__);
1633 ret = -EFAULT;
1634 goto exit;
1635 }
1636 }
1637 else if (strncmp(command, "REASSOC", 7) == 0)
1638 {
1639 tANI_U8 *value = command;
1640 tANI_U8 channel = 0;
1641 tSirMacAddr targetApBssid;
1642 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001643#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1644 tCsrHandoffRequest handoffInfo;
1645#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001646 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001647 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1648
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001649 /* if not associated, no need to proceed with reassoc */
1650 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1651 {
1652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1653 ret = -EINVAL;
1654 goto exit;
1655 }
1656
1657 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1658 if (eHAL_STATUS_SUCCESS != status)
1659 {
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: Failed to parse reassoc command data", __func__);
1662 ret = -EINVAL;
1663 goto exit;
1664 }
1665
1666 /* if the target bssid is same as currently associated AP,
1667 then no need to proceed with reassoc */
1668 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1669 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1670 {
1671 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1672 ret = -EINVAL;
1673 goto exit;
1674 }
1675
1676 /* Check channel number is a valid channel number */
1677 if(VOS_STATUS_SUCCESS !=
1678 wlan_hdd_validate_operation_channel(pAdapter, channel))
1679 {
1680 hddLog(VOS_TRACE_LEVEL_ERROR,
1681 "%s: Invalid Channel [%d] \n", __func__, channel);
1682 return -EINVAL;
1683 }
1684
1685 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001686#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1687 handoffInfo.channel = channel;
1688 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1689 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1690#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001691 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001692#endif
1693#ifdef FEATURE_WLAN_LFR
1694 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1695 {
1696 tANI_U8 *value = command;
1697 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1698
1699 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1700 value = value + 12;
1701 /* Convert the value from ascii to integer */
1702 ret = kstrtou8(value, 10, &lfrMode);
1703 if (ret < 0)
1704 {
1705 /* If the input value is greater than max value of datatype, then also
1706 kstrtou8 fails */
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: kstrtou8 failed range [%d - %d]", __func__,
1709 CFG_LFR_FEATURE_ENABLED_MIN,
1710 CFG_LFR_FEATURE_ENABLED_MAX);
1711 ret = -EINVAL;
1712 goto exit;
1713 }
1714
1715 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1716 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1717 {
1718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1719 "lfr mode value %d is out of range"
1720 " (Min: %d Max: %d)", lfrMode,
1721 CFG_LFR_FEATURE_ENABLED_MIN,
1722 CFG_LFR_FEATURE_ENABLED_MAX);
1723 ret = -EINVAL;
1724 goto exit;
1725 }
1726
1727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1728 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1729
1730 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1731 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1732 }
1733#endif
1734#ifdef WLAN_FEATURE_VOWIFI_11R
1735 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1736 {
1737 tANI_U8 *value = command;
1738 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1739
1740 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1741 value = value + 18;
1742 /* Convert the value from ascii to integer */
1743 ret = kstrtou8(value, 10, &ft);
1744 if (ret < 0)
1745 {
1746 /* If the input value is greater than max value of datatype, then also
1747 kstrtou8 fails */
1748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1749 "%s: kstrtou8 failed range [%d - %d]", __func__,
1750 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1751 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1757 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1758 {
1759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1760 "ft mode value %d is out of range"
1761 " (Min: %d Max: %d)", ft,
1762 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1763 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1764 ret = -EINVAL;
1765 goto exit;
1766 }
1767
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1769 "%s: Received Command to change ft mode = %d", __func__, ft);
1770
1771 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1772 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1773 }
1774#endif
1775#ifdef FEATURE_WLAN_CCX
1776 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1777 {
1778 tANI_U8 *value = command;
1779 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1780
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001781 /* Check if the features OKC/CCX/11R are supported simultaneously,
1782 then this operation is not permitted (return FAILURE) */
1783 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1784 hdd_is_okc_mode_enabled(pHddCtx) &&
1785 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1786 {
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1788 "%s: OKC/CCX/11R are supported simultaneously"
1789 " hence this operation is not permitted!", __func__);
1790 ret = -EPERM;
1791 goto exit;
1792 }
1793
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001794 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1795 value = value + 11;
1796 /* Convert the value from ascii to integer */
1797 ret = kstrtou8(value, 10, &ccxMode);
1798 if (ret < 0)
1799 {
1800 /* If the input value is greater than max value of datatype, then also
1801 kstrtou8 fails */
1802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1803 "%s: kstrtou8 failed range [%d - %d]", __func__,
1804 CFG_CCX_FEATURE_ENABLED_MIN,
1805 CFG_CCX_FEATURE_ENABLED_MAX);
1806 ret = -EINVAL;
1807 goto exit;
1808 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001809 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1810 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "Ccx mode value %d is out of range"
1814 " (Min: %d Max: %d)", ccxMode,
1815 CFG_CCX_FEATURE_ENABLED_MIN,
1816 CFG_CCX_FEATURE_ENABLED_MAX);
1817 ret = -EINVAL;
1818 goto exit;
1819 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1821 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1822
1823 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1824 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1825 }
1826#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001827 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1828 {
1829 tANI_U8 *value = command;
1830 tANI_BOOLEAN roamScanControl = 0;
1831
1832 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1833 value = value + 19;
1834 /* Convert the value from ascii to integer */
1835 ret = kstrtou8(value, 10, &roamScanControl);
1836 if (ret < 0)
1837 {
1838 /* If the input value is greater than max value of datatype, then also
1839 kstrtou8 fails */
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1841 "%s: kstrtou8 failed ", __func__);
1842 ret = -EINVAL;
1843 goto exit;
1844 }
1845
1846 if (0 != roamScanControl)
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "roam scan control invalid value = %d",
1850 roamScanControl);
1851 ret = -EINVAL;
1852 goto exit;
1853 }
1854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1855 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1856
1857 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1858 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001859#ifdef FEATURE_WLAN_OKC
1860 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1861 {
1862 tANI_U8 *value = command;
1863 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1864
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001865 /* Check if the features OKC/CCX/11R are supported simultaneously,
1866 then this operation is not permitted (return FAILURE) */
1867 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1868 hdd_is_okc_mode_enabled(pHddCtx) &&
1869 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1870 {
1871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1872 "%s: OKC/CCX/11R are supported simultaneously"
1873 " hence this operation is not permitted!", __func__);
1874 ret = -EPERM;
1875 goto exit;
1876 }
1877
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001878 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1879 value = value + 11;
1880 /* Convert the value from ascii to integer */
1881 ret = kstrtou8(value, 10, &okcMode);
1882 if (ret < 0)
1883 {
1884 /* If the input value is greater than max value of datatype, then also
1885 kstrtou8 fails */
1886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1887 "%s: kstrtou8 failed range [%d - %d]", __func__,
1888 CFG_OKC_FEATURE_ENABLED_MIN,
1889 CFG_OKC_FEATURE_ENABLED_MAX);
1890 ret = -EINVAL;
1891 goto exit;
1892 }
1893
1894 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1895 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1896 {
1897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1898 "Okc mode value %d is out of range"
1899 " (Min: %d Max: %d)", okcMode,
1900 CFG_OKC_FEATURE_ENABLED_MIN,
1901 CFG_OKC_FEATURE_ENABLED_MAX);
1902 ret = -EINVAL;
1903 goto exit;
1904 }
1905
1906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1907 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1908
1909 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1910 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001911 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1912 {
1913 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1914 char extra[32];
1915 tANI_U8 len = 0;
1916
1917 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1918 if (copy_to_user(priv_data.buf, &extra, len + 1))
1919 {
1920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 "%s: failed to copy data to user buffer", __func__);
1922 ret = -EFAULT;
1923 goto exit;
1924 }
1925 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001926#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301927#ifdef WLAN_FEATURE_PACKET_FILTERING
1928 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1929 {
1930 tANI_U8 filterType = 0;
1931 tANI_U8 *value = command;
1932
1933 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1934 value = value + 22;
1935
1936 /* Convert the value from ascii to integer */
1937 ret = kstrtou8(value, 10, &filterType);
1938 if (ret < 0)
1939 {
1940 /* If the input value is greater than max value of datatype,
1941 * then also kstrtou8 fails
1942 */
1943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1944 "%s: kstrtou8 failed range ", __func__);
1945 ret = -EINVAL;
1946 goto exit;
1947 }
1948
1949 if (filterType != 0 && filterType != 1)
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1952 "%s: Accepted Values are 0 and 1 ", __func__);
1953 ret = -EINVAL;
1954 goto exit;
1955 }
1956 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
1957 pAdapter->sessionId);
1958 }
1959#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05301960 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
1961 {
1962 char *dhcpPhase;
1963 dhcpPhase = command + 12;
1964 if ('1' == *dhcpPhase)
1965 {
1966 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
1967 pAdapter->macAddressCurrent.bytes);
1968 }
1969 else if ('2' == *dhcpPhase)
1970 {
1971 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
1972 pAdapter->macAddressCurrent.bytes);
1973 }
1974 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07001975 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
1976 {
1977 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
1978 }
1979 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
1980 {
1981 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
1982 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05301983 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
1984 {
1985 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1986 char extra[32];
1987 tANI_U8 len = 0;
1988
1989 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
1990 (int)pCfg->nActiveMaxChnTime);
1991 if (copy_to_user(priv_data.buf, &extra, len + 1))
1992 {
1993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1994 "%s: failed to copy data to user buffer", __func__);
1995 ret = -EFAULT;
1996 goto exit;
1997 }
1998 ret = len;
1999 }
2000 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2001 {
2002 tANI_U8 *value = command;
2003 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2004 int val = 0, temp;
2005
2006 value = value + 13;
2007 temp = kstrtou32(value, 10, &val);
2008 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2009 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2010 {
2011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2012 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2013 ret = -EFAULT;
2014 goto exit;
2015 }
2016 pCfg->nActiveMaxChnTime = val;
2017 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07002018 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
2019 {
2020 tANI_U8 filterType = 0;
2021 tANI_U8 *value;
2022 value = command + 9;
2023
2024 /* Convert the value from ascii to integer */
2025 ret = kstrtou8(value, 10, &filterType);
2026 if (ret < 0)
2027 {
2028 /* If the input value is greater than max value of datatype,
2029 * then also kstrtou8 fails
2030 */
2031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2032 "%s: kstrtou8 failed range ", __func__);
2033 ret = -EINVAL;
2034 goto exit;
2035 }
2036 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
2037 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
2038 {
2039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2040 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
2041 " 2-Sink ", __func__);
2042 ret = -EINVAL;
2043 goto exit;
2044 }
2045 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
2046 pHddCtx->drvr_miracast = filterType;
2047 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
2048 }
Leo Chang614d2072013-08-22 14:59:44 -07002049 else if (strncmp(command, "SETMCRATE", 9) == 0)
2050 {
2051 int rc;
2052 tANI_U8 *value = command;
2053 int targetRate;
2054
2055 /* Only valid for SAP mode */
2056 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
2057 {
2058 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: SAP mode is not running", __func__);
2060 ret = -EFAULT;
2061 goto exit;
2062 }
2063
2064 /* Move pointer to ahead of SETMCRATE<delimiter> */
2065 /* input value is in units of hundred kbps */
2066 value = value + 10;
2067 /* Convert the value from ascii to integer, decimal base */
2068 ret = kstrtouint(value, 10, &targetRate);
2069
2070 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
2071 if (rc)
2072 {
2073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "%s: Set MC Rate Fail %d", __func__, rc);
2075 ret = -EFAULT;
2076 goto exit;
2077 }
2078 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002079 else {
2080 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2081 __func__, command);
2082 }
2083
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 }
2085exit:
2086 if (command)
2087 {
2088 kfree(command);
2089 }
2090 return ret;
2091}
2092
Srinivas Girigowdade697412013-02-14 16:31:48 -08002093#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2094void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2095{
2096 eCsrBand band = -1;
2097 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2098 switch (band)
2099 {
2100 case eCSR_BAND_ALL:
2101 *pBand = WLAN_HDD_UI_BAND_AUTO;
2102 break;
2103
2104 case eCSR_BAND_24:
2105 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2106 break;
2107
2108 case eCSR_BAND_5G:
2109 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2110 break;
2111
2112 default:
2113 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2114 *pBand = -1;
2115 break;
2116 }
2117}
2118
2119/**---------------------------------------------------------------------------
2120
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002121 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2122
2123 This function parses the send action frame data passed in the format
2124 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2125
Srinivas Girigowda56076852013-08-20 14:00:50 -07002126 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002127 \param - pTargetApBssid Pointer to target Ap bssid
2128 \param - pChannel Pointer to the Target AP channel
2129 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2130 \param - pBuf Pointer to data
2131 \param - pBufLen Pointer to data length
2132
2133 \return - 0 for success non-zero for failure
2134
2135 --------------------------------------------------------------------------*/
2136VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2137 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2138{
2139 tANI_U8 *inPtr = pValue;
2140 tANI_U8 *dataEnd;
2141 int tempInt;
2142 int j = 0;
2143 int i = 0;
2144 int v = 0;
2145 tANI_U8 tempBuf[32];
2146 tANI_U8 tempByte = 0;
2147
2148 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2149 /*no argument after the command*/
2150 if (NULL == inPtr)
2151 {
2152 return -EINVAL;
2153 }
2154
2155 /*no space after the command*/
2156 else if (SPACE_ASCII_VALUE != *inPtr)
2157 {
2158 return -EINVAL;
2159 }
2160
2161 /*removing empty spaces*/
2162 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2163
2164 /*no argument followed by spaces*/
2165 if ('\0' == *inPtr)
2166 {
2167 return -EINVAL;
2168 }
2169
2170 /*getting the first argument ie the target AP bssid */
2171 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2172 {
2173 return -EINVAL;
2174 }
2175 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2176 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2177 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2178
2179 /* point to the next argument */
2180 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2181 /*no argument after the command*/
2182 if (NULL == inPtr) return -EINVAL;
2183
2184 /*removing empty spaces*/
2185 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2186
2187 /*no argument followed by spaces*/
2188 if ('\0' == *inPtr)
2189 {
2190 return -EINVAL;
2191 }
2192
2193 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002194 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002195 v = kstrtos32(tempBuf, 10, &tempInt);
2196 if ( v < 0) return -EINVAL;
2197
2198 *pChannel = tempInt;
2199
2200 /* point to the next argument */
2201 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2202 /*no argument after the command*/
2203 if (NULL == inPtr) return -EINVAL;
2204 /*removing empty spaces*/
2205 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2206
2207 /*no argument followed by spaces*/
2208 if ('\0' == *inPtr)
2209 {
2210 return -EINVAL;
2211 }
2212
2213 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002214 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002215 v = kstrtos32(tempBuf, 10, &tempInt);
2216 if ( v < 0) return -EINVAL;
2217
2218 *pDwellTime = tempInt;
2219
2220 /* point to the next argument */
2221 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2222 /*no argument after the command*/
2223 if (NULL == inPtr) return -EINVAL;
2224 /*removing empty spaces*/
2225 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2226
2227 /*no argument followed by spaces*/
2228 if ('\0' == *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 /* find the length of data */
2234 dataEnd = inPtr;
2235 while(('\0' != *dataEnd) )
2236 {
2237 dataEnd++;
2238 ++(*pBufLen);
2239 }
2240 if ( *pBufLen <= 0) return -EINVAL;
2241
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002242 /* Allocate the number of bytes based on the number of input characters
2243 whether it is even or odd.
2244 if the number of input characters are even, then we need N/2 byte.
2245 if the number of input characters are odd, then we need do (N+1)/2 to
2246 compensate rounding off.
2247 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2248 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2249 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002250 if (NULL == *pBuf)
2251 {
2252 hddLog(VOS_TRACE_LEVEL_FATAL,
2253 "%s: vos_mem_alloc failed ", __func__);
2254 return -EINVAL;
2255 }
2256
2257 /* the buffer received from the upper layer is character buffer,
2258 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2259 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2260 and f0 in 3rd location */
2261 for (i = 0, j = 0; j < *pBufLen; j += 2)
2262 {
2263 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2264 (*pBuf)[i++] = tempByte;
2265 }
2266 *pBufLen = i;
2267 return VOS_STATUS_SUCCESS;
2268}
2269
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002270/**---------------------------------------------------------------------------
2271
Srinivas Girigowdade697412013-02-14 16:31:48 -08002272 \brief hdd_parse_channellist() - HDD Parse channel list
2273
2274 This function parses the channel list passed in the format
2275 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002276 if the Number of channels (N) does not match with the actual number of channels passed
2277 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2278 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2279 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2280 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002281
2282 \param - pValue Pointer to input channel list
2283 \param - ChannelList Pointer to local output array to record channel list
2284 \param - pNumChannels Pointer to number of roam scan channels
2285
2286 \return - 0 for success non-zero for failure
2287
2288 --------------------------------------------------------------------------*/
2289VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2290{
2291 tANI_U8 *inPtr = pValue;
2292 int tempInt;
2293 int j = 0;
2294 int v = 0;
2295 char buf[32];
2296
2297 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2298 /*no argument after the command*/
2299 if (NULL == inPtr)
2300 {
2301 return -EINVAL;
2302 }
2303
2304 /*no space after the command*/
2305 else if (SPACE_ASCII_VALUE != *inPtr)
2306 {
2307 return -EINVAL;
2308 }
2309
2310 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002311 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002312
2313 /*no argument followed by spaces*/
2314 if ('\0' == *inPtr)
2315 {
2316 return -EINVAL;
2317 }
2318
2319 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002320 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002321 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002322 if ((v < 0) ||
2323 (tempInt <= 0) ||
2324 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2325 {
2326 return -EINVAL;
2327 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002328
2329 *pNumChannels = tempInt;
2330
2331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2332 "Number of channels are: %d", *pNumChannels);
2333
2334 for (j = 0; j < (*pNumChannels); j++)
2335 {
2336 /*inPtr pointing to the beginning of first space after number of channels*/
2337 inPtr = strpbrk( inPtr, " " );
2338 /*no channel list after the number of channels argument*/
2339 if (NULL == inPtr)
2340 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002341 if (0 != j)
2342 {
2343 *pNumChannels = j;
2344 return VOS_STATUS_SUCCESS;
2345 }
2346 else
2347 {
2348 return -EINVAL;
2349 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350 }
2351
2352 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002353 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002354
2355 /*no channel list after the number of channels argument and spaces*/
2356 if ( '\0' == *inPtr )
2357 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002358 if (0 != j)
2359 {
2360 *pNumChannels = j;
2361 return VOS_STATUS_SUCCESS;
2362 }
2363 else
2364 {
2365 return -EINVAL;
2366 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002367 }
2368
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002369 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002371 if ((v < 0) ||
2372 (tempInt <= 0) ||
2373 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2374 {
2375 return -EINVAL;
2376 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 pChannelList[j] = tempInt;
2378
2379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2380 "Channel %d added to preferred channel list",
2381 pChannelList[j] );
2382 }
2383
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384 return VOS_STATUS_SUCCESS;
2385}
2386
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002387
2388/**---------------------------------------------------------------------------
2389
2390 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2391
2392 This function parses the reasoc command data passed in the format
2393 REASSOC<space><bssid><space><channel>
2394
Srinivas Girigowda56076852013-08-20 14:00:50 -07002395 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002396 \param - pTargetApBssid Pointer to target Ap bssid
2397 \param - pChannel Pointer to the Target AP channel
2398
2399 \return - 0 for success non-zero for failure
2400
2401 --------------------------------------------------------------------------*/
2402VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2403{
2404 tANI_U8 *inPtr = pValue;
2405 int tempInt;
2406 int v = 0;
2407 tANI_U8 tempBuf[32];
2408
2409 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2410 /*no argument after the command*/
2411 if (NULL == inPtr)
2412 {
2413 return -EINVAL;
2414 }
2415
2416 /*no space after the command*/
2417 else if (SPACE_ASCII_VALUE != *inPtr)
2418 {
2419 return -EINVAL;
2420 }
2421
2422 /*removing empty spaces*/
2423 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2424
2425 /*no argument followed by spaces*/
2426 if ('\0' == *inPtr)
2427 {
2428 return -EINVAL;
2429 }
2430
2431 /*getting the first argument ie the target AP bssid */
2432 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2433 {
2434 return -EINVAL;
2435 }
2436 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2437 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2438 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2439
2440 /* point to the next argument */
2441 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2442 /*no argument after the command*/
2443 if (NULL == inPtr) return -EINVAL;
2444
2445 /*removing empty spaces*/
2446 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2447
2448 /*no argument followed by spaces*/
2449 if ('\0' == *inPtr)
2450 {
2451 return -EINVAL;
2452 }
2453
2454 /*getting the next argument ie the channel number */
2455 sscanf(inPtr, "%s ", tempBuf);
2456 v = kstrtos32(tempBuf, 10, &tempInt);
2457 if ( v < 0) return -EINVAL;
2458
2459 *pChannel = tempInt;
2460 return VOS_STATUS_SUCCESS;
2461}
2462
2463#endif
2464
Jeff Johnson295189b2012-06-20 16:38:30 -07002465/**---------------------------------------------------------------------------
2466
2467 \brief hdd_open() - HDD Open function
2468
2469 This is called in response to ifconfig up
2470
2471 \param - dev Pointer to net_device structure
2472
2473 \return - 0 for success non-zero for failure
2474
2475 --------------------------------------------------------------------------*/
2476int hdd_open (struct net_device *dev)
2477{
2478 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2479 hdd_context_t *pHddCtx;
2480 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2481 VOS_STATUS status;
2482 v_BOOL_t in_standby = TRUE;
2483
2484 if (NULL == pAdapter)
2485 {
2486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002487 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002488 return -ENODEV;
2489 }
2490
2491 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2492 if (NULL == pHddCtx)
2493 {
2494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002495 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002496 return -ENODEV;
2497 }
2498
2499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2500 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2501 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002502 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2503 {
2504 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302505 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002506 in_standby = FALSE;
2507 break;
2508 }
2509 else
2510 {
2511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2512 pAdapterNode = pNext;
2513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 }
2515
2516 if (TRUE == in_standby)
2517 {
2518 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2519 {
2520 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2521 "wlan out of power save", __func__);
2522 return -EINVAL;
2523 }
2524 }
2525
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002526 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002527 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2528 {
2529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002530 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 /* Enable TX queues only when we are connected */
2532 netif_tx_start_all_queues(dev);
2533 }
2534
2535 return 0;
2536}
2537
2538int hdd_mon_open (struct net_device *dev)
2539{
2540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2541
2542 if(pAdapter == NULL) {
2543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002544 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002545 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002546 }
2547
2548 netif_start_queue(dev);
2549
2550 return 0;
2551}
2552/**---------------------------------------------------------------------------
2553
2554 \brief hdd_stop() - HDD stop function
2555
2556 This is called in response to ifconfig down
2557
2558 \param - dev Pointer to net_device structure
2559
2560 \return - 0 for success non-zero for failure
2561
2562 --------------------------------------------------------------------------*/
2563
2564int hdd_stop (struct net_device *dev)
2565{
2566 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2567 hdd_context_t *pHddCtx;
2568 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2569 VOS_STATUS status;
2570 v_BOOL_t enter_standby = TRUE;
2571
2572 ENTER();
2573
2574 if (NULL == pAdapter)
2575 {
2576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002577 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002578 return -ENODEV;
2579 }
2580
2581 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2582 if (NULL == pHddCtx)
2583 {
2584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002585 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 return -ENODEV;
2587 }
2588
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002589 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2591 netif_tx_disable(pAdapter->dev);
2592 netif_carrier_off(pAdapter->dev);
2593
2594
2595 /* SoftAP ifaces should never go in power save mode
2596 making sure same here. */
2597 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2598 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 )
2601 {
2602 /* SoftAP mode, so return from here */
2603 EXIT();
2604 return 0;
2605 }
2606
2607 /* Find if any iface is up then
2608 if any iface is up then can't put device to sleep/ power save mode. */
2609 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2610 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2611 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002612 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2613 {
2614 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302615 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002616 enter_standby = FALSE;
2617 break;
2618 }
2619 else
2620 {
2621 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2622 pAdapterNode = pNext;
2623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002624 }
2625
2626 if (TRUE == enter_standby)
2627 {
2628 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2629 "entering standby", __func__);
2630 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2631 {
2632 /*log and return success*/
2633 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2634 "wlan in power save", __func__);
2635 }
2636 }
2637
2638 EXIT();
2639 return 0;
2640}
2641
2642/**---------------------------------------------------------------------------
2643
2644 \brief hdd_uninit() - HDD uninit function
2645
2646 This is called during the netdev unregister to uninitialize all data
2647associated with the device
2648
2649 \param - dev Pointer to net_device structure
2650
2651 \return - void
2652
2653 --------------------------------------------------------------------------*/
2654static void hdd_uninit (struct net_device *dev)
2655{
2656 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2657
2658 ENTER();
2659
2660 do
2661 {
2662 if (NULL == pAdapter)
2663 {
2664 hddLog(VOS_TRACE_LEVEL_FATAL,
2665 "%s: NULL pAdapter", __func__);
2666 break;
2667 }
2668
2669 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2670 {
2671 hddLog(VOS_TRACE_LEVEL_FATAL,
2672 "%s: Invalid magic", __func__);
2673 break;
2674 }
2675
2676 if (NULL == pAdapter->pHddCtx)
2677 {
2678 hddLog(VOS_TRACE_LEVEL_FATAL,
2679 "%s: NULL pHddCtx", __func__);
2680 break;
2681 }
2682
2683 if (dev != pAdapter->dev)
2684 {
2685 hddLog(VOS_TRACE_LEVEL_FATAL,
2686 "%s: Invalid device reference", __func__);
2687 /* we haven't validated all cases so let this go for now */
2688 }
2689
2690 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2691
2692 /* after uninit our adapter structure will no longer be valid */
2693 pAdapter->dev = NULL;
2694 pAdapter->magic = 0;
2695 } while (0);
2696
2697 EXIT();
2698}
2699
2700/**---------------------------------------------------------------------------
2701
2702 \brief hdd_release_firmware() -
2703
2704 This function calls the release firmware API to free the firmware buffer.
2705
2706 \param - pFileName Pointer to the File Name.
2707 pCtx - Pointer to the adapter .
2708
2709
2710 \return - 0 for success, non zero for failure
2711
2712 --------------------------------------------------------------------------*/
2713
2714VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2715{
2716 VOS_STATUS status = VOS_STATUS_SUCCESS;
2717 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2718 ENTER();
2719
2720
2721 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2722
2723 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2724
2725 if(pHddCtx->fw) {
2726 release_firmware(pHddCtx->fw);
2727 pHddCtx->fw = NULL;
2728 }
2729 else
2730 status = VOS_STATUS_E_FAILURE;
2731 }
2732 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2733 if(pHddCtx->nv) {
2734 release_firmware(pHddCtx->nv);
2735 pHddCtx->nv = NULL;
2736 }
2737 else
2738 status = VOS_STATUS_E_FAILURE;
2739
2740 }
2741
2742 EXIT();
2743 return status;
2744}
2745
2746/**---------------------------------------------------------------------------
2747
2748 \brief hdd_request_firmware() -
2749
2750 This function reads the firmware file using the request firmware
2751 API and returns the the firmware data and the firmware file size.
2752
2753 \param - pfileName - Pointer to the file name.
2754 - pCtx - Pointer to the adapter .
2755 - ppfw_data - Pointer to the pointer of the firmware data.
2756 - pSize - Pointer to the file size.
2757
2758 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2759
2760 --------------------------------------------------------------------------*/
2761
2762
2763VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2764{
2765 int status;
2766 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2767 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2768 ENTER();
2769
2770 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2771
2772 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2773
2774 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2775 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2776 __func__, pfileName);
2777 retval = VOS_STATUS_E_FAILURE;
2778 }
2779
2780 else {
2781 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2782 *pSize = pHddCtx->fw->size;
2783 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2784 __func__, *pSize);
2785 }
2786 }
2787 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2788
2789 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2790
2791 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2792 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2793 __func__, pfileName);
2794 retval = VOS_STATUS_E_FAILURE;
2795 }
2796
2797 else {
2798 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2799 *pSize = pHddCtx->nv->size;
2800 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2801 __func__, *pSize);
2802 }
2803 }
2804
2805 EXIT();
2806 return retval;
2807}
2808/**---------------------------------------------------------------------------
2809 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2810
2811 This is the function invoked by SME to inform the result of a full power
2812 request issued by HDD
2813
2814 \param - callbackcontext - Pointer to cookie
2815 status - result of request
2816
2817 \return - None
2818
2819--------------------------------------------------------------------------*/
2820void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2821{
2822 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2823
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002824 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 if(&pHddCtx->full_pwr_comp_var)
2826 {
2827 complete(&pHddCtx->full_pwr_comp_var);
2828 }
2829}
2830
2831/**---------------------------------------------------------------------------
2832
2833 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2834
2835 This is the function invoked by SME to inform the result of BMPS
2836 request issued by HDD
2837
2838 \param - callbackcontext - Pointer to cookie
2839 status - result of request
2840
2841 \return - None
2842
2843--------------------------------------------------------------------------*/
2844void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2845{
2846
2847 struct completion *completion_var = (struct completion*) callbackContext;
2848
2849 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2850 if(completion_var != NULL)
2851 {
2852 complete(completion_var);
2853 }
2854}
2855
2856/**---------------------------------------------------------------------------
2857
2858 \brief hdd_get_cfg_file_size() -
2859
2860 This function reads the configuration file using the request firmware
2861 API and returns the configuration file size.
2862
2863 \param - pCtx - Pointer to the adapter .
2864 - pFileName - Pointer to the file name.
2865 - pBufSize - Pointer to the buffer size.
2866
2867 \return - 0 for success, non zero for failure
2868
2869 --------------------------------------------------------------------------*/
2870
2871VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2872{
2873 int status;
2874 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2875
2876 ENTER();
2877
2878 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2879
2880 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2881 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2882 status = VOS_STATUS_E_FAILURE;
2883 }
2884 else {
2885 *pBufSize = pHddCtx->fw->size;
2886 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2887 release_firmware(pHddCtx->fw);
2888 pHddCtx->fw = NULL;
2889 }
2890
2891 EXIT();
2892 return VOS_STATUS_SUCCESS;
2893}
2894
2895/**---------------------------------------------------------------------------
2896
2897 \brief hdd_read_cfg_file() -
2898
2899 This function reads the configuration file using the request firmware
2900 API and returns the cfg data and the buffer size of the configuration file.
2901
2902 \param - pCtx - Pointer to the adapter .
2903 - pFileName - Pointer to the file name.
2904 - pBuffer - Pointer to the data buffer.
2905 - pBufSize - Pointer to the buffer size.
2906
2907 \return - 0 for success, non zero for failure
2908
2909 --------------------------------------------------------------------------*/
2910
2911VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2912 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2913{
2914 int status;
2915 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2916
2917 ENTER();
2918
2919 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2920
2921 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2923 return VOS_STATUS_E_FAILURE;
2924 }
2925 else {
2926 if(*pBufSize != pHddCtx->fw->size) {
2927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2928 "file size", __func__);
2929 release_firmware(pHddCtx->fw);
2930 pHddCtx->fw = NULL;
2931 return VOS_STATUS_E_FAILURE;
2932 }
2933 else {
2934 if(pBuffer) {
2935 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2936 }
2937 release_firmware(pHddCtx->fw);
2938 pHddCtx->fw = NULL;
2939 }
2940 }
2941
2942 EXIT();
2943
2944 return VOS_STATUS_SUCCESS;
2945}
2946
2947/**---------------------------------------------------------------------------
2948
Jeff Johnson295189b2012-06-20 16:38:30 -07002949 \brief hdd_set_mac_address() -
2950
2951 This function sets the user specified mac address using
2952 the command ifconfig wlanX hw ether <mac adress>.
2953
2954 \param - dev - Pointer to the net device.
2955 - addr - Pointer to the sockaddr.
2956 \return - 0 for success, non zero for failure
2957
2958 --------------------------------------------------------------------------*/
2959
2960static int hdd_set_mac_address(struct net_device *dev, void *addr)
2961{
2962 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2963 struct sockaddr *psta_mac_addr = addr;
2964 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2965
2966 ENTER();
2967
2968 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2969
2970#ifdef HDD_SESSIONIZE
2971 // set the MAC address though the STA ID CFG.
2972 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2973 (v_U8_t *)&pAdapter->macAddressCurrent,
2974 sizeof( pAdapter->macAddressCurrent ),
2975 hdd_set_mac_addr_cb, VOS_FALSE );
2976#endif
2977
2978 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2979
2980 EXIT();
2981 return halStatus;
2982}
2983
2984tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2985{
2986 int i;
2987 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2988 {
2989 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2990 break;
2991 }
2992
2993 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2994 return NULL;
2995
2996 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2997 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2998}
2999
3000void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3001{
3002 int i;
3003 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3004 {
3005 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3006 {
3007 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3008 break;
3009 }
3010 }
3011 return;
3012}
3013
3014#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3015 static struct net_device_ops wlan_drv_ops = {
3016 .ndo_open = hdd_open,
3017 .ndo_stop = hdd_stop,
3018 .ndo_uninit = hdd_uninit,
3019 .ndo_start_xmit = hdd_hard_start_xmit,
3020 .ndo_tx_timeout = hdd_tx_timeout,
3021 .ndo_get_stats = hdd_stats,
3022 .ndo_do_ioctl = hdd_ioctl,
3023 .ndo_set_mac_address = hdd_set_mac_address,
3024 .ndo_select_queue = hdd_select_queue,
3025#ifdef WLAN_FEATURE_PACKET_FILTERING
3026#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3027 .ndo_set_rx_mode = hdd_set_multicast_list,
3028#else
3029 .ndo_set_multicast_list = hdd_set_multicast_list,
3030#endif //LINUX_VERSION_CODE
3031#endif
3032 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003033 static struct net_device_ops wlan_mon_drv_ops = {
3034 .ndo_open = hdd_mon_open,
3035 .ndo_stop = hdd_stop,
3036 .ndo_uninit = hdd_uninit,
3037 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3038 .ndo_tx_timeout = hdd_tx_timeout,
3039 .ndo_get_stats = hdd_stats,
3040 .ndo_do_ioctl = hdd_ioctl,
3041 .ndo_set_mac_address = hdd_set_mac_address,
3042 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003043
3044#endif
3045
3046void hdd_set_station_ops( struct net_device *pWlanDev )
3047{
3048#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3049 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3050 pWlanDev->netdev_ops = &wlan_drv_ops;
3051#else
3052 pWlanDev->open = hdd_open;
3053 pWlanDev->stop = hdd_stop;
3054 pWlanDev->uninit = hdd_uninit;
3055 pWlanDev->hard_start_xmit = NULL;
3056 pWlanDev->tx_timeout = hdd_tx_timeout;
3057 pWlanDev->get_stats = hdd_stats;
3058 pWlanDev->do_ioctl = hdd_ioctl;
3059 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3060 pWlanDev->set_mac_address = hdd_set_mac_address;
3061#endif
3062}
3063
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003064static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003065{
3066 struct net_device *pWlanDev = NULL;
3067 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 /*
3069 * cfg80211 initialization and registration....
3070 */
3071 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3072
Jeff Johnson295189b2012-06-20 16:38:30 -07003073 if(pWlanDev != NULL)
3074 {
3075
3076 //Save the pointer to the net_device in the HDD adapter
3077 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3078
Jeff Johnson295189b2012-06-20 16:38:30 -07003079 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3080
3081 pAdapter->dev = pWlanDev;
3082 pAdapter->pHddCtx = pHddCtx;
3083 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3084
3085 init_completion(&pAdapter->session_open_comp_var);
3086 init_completion(&pAdapter->session_close_comp_var);
3087 init_completion(&pAdapter->disconnect_comp_var);
3088 init_completion(&pAdapter->linkup_event_var);
3089 init_completion(&pAdapter->cancel_rem_on_chan_var);
3090 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003091#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3092 init_completion(&pAdapter->offchannel_tx_event);
3093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003094 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003095#ifdef FEATURE_WLAN_TDLS
3096 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003097 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003098 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303099 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003100#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003101 init_completion(&pHddCtx->mc_sus_event_var);
3102 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303103 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003104 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003105
Jeff Johnson295189b2012-06-20 16:38:30 -07003106 pAdapter->isLinkUpSvcNeeded = FALSE;
3107 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3108 //Init the net_device structure
3109 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3110
3111 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3112 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3113 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3114 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3115
3116 hdd_set_station_ops( pAdapter->dev );
3117
3118 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003119 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3120 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3121 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 /* set pWlanDev's parent to underlying device */
3123 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3124 }
3125
3126 return pAdapter;
3127}
3128
3129VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3130{
3131 struct net_device *pWlanDev = pAdapter->dev;
3132 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3133 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3134 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3135
3136 if( rtnl_lock_held )
3137 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003138 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003139 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3140 {
3141 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3142 return VOS_STATUS_E_FAILURE;
3143 }
3144 }
3145 if (register_netdevice(pWlanDev))
3146 {
3147 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3148 return VOS_STATUS_E_FAILURE;
3149 }
3150 }
3151 else
3152 {
3153 if(register_netdev(pWlanDev))
3154 {
3155 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3156 return VOS_STATUS_E_FAILURE;
3157 }
3158 }
3159 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3160
3161 return VOS_STATUS_SUCCESS;
3162}
3163
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003164static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003165{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003166 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003167
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003168 if (NULL == pAdapter)
3169 {
3170 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3171 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003173
3174 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3175 {
3176 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3177 return eHAL_STATUS_NOT_INITIALIZED;
3178 }
3179
3180 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3181
3182 /* need to make sure all of our scheduled work has completed.
3183 * This callback is called from MC thread context, so it is safe to
3184 * to call below flush workqueue API from here.
3185 */
3186 flush_scheduled_work();
3187
3188 /* We can be blocked while waiting for scheduled work to be
3189 * flushed, and the adapter structure can potentially be freed, in
3190 * which case the magic will have been reset. So make sure the
3191 * magic is still good, and hence the adapter structure is still
3192 * valid, before signaling completion */
3193 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3194 {
3195 complete(&pAdapter->session_close_comp_var);
3196 }
3197
Jeff Johnson295189b2012-06-20 16:38:30 -07003198 return eHAL_STATUS_SUCCESS;
3199}
3200
3201VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3202{
3203 struct net_device *pWlanDev = pAdapter->dev;
3204 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3205 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3206 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3207 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3208 int rc = 0;
3209
3210 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003211 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003212 //Open a SME session for future operation
3213 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003214 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3216 {
3217 hddLog(VOS_TRACE_LEVEL_FATAL,
3218 "sme_OpenSession() failed with status code %08d [x%08lx]",
3219 halStatus, halStatus );
3220 status = VOS_STATUS_E_FAILURE;
3221 goto error_sme_open;
3222 }
3223
3224 //Block on a completion variable. Can't wait forever though.
3225 rc = wait_for_completion_interruptible_timeout(
3226 &pAdapter->session_open_comp_var,
3227 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3228 if (!rc)
3229 {
3230 hddLog(VOS_TRACE_LEVEL_FATAL,
3231 "Session is not opened within timeout period code %08d", rc );
3232 status = VOS_STATUS_E_FAILURE;
3233 goto error_sme_open;
3234 }
3235
3236 // Register wireless extensions
3237 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3238 {
3239 hddLog(VOS_TRACE_LEVEL_FATAL,
3240 "hdd_register_wext() failed with status code %08d [x%08lx]",
3241 halStatus, halStatus );
3242 status = VOS_STATUS_E_FAILURE;
3243 goto error_register_wext;
3244 }
3245 //Safe to register the hard_start_xmit function again
3246#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3247 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3248#else
3249 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3250#endif
3251
3252 //Set the Connection State to Not Connected
3253 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3254
3255 //Set the default operation channel
3256 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3257
3258 /* Make the default Auth Type as OPEN*/
3259 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3260
3261 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3262 {
3263 hddLog(VOS_TRACE_LEVEL_FATAL,
3264 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3265 status, status );
3266 goto error_init_txrx;
3267 }
3268
3269 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3270
3271 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3272 {
3273 hddLog(VOS_TRACE_LEVEL_FATAL,
3274 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3275 status, status );
3276 goto error_wmm_init;
3277 }
3278
3279 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3280
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003281#ifdef FEATURE_WLAN_TDLS
3282 if(0 != wlan_hdd_tdls_init(pAdapter))
3283 {
3284 status = VOS_STATUS_E_FAILURE;
3285 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3286 goto error_tdls_init;
3287 }
3288 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3289#endif
3290
Jeff Johnson295189b2012-06-20 16:38:30 -07003291 return VOS_STATUS_SUCCESS;
3292
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003293#ifdef FEATURE_WLAN_TDLS
3294error_tdls_init:
3295 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3296 hdd_wmm_adapter_close(pAdapter);
3297#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003298error_wmm_init:
3299 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3300 hdd_deinit_tx_rx(pAdapter);
3301error_init_txrx:
3302 hdd_UnregisterWext(pWlanDev);
3303error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003304 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003305 {
3306 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003307 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003309 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 {
3311 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003312 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003313 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003314 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 }
3316}
3317error_sme_open:
3318 return status;
3319}
3320
Jeff Johnson295189b2012-06-20 16:38:30 -07003321void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3322{
3323 hdd_cfg80211_state_t *cfgState;
3324
3325 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3326
3327 if( NULL != cfgState->buf )
3328 {
3329 int rc;
3330 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3331 rc = wait_for_completion_interruptible_timeout(
3332 &pAdapter->tx_action_cnf_event,
3333 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3334 if(!rc)
3335 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003336 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003337 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3338 }
3339 }
3340 return;
3341}
Jeff Johnson295189b2012-06-20 16:38:30 -07003342
3343void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3344{
3345 ENTER();
3346 switch ( pAdapter->device_mode )
3347 {
3348 case WLAN_HDD_INFRA_STATION:
3349 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003350 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 {
3352 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3353 {
3354 hdd_deinit_tx_rx( pAdapter );
3355 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3356 }
3357
3358 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3359 {
3360 hdd_wmm_adapter_close( pAdapter );
3361 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3362 }
3363
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003365#ifdef FEATURE_WLAN_TDLS
3366 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3367 {
3368 wlan_hdd_tdls_exit(pAdapter);
3369 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3370 }
3371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003372
3373 break;
3374 }
3375
3376 case WLAN_HDD_SOFTAP:
3377 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003379 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003380
3381 hdd_unregister_hostapd(pAdapter);
3382 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003383 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 break;
3385 }
3386
3387 case WLAN_HDD_MONITOR:
3388 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003389 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003390 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3391 {
3392 hdd_deinit_tx_rx( pAdapter );
3393 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003395 if(NULL != pAdapterforTx)
3396 {
3397 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003399 break;
3400 }
3401
3402
3403 default:
3404 break;
3405 }
3406
3407 EXIT();
3408}
3409
3410void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3411{
3412 struct net_device *pWlanDev = pAdapter->dev;
3413
3414 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3415 if( rtnl_held )
3416 {
3417 unregister_netdevice(pWlanDev);
3418 }
3419 else
3420 {
3421 unregister_netdev(pWlanDev);
3422 }
3423 // note that the pAdapter is no longer valid at this point
3424 // since the memory has been reclaimed
3425 }
3426
3427}
3428
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003429void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3430{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303431 VOS_STATUS status;
3432 hdd_adapter_t *pAdapter = NULL;
3433 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003434
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303435 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003436
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303437 /*loop through all adapters.*/
3438 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003439 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303440 pAdapter = pAdapterNode->pAdapter;
3441 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3442 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003443
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303444 { // we skip this registration for modes other than STA and P2P client modes.
3445 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3446 pAdapterNode = pNext;
3447 continue;
3448 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003449
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303450 //Apply Dynamic DTIM For P2P
3451 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3452 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3453 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3454 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3455 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3456 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3457 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3458 (eConnectionState_Associated ==
3459 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3460 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3461 {
3462 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003463
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303464 powerRequest.uIgnoreDTIM = 1;
3465 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3466
3467 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3468 {
3469 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3470 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3471 }
3472 else
3473 {
3474 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3475 }
3476
3477 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3478 * specified during Enter/Exit BMPS when LCD off*/
3479 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3480 NULL, eANI_BOOLEAN_FALSE);
3481 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3482 NULL, eANI_BOOLEAN_FALSE);
3483
3484 /* switch to the DTIM specified in cfg.ini */
3485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3486 "Switch to DTIM %d", powerRequest.uListenInterval);
3487 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3488 break;
3489
3490 }
3491
3492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3493 pAdapterNode = pNext;
3494 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003495}
3496
3497void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3498{
3499 /*Switch back to DTIM 1*/
3500 tSirSetPowerParamsReq powerRequest = { 0 };
3501
3502 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3503 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003504 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003505
3506 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3507 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3508 NULL, eANI_BOOLEAN_FALSE);
3509 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3510 NULL, eANI_BOOLEAN_FALSE);
3511
3512 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3513 "Switch to DTIM%d",powerRequest.uListenInterval);
3514 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3515
3516}
3517
Jeff Johnson295189b2012-06-20 16:38:30 -07003518VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3519{
3520 VOS_STATUS status = VOS_STATUS_SUCCESS;
3521
3522 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3523 {
3524 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3525 }
3526
3527 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3528 {
3529 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3530 }
3531
3532 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3533 {
3534 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3535 }
3536
3537 return status;
3538}
3539
3540VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3541{
3542 hdd_adapter_t *pAdapter = NULL;
3543 eHalStatus halStatus;
3544 VOS_STATUS status = VOS_STATUS_E_INVAL;
3545 v_BOOL_t disableBmps = FALSE;
3546 v_BOOL_t disableImps = FALSE;
3547
3548 switch(session_type)
3549 {
3550 case WLAN_HDD_INFRA_STATION:
3551 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003552 case WLAN_HDD_P2P_CLIENT:
3553 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 //Exit BMPS -> Is Sta/P2P Client is already connected
3555 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3556 if((NULL != pAdapter)&&
3557 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3558 {
3559 disableBmps = TRUE;
3560 }
3561
3562 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3563 if((NULL != pAdapter)&&
3564 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3565 {
3566 disableBmps = TRUE;
3567 }
3568
3569 //Exit both Bmps and Imps incase of Go/SAP Mode
3570 if((WLAN_HDD_SOFTAP == session_type) ||
3571 (WLAN_HDD_P2P_GO == session_type))
3572 {
3573 disableBmps = TRUE;
3574 disableImps = TRUE;
3575 }
3576
3577 if(TRUE == disableImps)
3578 {
3579 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3580 {
3581 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3582 }
3583 }
3584
3585 if(TRUE == disableBmps)
3586 {
3587 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3588 {
3589 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3590
3591 if(eHAL_STATUS_SUCCESS != halStatus)
3592 {
3593 status = VOS_STATUS_E_FAILURE;
3594 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3595 VOS_ASSERT(0);
3596 return status;
3597 }
3598 }
3599
3600 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3601 {
3602 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3603
3604 if(eHAL_STATUS_SUCCESS != halStatus)
3605 {
3606 status = VOS_STATUS_E_FAILURE;
3607 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3608 VOS_ASSERT(0);
3609 return status;
3610 }
3611 }
3612 }
3613
3614 if((TRUE == disableBmps) ||
3615 (TRUE == disableImps))
3616 {
3617 /* Now, get the chip into Full Power now */
3618 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3619 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3620 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3621
3622 if(halStatus != eHAL_STATUS_SUCCESS)
3623 {
3624 if(halStatus == eHAL_STATUS_PMC_PENDING)
3625 {
3626 //Block on a completion variable. Can't wait forever though
3627 wait_for_completion_interruptible_timeout(
3628 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3629 }
3630 else
3631 {
3632 status = VOS_STATUS_E_FAILURE;
3633 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3634 VOS_ASSERT(0);
3635 return status;
3636 }
3637 }
3638
3639 status = VOS_STATUS_SUCCESS;
3640 }
3641
3642 break;
3643 }
3644 return status;
3645}
3646
3647hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003648 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 tANI_U8 rtnl_held )
3650{
3651 hdd_adapter_t *pAdapter = NULL;
3652 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3653 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3654 VOS_STATUS exitbmpsStatus;
3655
3656 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3657
3658 //Disable BMPS incase of Concurrency
3659 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3660
3661 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3662 {
3663 //Fail to Exit BMPS
3664 VOS_ASSERT(0);
3665 return NULL;
3666 }
3667
3668 switch(session_type)
3669 {
3670 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003672 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 {
3674 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3675
3676 if( NULL == pAdapter )
3677 return NULL;
3678
Jeff Johnsone7245742012-09-05 17:12:55 -07003679 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3680 NL80211_IFTYPE_P2P_CLIENT:
3681 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003682
Jeff Johnson295189b2012-06-20 16:38:30 -07003683 pAdapter->device_mode = session_type;
3684
3685 status = hdd_init_station_mode( pAdapter );
3686 if( VOS_STATUS_SUCCESS != status )
3687 goto err_free_netdev;
3688
3689 status = hdd_register_interface( pAdapter, rtnl_held );
3690 if( VOS_STATUS_SUCCESS != status )
3691 {
3692 hdd_deinit_adapter(pHddCtx, pAdapter);
3693 goto err_free_netdev;
3694 }
3695 //Stop the Interface TX queue.
3696 netif_tx_disable(pAdapter->dev);
3697 //netif_tx_disable(pWlanDev);
3698 netif_carrier_off(pAdapter->dev);
3699
3700 break;
3701 }
3702
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003704 case WLAN_HDD_SOFTAP:
3705 {
3706 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3707 if( NULL == pAdapter )
3708 return NULL;
3709
Jeff Johnson295189b2012-06-20 16:38:30 -07003710 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3711 NL80211_IFTYPE_AP:
3712 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 pAdapter->device_mode = session_type;
3714
3715 status = hdd_init_ap_mode(pAdapter);
3716 if( VOS_STATUS_SUCCESS != status )
3717 goto err_free_netdev;
3718
3719 status = hdd_register_hostapd( pAdapter, rtnl_held );
3720 if( VOS_STATUS_SUCCESS != status )
3721 {
3722 hdd_deinit_adapter(pHddCtx, pAdapter);
3723 goto err_free_netdev;
3724 }
3725
3726 netif_tx_disable(pAdapter->dev);
3727 netif_carrier_off(pAdapter->dev);
3728
3729 hdd_set_conparam( 1 );
3730 break;
3731 }
3732 case WLAN_HDD_MONITOR:
3733 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3735 if( NULL == pAdapter )
3736 return NULL;
3737
3738 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3739 pAdapter->device_mode = session_type;
3740 status = hdd_register_interface( pAdapter, rtnl_held );
3741#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3742 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3743#else
3744 pAdapter->dev->open = hdd_mon_open;
3745 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3746#endif
3747 hdd_init_tx_rx( pAdapter );
3748 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3749 //Set adapter to be used for data tx. It will use either GO or softap.
3750 pAdapter->sessionCtx.monitor.pAdapterForTx =
3751 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3753 {
3754 pAdapter->sessionCtx.monitor.pAdapterForTx =
3755 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3756 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 /* This workqueue will be used to transmit management packet over
3758 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003759 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3760 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3761 return NULL;
3762 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003763
Jeff Johnson295189b2012-06-20 16:38:30 -07003764 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3765 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 }
3767 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 case WLAN_HDD_FTM:
3769 {
3770 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3771
3772 if( NULL == pAdapter )
3773 return NULL;
3774 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3775 * message while loading driver in FTM mode. */
3776 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3777 pAdapter->device_mode = session_type;
3778 status = hdd_register_interface( pAdapter, rtnl_held );
3779 }
3780 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 default:
3782 {
3783 VOS_ASSERT(0);
3784 return NULL;
3785 }
3786 }
3787
3788
3789 if( VOS_STATUS_SUCCESS == status )
3790 {
3791 //Add it to the hdd's session list.
3792 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3793 if( NULL == pHddAdapterNode )
3794 {
3795 status = VOS_STATUS_E_NOMEM;
3796 }
3797 else
3798 {
3799 pHddAdapterNode->pAdapter = pAdapter;
3800 status = hdd_add_adapter_back ( pHddCtx,
3801 pHddAdapterNode );
3802 }
3803 }
3804
3805 if( VOS_STATUS_SUCCESS != status )
3806 {
3807 if( NULL != pAdapter )
3808 {
3809 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3810 pAdapter = NULL;
3811 }
3812 if( NULL != pHddAdapterNode )
3813 {
3814 vos_mem_free( pHddAdapterNode );
3815 }
3816
3817 goto resume_bmps;
3818 }
3819
3820 if(VOS_STATUS_SUCCESS == status)
3821 {
3822 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3823
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003824 //Initialize the WoWL service
3825 if(!hdd_init_wowl(pAdapter))
3826 {
3827 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3828 goto err_free_netdev;
3829 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 return pAdapter;
3832
3833err_free_netdev:
3834 free_netdev(pAdapter->dev);
3835 wlan_hdd_release_intf_addr( pHddCtx,
3836 pAdapter->macAddressCurrent.bytes );
3837
3838resume_bmps:
3839 //If bmps disabled enable it
3840 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3841 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303842 if (pHddCtx->hdd_wlan_suspended)
3843 {
3844 hdd_set_pwrparams(pHddCtx);
3845 }
3846 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003847 }
3848 return NULL;
3849}
3850
3851VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3852 tANI_U8 rtnl_held )
3853{
3854 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3855 VOS_STATUS status;
3856
3857 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3858 if( VOS_STATUS_SUCCESS != status )
3859 return status;
3860
3861 while ( pCurrent->pAdapter != pAdapter )
3862 {
3863 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3864 if( VOS_STATUS_SUCCESS != status )
3865 break;
3866
3867 pCurrent = pNext;
3868 }
3869 pAdapterNode = pCurrent;
3870 if( VOS_STATUS_SUCCESS == status )
3871 {
3872 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3873 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3874 hdd_remove_adapter( pHddCtx, pAdapterNode );
3875 vos_mem_free( pAdapterNode );
3876
Jeff Johnson295189b2012-06-20 16:38:30 -07003877
3878 /* If there is a single session of STA/P2P client, re-enable BMPS */
3879 if ((!vos_concurrent_sessions_running()) &&
3880 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3881 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3882 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303883 if (pHddCtx->hdd_wlan_suspended)
3884 {
3885 hdd_set_pwrparams(pHddCtx);
3886 }
3887 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 }
3889
3890 return VOS_STATUS_SUCCESS;
3891 }
3892
3893 return VOS_STATUS_E_FAILURE;
3894}
3895
3896VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3897{
3898 hdd_adapter_list_node_t *pHddAdapterNode;
3899 VOS_STATUS status;
3900
3901 ENTER();
3902
3903 do
3904 {
3905 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3906 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3907 {
3908 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3909 vos_mem_free( pHddAdapterNode );
3910 }
3911 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3912
3913 EXIT();
3914
3915 return VOS_STATUS_SUCCESS;
3916}
3917
3918void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3919{
3920 v_U8_t addIE[1] = {0};
3921
3922 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3923 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3924 eANI_BOOLEAN_FALSE) )
3925 {
3926 hddLog(LOGE,
3927 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3928 }
3929
3930 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3931 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3932 eANI_BOOLEAN_FALSE) )
3933 {
3934 hddLog(LOGE,
3935 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3936 }
3937
3938 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3939 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3940 eANI_BOOLEAN_FALSE) )
3941 {
3942 hddLog(LOGE,
3943 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3944 }
3945}
3946
3947VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3948{
3949 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3950 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3951 union iwreq_data wrqu;
3952
3953 ENTER();
3954
3955 switch(pAdapter->device_mode)
3956 {
3957 case WLAN_HDD_INFRA_STATION:
3958 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003959 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3961 {
3962 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3963 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3964 pAdapter->sessionId,
3965 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3966 else
3967 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3968 pAdapter->sessionId,
3969 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3970 //success implies disconnect command got queued up successfully
3971 if(halStatus == eHAL_STATUS_SUCCESS)
3972 {
3973 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3974 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3975 }
3976 memset(&wrqu, '\0', sizeof(wrqu));
3977 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3978 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3979 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3980 }
3981 else
3982 {
3983 hdd_abort_mac_scan(pHddCtx);
3984 }
3985
3986 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3987 {
3988 INIT_COMPLETION(pAdapter->session_close_comp_var);
3989 if (eHAL_STATUS_SUCCESS ==
3990 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3991 hdd_smeCloseSessionCallback, pAdapter))
3992 {
3993 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003994 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003995 &pAdapter->session_close_comp_var,
3996 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3997 }
3998 }
3999
4000 break;
4001
4002 case WLAN_HDD_SOFTAP:
4003 case WLAN_HDD_P2P_GO:
4004 //Any softap specific cleanup here...
4005 mutex_lock(&pHddCtx->sap_lock);
4006 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4007 {
4008 VOS_STATUS status;
4009 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4010
4011 //Stop Bss.
4012 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4013 if (VOS_IS_STATUS_SUCCESS(status))
4014 {
4015 hdd_hostapd_state_t *pHostapdState =
4016 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4017
4018 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4019
4020 if (!VOS_IS_STATUS_SUCCESS(status))
4021 {
4022 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004023 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004024 }
4025 }
4026 else
4027 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004028 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004029 }
4030 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4031
4032 if (eHAL_STATUS_FAILURE ==
4033 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4034 0, NULL, eANI_BOOLEAN_FALSE))
4035 {
4036 hddLog(LOGE,
4037 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004038 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004039 }
4040
4041 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4042 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4043 eANI_BOOLEAN_FALSE) )
4044 {
4045 hddLog(LOGE,
4046 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4047 }
4048
4049 // Reset WNI_CFG_PROBE_RSP Flags
4050 wlan_hdd_reset_prob_rspies(pAdapter);
4051 kfree(pAdapter->sessionCtx.ap.beacon);
4052 pAdapter->sessionCtx.ap.beacon = NULL;
4053 }
4054 mutex_unlock(&pHddCtx->sap_lock);
4055 break;
4056 case WLAN_HDD_MONITOR:
4057 break;
4058 default:
4059 break;
4060 }
4061
4062 EXIT();
4063 return VOS_STATUS_SUCCESS;
4064}
4065
4066VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4067{
4068 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4069 VOS_STATUS status;
4070 hdd_adapter_t *pAdapter;
4071
4072 ENTER();
4073
4074 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4075
4076 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4077 {
4078 pAdapter = pAdapterNode->pAdapter;
4079 netif_tx_disable(pAdapter->dev);
4080 netif_carrier_off(pAdapter->dev);
4081
4082 hdd_stop_adapter( pHddCtx, pAdapter );
4083
4084 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4085 pAdapterNode = pNext;
4086 }
4087
4088 EXIT();
4089
4090 return VOS_STATUS_SUCCESS;
4091}
4092
4093VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4094{
4095 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4096 VOS_STATUS status;
4097 hdd_adapter_t *pAdapter;
4098
4099 ENTER();
4100
4101 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4102
4103 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4104 {
4105 pAdapter = pAdapterNode->pAdapter;
4106 netif_tx_disable(pAdapter->dev);
4107 netif_carrier_off(pAdapter->dev);
4108
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004109 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4110
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 hdd_deinit_tx_rx(pAdapter);
4112 hdd_wmm_adapter_close(pAdapter);
4113
4114 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4115 pAdapterNode = pNext;
4116 }
4117
4118 EXIT();
4119
4120 return VOS_STATUS_SUCCESS;
4121}
4122
4123VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4124{
4125 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4126 VOS_STATUS status;
4127 hdd_adapter_t *pAdapter;
4128 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304129 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004130
4131 ENTER();
4132
4133 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4134
4135 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4136 {
4137 pAdapter = pAdapterNode->pAdapter;
4138
4139 switch(pAdapter->device_mode)
4140 {
4141 case WLAN_HDD_INFRA_STATION:
4142 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004143 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304144
4145 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4146
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 hdd_init_station_mode(pAdapter);
4148 /* Open the gates for HDD to receive Wext commands */
4149 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004150 pHddCtx->scan_info.mScanPending = FALSE;
4151 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004152
4153 //Trigger the initial scan
4154 hdd_wlan_initial_scan(pAdapter);
4155
4156 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304157 if (eConnectionState_Associated == connState ||
4158 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 {
4160 union iwreq_data wrqu;
4161 memset(&wrqu, '\0', sizeof(wrqu));
4162 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4163 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4164 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004165 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004166
Jeff Johnson295189b2012-06-20 16:38:30 -07004167 /* indicate disconnected event to nl80211 */
4168 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4169 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004170 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304171 else if (eConnectionState_Connecting == connState)
4172 {
4173 /*
4174 * Indicate connect failure to supplicant if we were in the
4175 * process of connecting
4176 */
4177 cfg80211_connect_result(pAdapter->dev, NULL,
4178 NULL, 0, NULL, 0,
4179 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4180 GFP_KERNEL);
4181 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004182 break;
4183
4184 case WLAN_HDD_SOFTAP:
4185 /* softAP can handle SSR */
4186 break;
4187
4188 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004189 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4190 __func__);
4191 /* event supplicant to restart */
4192 cfg80211_del_sta(pAdapter->dev,
4193 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004194 break;
4195
4196 case WLAN_HDD_MONITOR:
4197 /* monitor interface start */
4198 break;
4199 default:
4200 break;
4201 }
4202
4203 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4204 pAdapterNode = pNext;
4205 }
4206
4207 EXIT();
4208
4209 return VOS_STATUS_SUCCESS;
4210}
4211
4212VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4213{
4214 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4215 hdd_adapter_t *pAdapter;
4216 VOS_STATUS status;
4217 v_U32_t roamId;
4218
4219 ENTER();
4220
4221 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4222
4223 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4224 {
4225 pAdapter = pAdapterNode->pAdapter;
4226
4227 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4228 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4229 {
4230 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4231 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4232
4233 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4234 init_completion(&pAdapter->disconnect_comp_var);
4235 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4236 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4237
4238 wait_for_completion_interruptible_timeout(
4239 &pAdapter->disconnect_comp_var,
4240 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4241
4242 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4243 pHddCtx->isAmpAllowed = VOS_FALSE;
4244 sme_RoamConnect(pHddCtx->hHal,
4245 pAdapter->sessionId, &(pWextState->roamProfile),
4246 &roamId);
4247 }
4248
4249 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4250 pAdapterNode = pNext;
4251 }
4252
4253 EXIT();
4254
4255 return VOS_STATUS_SUCCESS;
4256}
4257
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004258void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4259{
4260 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4261 VOS_STATUS status;
4262 hdd_adapter_t *pAdapter;
4263 hdd_station_ctx_t *pHddStaCtx;
4264 hdd_ap_ctx_t *pHddApCtx;
4265 hdd_hostapd_state_t * pHostapdState;
4266 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4267 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4268 const char *p2pMode = "DEV";
4269 const char *ccMode = "Standalone";
4270 int n;
4271
4272 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4273 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4274 {
4275 pAdapter = pAdapterNode->pAdapter;
4276 switch (pAdapter->device_mode) {
4277 case WLAN_HDD_INFRA_STATION:
4278 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4279 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4280 staChannel = pHddStaCtx->conn_info.operationChannel;
4281 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4282 }
4283 break;
4284 case WLAN_HDD_P2P_CLIENT:
4285 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4286 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4287 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4288 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4289 p2pMode = "CLI";
4290 }
4291 break;
4292 case WLAN_HDD_P2P_GO:
4293 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4294 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4295 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4296 p2pChannel = pHddApCtx->operatingChannel;
4297 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4298 }
4299 p2pMode = "GO";
4300 break;
4301 case WLAN_HDD_SOFTAP:
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 apChannel = pHddApCtx->operatingChannel;
4306 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4307 }
4308 break;
4309 default:
4310 break;
4311 }
4312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4313 pAdapterNode = pNext;
4314 }
4315 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4316 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4317 }
4318 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4319 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4320 if (p2pChannel > 0) {
4321 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4322 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4323 }
4324 if (apChannel > 0) {
4325 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4326 apChannel, MAC_ADDR_ARRAY(apBssid));
4327 }
4328
4329 if (p2pChannel > 0 && apChannel > 0) {
4330 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4331 }
4332}
4333
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004334bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004335{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004336 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004337}
4338
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004339/* Once SSR is disabled then it cannot be set. */
4340void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004341{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004342 if (HDD_SSR_DISABLED == isSsrRequired)
4343 return;
4344
Jeff Johnson295189b2012-06-20 16:38:30 -07004345 isSsrRequired = value;
4346}
4347
4348VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4349 hdd_adapter_list_node_t** ppAdapterNode)
4350{
4351 VOS_STATUS status;
4352 spin_lock(&pHddCtx->hddAdapters.lock);
4353 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4354 (hdd_list_node_t**) ppAdapterNode );
4355 spin_unlock(&pHddCtx->hddAdapters.lock);
4356 return status;
4357}
4358
4359VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4360 hdd_adapter_list_node_t* pAdapterNode,
4361 hdd_adapter_list_node_t** pNextAdapterNode)
4362{
4363 VOS_STATUS status;
4364 spin_lock(&pHddCtx->hddAdapters.lock);
4365 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4366 (hdd_list_node_t*) pAdapterNode,
4367 (hdd_list_node_t**)pNextAdapterNode );
4368
4369 spin_unlock(&pHddCtx->hddAdapters.lock);
4370 return status;
4371}
4372
4373VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4374 hdd_adapter_list_node_t* pAdapterNode)
4375{
4376 VOS_STATUS status;
4377 spin_lock(&pHddCtx->hddAdapters.lock);
4378 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4379 &pAdapterNode->node );
4380 spin_unlock(&pHddCtx->hddAdapters.lock);
4381 return status;
4382}
4383
4384VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4385 hdd_adapter_list_node_t** ppAdapterNode)
4386{
4387 VOS_STATUS status;
4388 spin_lock(&pHddCtx->hddAdapters.lock);
4389 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4390 (hdd_list_node_t**) ppAdapterNode );
4391 spin_unlock(&pHddCtx->hddAdapters.lock);
4392 return status;
4393}
4394
4395VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4396 hdd_adapter_list_node_t* pAdapterNode)
4397{
4398 VOS_STATUS status;
4399 spin_lock(&pHddCtx->hddAdapters.lock);
4400 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4401 (hdd_list_node_t*) pAdapterNode );
4402 spin_unlock(&pHddCtx->hddAdapters.lock);
4403 return status;
4404}
4405
4406VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4407 hdd_adapter_list_node_t* pAdapterNode)
4408{
4409 VOS_STATUS status;
4410 spin_lock(&pHddCtx->hddAdapters.lock);
4411 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4412 (hdd_list_node_t*) pAdapterNode );
4413 spin_unlock(&pHddCtx->hddAdapters.lock);
4414 return status;
4415}
4416
4417hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4418 tSirMacAddr macAddr )
4419{
4420 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4421 hdd_adapter_t *pAdapter;
4422 VOS_STATUS status;
4423
4424 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4425
4426 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4427 {
4428 pAdapter = pAdapterNode->pAdapter;
4429
4430 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4431 macAddr, sizeof(tSirMacAddr) ) )
4432 {
4433 return pAdapter;
4434 }
4435 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4436 pAdapterNode = pNext;
4437 }
4438
4439 return NULL;
4440
4441}
4442
4443hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4444{
4445 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4446 hdd_adapter_t *pAdapter;
4447 VOS_STATUS status;
4448
4449 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4450
4451 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4452 {
4453 pAdapter = pAdapterNode->pAdapter;
4454
4455 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4456 IFNAMSIZ ) )
4457 {
4458 return pAdapter;
4459 }
4460 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4461 pAdapterNode = pNext;
4462 }
4463
4464 return NULL;
4465
4466}
4467
4468hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4469{
4470 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4471 hdd_adapter_t *pAdapter;
4472 VOS_STATUS status;
4473
4474 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4475
4476 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4477 {
4478 pAdapter = pAdapterNode->pAdapter;
4479
4480 if( pAdapter && (mode == pAdapter->device_mode) )
4481 {
4482 return pAdapter;
4483 }
4484 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4485 pAdapterNode = pNext;
4486 }
4487
4488 return NULL;
4489
4490}
4491
4492//Remove this function later
4493hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4494{
4495 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4496 hdd_adapter_t *pAdapter;
4497 VOS_STATUS status;
4498
4499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4500
4501 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4502 {
4503 pAdapter = pAdapterNode->pAdapter;
4504
4505 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4506 {
4507 return pAdapter;
4508 }
4509
4510 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4511 pAdapterNode = pNext;
4512 }
4513
4514 return NULL;
4515
4516}
4517
Jeff Johnson295189b2012-06-20 16:38:30 -07004518/**---------------------------------------------------------------------------
4519
4520 \brief hdd_set_monitor_tx_adapter() -
4521
4522 This API initializes the adapter to be used while transmitting on monitor
4523 adapter.
4524
4525 \param - pHddCtx - Pointer to the HDD context.
4526 pAdapter - Adapter that will used for TX. This can be NULL.
4527 \return - None.
4528 --------------------------------------------------------------------------*/
4529void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4530{
4531 hdd_adapter_t *pMonAdapter;
4532
4533 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4534
4535 if( NULL != pMonAdapter )
4536 {
4537 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4538 }
4539}
Jeff Johnson295189b2012-06-20 16:38:30 -07004540/**---------------------------------------------------------------------------
4541
4542 \brief hdd_select_queue() -
4543
4544 This API returns the operating channel of the requested device mode
4545
4546 \param - pHddCtx - Pointer to the HDD context.
4547 - mode - Device mode for which operating channel is required
4548 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4549 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4550 \return - channel number. "0" id the requested device is not found OR it is not connected.
4551 --------------------------------------------------------------------------*/
4552v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4553{
4554 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4555 VOS_STATUS status;
4556 hdd_adapter_t *pAdapter;
4557 v_U8_t operatingChannel = 0;
4558
4559 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4560
4561 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4562 {
4563 pAdapter = pAdapterNode->pAdapter;
4564
4565 if( mode == pAdapter->device_mode )
4566 {
4567 switch(pAdapter->device_mode)
4568 {
4569 case WLAN_HDD_INFRA_STATION:
4570 case WLAN_HDD_P2P_CLIENT:
4571 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4572 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4573 break;
4574 case WLAN_HDD_SOFTAP:
4575 case WLAN_HDD_P2P_GO:
4576 /*softap connection info */
4577 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4578 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4579 break;
4580 default:
4581 break;
4582 }
4583
4584 break; //Found the device of interest. break the loop
4585 }
4586
4587 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4588 pAdapterNode = pNext;
4589 }
4590 return operatingChannel;
4591}
4592
4593#ifdef WLAN_FEATURE_PACKET_FILTERING
4594/**---------------------------------------------------------------------------
4595
4596 \brief hdd_set_multicast_list() -
4597
4598 This used to set the multicast address list.
4599
4600 \param - dev - Pointer to the WLAN device.
4601 - skb - Pointer to OS packet (sk_buff).
4602 \return - success/fail
4603
4604 --------------------------------------------------------------------------*/
4605static void hdd_set_multicast_list(struct net_device *dev)
4606{
4607 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 int mc_count;
4609 int i = 0;
4610 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304611
4612 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 {
4614 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304615 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004616 return;
4617 }
4618
4619 if (dev->flags & IFF_ALLMULTI)
4620 {
4621 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004622 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304623 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004624 }
4625 else
4626 {
4627 mc_count = netdev_mc_count(dev);
4628 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004629 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4631 {
4632 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004633 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304634 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004635 return;
4636 }
4637
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304638 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004639
4640 netdev_for_each_mc_addr(ha, dev) {
4641 if (i == mc_count)
4642 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304643 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4644 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4645 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304647 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 i++;
4649 }
4650 }
4651 return;
4652}
4653#endif
4654
4655/**---------------------------------------------------------------------------
4656
4657 \brief hdd_select_queue() -
4658
4659 This function is registered with the Linux OS for network
4660 core to decide which queue to use first.
4661
4662 \param - dev - Pointer to the WLAN device.
4663 - skb - Pointer to OS packet (sk_buff).
4664 \return - ac, Queue Index/access category corresponding to UP in IP header
4665
4666 --------------------------------------------------------------------------*/
4667v_U16_t hdd_select_queue(struct net_device *dev,
4668 struct sk_buff *skb)
4669{
4670 return hdd_wmm_select_queue(dev, skb);
4671}
4672
4673
4674/**---------------------------------------------------------------------------
4675
4676 \brief hdd_wlan_initial_scan() -
4677
4678 This function triggers the initial scan
4679
4680 \param - pAdapter - Pointer to the HDD adapter.
4681
4682 --------------------------------------------------------------------------*/
4683void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4684{
4685 tCsrScanRequest scanReq;
4686 tCsrChannelInfo channelInfo;
4687 eHalStatus halStatus;
4688 unsigned long scanId;
4689 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4690
4691 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4692 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4693 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4694
4695 if(sme_Is11dSupported(pHddCtx->hHal))
4696 {
4697 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4698 if ( HAL_STATUS_SUCCESS( halStatus ) )
4699 {
4700 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4701 if( !scanReq.ChannelInfo.ChannelList )
4702 {
4703 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4704 vos_mem_free(channelInfo.ChannelList);
4705 return;
4706 }
4707 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4708 channelInfo.numOfChannels);
4709 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4710 vos_mem_free(channelInfo.ChannelList);
4711 }
4712
4713 scanReq.scanType = eSIR_PASSIVE_SCAN;
4714 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4715 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4716 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4717 }
4718 else
4719 {
4720 scanReq.scanType = eSIR_ACTIVE_SCAN;
4721 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4722 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4723 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4724 }
4725
4726 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4727 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4728 {
4729 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4730 __func__, halStatus );
4731 }
4732
4733 if(sme_Is11dSupported(pHddCtx->hHal))
4734 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4735}
4736
4737struct fullPowerContext
4738{
4739 struct completion completion;
4740 unsigned int magic;
4741};
4742#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4743
4744/**---------------------------------------------------------------------------
4745
4746 \brief hdd_full_power_callback() - HDD full power callback function
4747
4748 This is the function invoked by SME to inform the result of a full power
4749 request issued by HDD
4750
4751 \param - callbackcontext - Pointer to cookie
4752 \param - status - result of request
4753
4754 \return - None
4755
4756 --------------------------------------------------------------------------*/
4757static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4758{
4759 struct fullPowerContext *pContext = callbackContext;
4760
4761 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304762 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004763
4764 if (NULL == callbackContext)
4765 {
4766 hddLog(VOS_TRACE_LEVEL_ERROR,
4767 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004768 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 return;
4770 }
4771
4772 /* there is a race condition that exists between this callback function
4773 and the caller since the caller could time out either before or
4774 while this code is executing. we'll assume the timeout hasn't
4775 occurred, but we'll verify that right before we save our work */
4776
4777 if (POWER_CONTEXT_MAGIC != pContext->magic)
4778 {
4779 /* the caller presumably timed out so there is nothing we can do */
4780 hddLog(VOS_TRACE_LEVEL_WARN,
4781 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004782 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004783 return;
4784 }
4785
4786 /* the race is on. caller could have timed out immediately after
4787 we verified the magic, but if so, caller will wait a short time
4788 for us to notify the caller, so the context will stay valid */
4789 complete(&pContext->completion);
4790}
4791
4792/**---------------------------------------------------------------------------
4793
4794 \brief hdd_wlan_exit() - HDD WLAN exit function
4795
4796 This is the driver exit point (invoked during rmmod)
4797
4798 \param - pHddCtx - Pointer to the HDD Context
4799
4800 \return - None
4801
4802 --------------------------------------------------------------------------*/
4803void hdd_wlan_exit(hdd_context_t *pHddCtx)
4804{
4805 eHalStatus halStatus;
4806 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4807 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304808 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004810 struct fullPowerContext powerContext;
4811 long lrc;
4812
4813 ENTER();
4814
Jeff Johnson88ba7742013-02-27 14:36:02 -08004815 if (VOS_FTM_MODE != hdd_get_conparam())
4816 {
4817 // Unloading, restart logic is no more required.
4818 wlan_hdd_restart_deinit(pHddCtx);
4819 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004820
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 {
4825 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4826 WLAN_HDD_INFRA_STATION);
4827 if (pAdapter == NULL)
4828 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4829
4830 if (pAdapter != NULL)
4831 {
4832 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4833 hdd_UnregisterWext(pAdapter->dev);
4834 }
4835 }
4836 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004837
Jeff Johnson295189b2012-06-20 16:38:30 -07004838 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004839 {
4840 wlan_hdd_ftm_close(pHddCtx);
4841 goto free_hdd_ctx;
4842 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 //Stop the Interface TX queue.
4844 //netif_tx_disable(pWlanDev);
4845 //netif_carrier_off(pWlanDev);
4846
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4848 {
4849 pAdapter = hdd_get_adapter(pHddCtx,
4850 WLAN_HDD_SOFTAP);
4851 }
4852 else
4853 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 {
4856 pAdapter = hdd_get_adapter(pHddCtx,
4857 WLAN_HDD_INFRA_STATION);
4858 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 /* DeRegister with platform driver as client for Suspend/Resume */
4861 vosStatus = hddDeregisterPmOps(pHddCtx);
4862 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4863 {
4864 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4865 VOS_ASSERT(0);
4866 }
4867
4868 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4869 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4870 {
4871 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4872 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004873
4874 // Cancel any outstanding scan requests. We are about to close all
4875 // of our adapters, but an adapter structure is what SME passes back
4876 // to our callback function. Hence if there are any outstanding scan
4877 // requests then there is a race condition between when the adapter
4878 // is closed and when the callback is invoked. We try to resolve that
4879 // race condition here by canceling any outstanding scans before we
4880 // close the adapters.
4881 // Note that the scans may be cancelled in an asynchronous manner, so
4882 // ideally there needs to be some kind of synchronization. Rather than
4883 // introduce a new synchronization here, we will utilize the fact that
4884 // we are about to Request Full Power, and since that is synchronized,
4885 // the expectation is that by the time Request Full Power has completed,
4886 // all scans will be cancelled.
4887 hdd_abort_mac_scan( pHddCtx );
4888
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304889 //Stop the timer if already running
4890 if (VOS_TIMER_STATE_RUNNING ==
4891 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4892 {
4893 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4894 }
4895
4896 // Destroy hdd_p2p_go_conn_is_in_progress timer
4897 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4898 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4899 {
4900 hddLog(VOS_TRACE_LEVEL_ERROR,
4901 "%s: Cannot deallocate p2p connection timer", __func__);
4902 }
4903
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004904 //Stop the traffic monitor timer
4905 if ( VOS_TIMER_STATE_RUNNING ==
4906 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4907 {
4908 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4909 }
4910
4911 // Destroy the traffic monitor timer
4912 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4913 &pHddCtx->tx_rx_trafficTmr)))
4914 {
4915 hddLog(VOS_TRACE_LEVEL_ERROR,
4916 "%s: Cannot deallocate Traffic monitor timer", __func__);
4917 }
4918
Jeff Johnson295189b2012-06-20 16:38:30 -07004919 //Disable IMPS/BMPS as we do not want the device to enter any power
4920 //save mode during shutdown
4921 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4922 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4923 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4924
4925 //Ensure that device is in full power as we will touch H/W during vos_Stop
4926 init_completion(&powerContext.completion);
4927 powerContext.magic = POWER_CONTEXT_MAGIC;
4928
4929 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4930 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4931
4932 if (eHAL_STATUS_SUCCESS != halStatus)
4933 {
4934 if (eHAL_STATUS_PMC_PENDING == halStatus)
4935 {
4936 /* request was sent -- wait for the response */
4937 lrc = wait_for_completion_interruptible_timeout(
4938 &powerContext.completion,
4939 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4940 /* either we have a response or we timed out
4941 either way, first invalidate our magic */
4942 powerContext.magic = 0;
4943 if (lrc <= 0)
4944 {
4945 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004946 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 /* there is a race condition such that the callback
4948 function could be executing at the same time we are. of
4949 primary concern is if the callback function had already
4950 verified the "magic" but hasn't yet set the completion
4951 variable. Since the completion variable is on our
4952 stack, we'll delay just a bit to make sure the data is
4953 still valid if that is the case */
4954 msleep(50);
4955 }
4956 }
4957 else
4958 {
4959 hddLog(VOS_TRACE_LEVEL_ERROR,
4960 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004961 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 VOS_ASSERT(0);
4963 /* continue -- need to clean up as much as possible */
4964 }
4965 }
4966
Yue Ma0d4891e2013-08-06 17:01:45 -07004967 hdd_debugfs_exit(pHddCtx);
4968
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 // Unregister the Net Device Notifier
4970 unregister_netdevice_notifier(&hdd_netdev_notifier);
4971
Jeff Johnson295189b2012-06-20 16:38:30 -07004972 hdd_stop_all_adapters( pHddCtx );
4973
Jeff Johnson295189b2012-06-20 16:38:30 -07004974#ifdef WLAN_BTAMP_FEATURE
4975 vosStatus = WLANBAP_Stop(pVosContext);
4976 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4977 {
4978 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4979 "%s: Failed to stop BAP",__func__);
4980 }
4981#endif //WLAN_BTAMP_FEATURE
4982
4983 //Stop all the modules
4984 vosStatus = vos_stop( pVosContext );
4985 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4986 {
4987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4988 "%s: Failed to stop VOSS",__func__);
4989 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4990 }
4991
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 //Assert Deep sleep signal now to put Libra HW in lowest power state
4993 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4994 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4995
4996 //Vote off any PMIC voltage supplies
4997 vos_chipPowerDown(NULL, NULL, NULL);
4998
4999 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5000
Leo Chang59cdc7e2013-07-10 10:08:21 -07005001
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005004
5005 //Close the scheduler before calling vos_close to make sure no thread is
5006 // scheduled after the each module close is called i.e after all the data
5007 // structures are freed.
5008 vosStatus = vos_sched_close( pVosContext );
5009 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5010 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5011 "%s: Failed to close VOSS Scheduler",__func__);
5012 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5013 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005014#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005015#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5016 /* Destroy the wake lock */
5017 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5018#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005019 /* Destroy the wake lock */
5020 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005022
5023 //Close VOSS
5024 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5025 vos_close(pVosContext);
5026
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 //Close Watchdog
5028 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5029 vos_watchdog_close(pVosContext);
5030
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305031 //Clean up HDD Nlink Service
5032 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005033#ifdef WLAN_KD_READY_NOTIFIER
5034 nl_srv_exit(pHddCtx->ptt_pid);
5035#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305036 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005037#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305038
Jeff Johnson295189b2012-06-20 16:38:30 -07005039 /* Cancel the vote for XO Core ON.
5040 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5041 * exited at this point
5042 */
5043 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5044 " when WLAN is turned OFF\n");
5045 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5046 {
5047 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5048 " Not returning failure."
5049 " Power consumed will be high\n");
5050 }
5051
5052 hdd_close_all_adapters( pHddCtx );
5053
5054
5055 //Free up dynamically allocated members inside HDD Adapter
5056 kfree(pHddCtx->cfg_ini);
5057 pHddCtx->cfg_ini= NULL;
5058
5059 /* free the power on lock from platform driver */
5060 if (free_riva_power_on_lock("wlan"))
5061 {
5062 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5063 __func__);
5064 }
5065
Jeff Johnson88ba7742013-02-27 14:36:02 -08005066free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005067 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005068 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005069 if (hdd_is_ssr_required())
5070 {
5071 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005072 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 msleep(5000);
5074 }
5075 hdd_set_ssr_required (VOS_FALSE);
5076}
5077
5078
5079/**---------------------------------------------------------------------------
5080
5081 \brief hdd_update_config_from_nv() - Function to update the contents of
5082 the running configuration with parameters taken from NV storage
5083
5084 \param - pHddCtx - Pointer to the HDD global context
5085
5086 \return - VOS_STATUS_SUCCESS if successful
5087
5088 --------------------------------------------------------------------------*/
5089static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5090{
Jeff Johnson295189b2012-06-20 16:38:30 -07005091 v_BOOL_t itemIsValid = VOS_FALSE;
5092 VOS_STATUS status;
5093 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5094 v_U8_t macLoop;
5095
5096 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5097 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5098 if(status != VOS_STATUS_SUCCESS)
5099 {
5100 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5101 return VOS_STATUS_E_FAILURE;
5102 }
5103
5104 if (itemIsValid == VOS_TRUE)
5105 {
5106 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5107 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5108 VOS_MAX_CONCURRENCY_PERSONA);
5109 if(status != VOS_STATUS_SUCCESS)
5110 {
5111 /* Get MAC from NV fail, not update CFG info
5112 * INI MAC value will be used for MAC setting */
5113 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5114 return VOS_STATUS_E_FAILURE;
5115 }
5116
5117 /* If first MAC is not valid, treat all others are not valid
5118 * Then all MACs will be got from ini file */
5119 if(vos_is_macaddr_zero(&macFromNV[0]))
5120 {
5121 /* MAC address in NV file is not configured yet */
5122 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5123 return VOS_STATUS_E_INVAL;
5124 }
5125
5126 /* Get MAC address from NV, update CFG info */
5127 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5128 {
5129 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5130 {
5131 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5132 /* This MAC is not valid, skip it
5133 * This MAC will be got from ini file */
5134 }
5135 else
5136 {
5137 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5138 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5139 VOS_MAC_ADDR_SIZE);
5140 }
5141 }
5142 }
5143 else
5144 {
5145 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5146 return VOS_STATUS_E_FAILURE;
5147 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005148
Jeff Johnson295189b2012-06-20 16:38:30 -07005149
5150 return VOS_STATUS_SUCCESS;
5151}
5152
5153/**---------------------------------------------------------------------------
5154
5155 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5156
5157 \param - pAdapter - Pointer to the HDD
5158
5159 \return - None
5160
5161 --------------------------------------------------------------------------*/
5162VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5163{
5164 eHalStatus halStatus;
5165 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305166 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005167
Jeff Johnson295189b2012-06-20 16:38:30 -07005168
5169 // Send ready indication to the HDD. This will kick off the MAC
5170 // into a 'running' state and should kick off an initial scan.
5171 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5172 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5173 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305174 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 "code %08d [x%08x]",__func__, halStatus, halStatus );
5176 return VOS_STATUS_E_FAILURE;
5177 }
5178
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305179 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5181 // And RIVA will crash
5182 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5183 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305184 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5185 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5186
5187
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 return VOS_STATUS_SUCCESS;
5189}
5190
Jeff Johnson295189b2012-06-20 16:38:30 -07005191/* wake lock APIs for HDD */
5192void hdd_prevent_suspend(void)
5193{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005194#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005195 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005196#else
5197 wcnss_prevent_suspend();
5198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005199}
5200
5201void hdd_allow_suspend(void)
5202{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005203#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005205#else
5206 wcnss_allow_suspend();
5207#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005208}
5209
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005210void hdd_allow_suspend_timeout(v_U32_t timeout)
5211{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005212#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005213 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005214#else
5215 /* Do nothing as there is no API in wcnss for timeout*/
5216#endif
5217}
5218
Jeff Johnson295189b2012-06-20 16:38:30 -07005219/**---------------------------------------------------------------------------
5220
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005221 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5222 information between Host and Riva
5223
5224 This function gets reported version of FW
5225 It also finds the version of Riva headers used to compile the host
5226 It compares the above two and prints a warning if they are different
5227 It gets the SW and HW version string
5228 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5229 indicating the features they support through a bitmap
5230
5231 \param - pHddCtx - Pointer to HDD context
5232
5233 \return - void
5234
5235 --------------------------------------------------------------------------*/
5236
5237void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5238{
5239
5240 tSirVersionType versionCompiled;
5241 tSirVersionType versionReported;
5242 tSirVersionString versionString;
5243 tANI_U8 fwFeatCapsMsgSupported = 0;
5244 VOS_STATUS vstatus;
5245
5246 /* retrieve and display WCNSS version information */
5247 do {
5248
5249 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5250 &versionCompiled);
5251 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5252 {
5253 hddLog(VOS_TRACE_LEVEL_FATAL,
5254 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005255 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005256 break;
5257 }
5258
5259 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5260 &versionReported);
5261 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5262 {
5263 hddLog(VOS_TRACE_LEVEL_FATAL,
5264 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005265 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005266 break;
5267 }
5268
5269 if ((versionCompiled.major != versionReported.major) ||
5270 (versionCompiled.minor != versionReported.minor) ||
5271 (versionCompiled.version != versionReported.version) ||
5272 (versionCompiled.revision != versionReported.revision))
5273 {
5274 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5275 "Host expected %u.%u.%u.%u\n",
5276 WLAN_MODULE_NAME,
5277 (int)versionReported.major,
5278 (int)versionReported.minor,
5279 (int)versionReported.version,
5280 (int)versionReported.revision,
5281 (int)versionCompiled.major,
5282 (int)versionCompiled.minor,
5283 (int)versionCompiled.version,
5284 (int)versionCompiled.revision);
5285 }
5286 else
5287 {
5288 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5289 WLAN_MODULE_NAME,
5290 (int)versionReported.major,
5291 (int)versionReported.minor,
5292 (int)versionReported.version,
5293 (int)versionReported.revision);
5294 }
5295
5296 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5297 versionString,
5298 sizeof(versionString));
5299 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5300 {
5301 hddLog(VOS_TRACE_LEVEL_FATAL,
5302 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005303 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005304 break;
5305 }
5306
5307 pr_info("%s: WCNSS software version %s\n",
5308 WLAN_MODULE_NAME, versionString);
5309
5310 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5311 versionString,
5312 sizeof(versionString));
5313 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5314 {
5315 hddLog(VOS_TRACE_LEVEL_FATAL,
5316 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005317 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005318 break;
5319 }
5320
5321 pr_info("%s: WCNSS hardware version %s\n",
5322 WLAN_MODULE_NAME, versionString);
5323
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005324 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5325 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005326 send the message only if it the riva is 1.1
5327 minor numbers for different riva branches:
5328 0 -> (1.0)Mainline Build
5329 1 -> (1.1)Mainline Build
5330 2->(1.04) Stability Build
5331 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005332 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005333 ((versionReported.minor>=1) && (versionReported.version>=1)))
5334 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5335 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005336
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005337 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005338 {
5339#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5340 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5341 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5342#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005343 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5344 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5345 {
5346 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5347 }
5348
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005349 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005350 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005351
5352 } while (0);
5353
5354}
5355
5356/**---------------------------------------------------------------------------
5357
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305358 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5359
5360 \param - pHddCtx - Pointer to the hdd context
5361
5362 \return - true if hardware supports 5GHz
5363
5364 --------------------------------------------------------------------------*/
5365static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5366{
5367 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5368 * then hardware support 5Ghz.
5369 */
5370 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5371 {
5372 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5373 return true;
5374 }
5375 else
5376 {
5377 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5378 __func__);
5379 return false;
5380 }
5381}
5382
5383
5384/**---------------------------------------------------------------------------
5385
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 \brief hdd_wlan_startup() - HDD init function
5387
5388 This is the driver startup code executed once a WLAN device has been detected
5389
5390 \param - dev - Pointer to the underlying device
5391
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005392 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005393
5394 --------------------------------------------------------------------------*/
5395
5396int hdd_wlan_startup(struct device *dev )
5397{
5398 VOS_STATUS status;
5399 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005400 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 hdd_context_t *pHddCtx = NULL;
5402 v_CONTEXT_t pVosContext= NULL;
5403#ifdef WLAN_BTAMP_FEATURE
5404 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5405 WLANBAP_ConfigType btAmpConfig;
5406 hdd_config_t *pConfig;
5407#endif
5408 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005410
5411 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 /*
5413 * cfg80211: wiphy allocation
5414 */
5415 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5416
5417 if(wiphy == NULL)
5418 {
5419 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005420 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 }
5422
5423 pHddCtx = wiphy_priv(wiphy);
5424
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 //Initialize the adapter context to zeros.
5426 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5427
Jeff Johnson295189b2012-06-20 16:38:30 -07005428 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 hdd_prevent_suspend();
5430 pHddCtx->isLoadUnloadInProgress = TRUE;
5431
5432 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5433
5434 /*Get vos context here bcoz vos_open requires it*/
5435 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5436
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005437 if(pVosContext == NULL)
5438 {
5439 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5440 goto err_free_hdd_context;
5441 }
5442
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 //Save the Global VOSS context in adapter context for future.
5444 pHddCtx->pvosContext = pVosContext;
5445
5446 //Save the adapter context in global context for future.
5447 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5448
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 pHddCtx->parent_dev = dev;
5450
5451 init_completion(&pHddCtx->full_pwr_comp_var);
5452 init_completion(&pHddCtx->standby_comp_var);
5453 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005454 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005455 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +05305456 init_completion(&pHddCtx->driver_crda_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005457
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305458 spin_lock_init(&pHddCtx->schedScan_lock);
5459
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5461
5462 // Load all config first as TL config is needed during vos_open
5463 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5464 if(pHddCtx->cfg_ini == NULL)
5465 {
5466 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5467 goto err_free_hdd_context;
5468 }
5469
5470 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5471
5472 // Read and parse the qcom_cfg.ini file
5473 status = hdd_parse_config_ini( pHddCtx );
5474 if ( VOS_STATUS_SUCCESS != status )
5475 {
5476 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5477 __func__, WLAN_INI_FILE);
5478 goto err_config;
5479 }
5480
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305481 /* INI has been read, initialise the configuredMcastBcastFilter with
5482 * INI value as this will serve as the default value
5483 */
5484 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5485 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5486 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305487
5488 if (false == hdd_is_5g_supported(pHddCtx))
5489 {
5490 //5Ghz is not supported.
5491 if (1 != pHddCtx->cfg_ini->nBandCapability)
5492 {
5493 hddLog(VOS_TRACE_LEVEL_INFO,
5494 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5495 pHddCtx->cfg_ini->nBandCapability = 1;
5496 }
5497 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305498
5499 /* If SNR Monitoring is enabled, FW has to parse all beacons
5500 * for calcaluting and storing the average SNR, so set Nth beacon
5501 * filter to 1 to enable FW to parse all the beaocons
5502 */
5503 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5504 {
5505 /* The log level is deliberately set to WARN as overriding
5506 * nthBeaconFilter to 1 will increase power cosumption and this
5507 * might just prove helpful to detect the power issue.
5508 */
5509 hddLog(VOS_TRACE_LEVEL_WARN,
5510 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5511 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5512 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 /*
5514 * cfg80211: Initialization and registration ...
5515 */
5516 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5517 {
5518 hddLog(VOS_TRACE_LEVEL_FATAL,
5519 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5520 goto err_wiphy_reg;
5521 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005522
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005523 // Update VOS trace levels based upon the cfg.ini
5524 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5525 pHddCtx->cfg_ini->vosTraceEnableBAP);
5526 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5527 pHddCtx->cfg_ini->vosTraceEnableTL);
5528 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5529 pHddCtx->cfg_ini->vosTraceEnableWDI);
5530 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5531 pHddCtx->cfg_ini->vosTraceEnableHDD);
5532 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5533 pHddCtx->cfg_ini->vosTraceEnableSME);
5534 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5535 pHddCtx->cfg_ini->vosTraceEnablePE);
5536 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5537 pHddCtx->cfg_ini->vosTraceEnableWDA);
5538 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5539 pHddCtx->cfg_ini->vosTraceEnableSYS);
5540 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5541 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005542 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5543 pHddCtx->cfg_ini->vosTraceEnableSAP);
5544 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5545 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005546
Jeff Johnson295189b2012-06-20 16:38:30 -07005547 // Update WDI trace levels based upon the cfg.ini
5548 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5549 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5550 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5551 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5552 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5553 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5554 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5555 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005556
Jeff Johnson88ba7742013-02-27 14:36:02 -08005557 if (VOS_FTM_MODE == hdd_get_conparam())
5558 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005559 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5560 {
5561 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5562 goto err_free_hdd_context;
5563 }
5564 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5565 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005567
Jeff Johnson88ba7742013-02-27 14:36:02 -08005568 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5570 {
5571 status = vos_watchdog_open(pVosContext,
5572 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5573
5574 if(!VOS_IS_STATUS_SUCCESS( status ))
5575 {
5576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005577 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 }
5579 }
5580
5581 pHddCtx->isLogpInProgress = FALSE;
5582 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5583
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5585 if(!VOS_IS_STATUS_SUCCESS(status))
5586 {
5587 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 }
5590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 status = vos_open( &pVosContext, 0);
5592 if ( !VOS_IS_STATUS_SUCCESS( status ))
5593 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005594 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5595 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 }
5597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5599
5600 if ( NULL == pHddCtx->hHal )
5601 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005602 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 goto err_vosclose;
5604 }
5605
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005606 status = vos_preStart( pHddCtx->pvosContext );
5607 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5608 {
5609 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5610 goto err_vosclose;
5611 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005612
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005613 /* Note that the vos_preStart() sequence triggers the cfg download.
5614 The cfg download must occur before we update the SME config
5615 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005616 status = hdd_set_sme_config( pHddCtx );
5617
5618 if ( VOS_STATUS_SUCCESS != status )
5619 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005620 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5621 goto err_vosclose;
5622 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005623
5624 //Initialize the WMM module
5625 status = hdd_wmm_init(pHddCtx);
5626 if (!VOS_IS_STATUS_SUCCESS(status))
5627 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005628 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005629 goto err_vosclose;
5630 }
5631
Jeff Johnson295189b2012-06-20 16:38:30 -07005632 /* In the integrated architecture we update the configuration from
5633 the INI file and from NV before vOSS has been started so that
5634 the final contents are available to send down to the cCPU */
5635
5636 // Apply the cfg.ini to cfg.dat
5637 if (FALSE == hdd_update_config_dat(pHddCtx))
5638 {
5639 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5640 goto err_vosclose;
5641 }
5642
5643 // Apply the NV to cfg.dat
5644 /* Prima Update MAC address only at here */
5645 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5646 {
5647#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5648 /* There was not a valid set of MAC Addresses in NV. See if the
5649 default addresses were modified by the cfg.ini settings. If so,
5650 we'll use them, but if not, we'll autogenerate a set of MAC
5651 addresses based upon the device serial number */
5652
5653 static const v_MACADDR_t default_address =
5654 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5655 unsigned int serialno;
5656 int i;
5657
5658 serialno = wcnss_get_serial_number();
5659 if ((0 != serialno) &&
5660 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5661 sizeof(default_address))))
5662 {
5663 /* cfg.ini has the default address, invoke autogen logic */
5664
5665 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5666 bytes of the serial number that can be used to generate
5667 the other 3 bytes of the MAC address. Mask off all but
5668 the lower 3 bytes (this will also make sure we don't
5669 overflow in the next step) */
5670 serialno &= 0x00FFFFFF;
5671
5672 /* we need a unique address for each session */
5673 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5674
5675 /* autogen all addresses */
5676 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5677 {
5678 /* start with the entire default address */
5679 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5680 /* then replace the lower 3 bytes */
5681 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5682 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5683 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5684
5685 serialno++;
5686 }
5687
5688 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5689 MAC_ADDRESS_STR,
5690 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5691 }
5692 else
5693#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5694 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005695 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005696 "%s: Invalid MAC address in NV, using MAC from ini file "
5697 MAC_ADDRESS_STR, __func__,
5698 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5699 }
5700 }
5701 {
5702 eHalStatus halStatus;
5703 // Set the MAC Address
5704 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5705 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5706 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5707 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5708
5709 if (!HAL_STATUS_SUCCESS( halStatus ))
5710 {
5711 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5712 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005713 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 }
5715 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005716
5717 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5718 Note: Firmware image will be read and downloaded inside vos_start API */
5719 status = vos_start( pHddCtx->pvosContext );
5720 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5721 {
5722 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5723 goto err_vosclose;
5724 }
5725
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005726 /* Exchange capability info between Host and FW and also get versioning info from FW */
5727 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005728
5729 status = hdd_post_voss_start_config( pHddCtx );
5730 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5731 {
5732 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5733 __func__);
5734 goto err_vosstop;
5735 }
5736
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5738 {
5739 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5740 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5741 }
5742 else
5743 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5745 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5746 if (pAdapter != NULL)
5747 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305748 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005749 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305750 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5751 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5752 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005753
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305754 /* Generate the P2P Device Address. This consists of the device's
5755 * primary MAC address with the locally administered bit set.
5756 */
5757 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005758 }
5759 else
5760 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305761 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5762 if (p2p_dev_addr != NULL)
5763 {
5764 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5765 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5766 }
5767 else
5768 {
5769 hddLog(VOS_TRACE_LEVEL_FATAL,
5770 "%s: Failed to allocate mac_address for p2p_device",
5771 __func__);
5772 goto err_close_adapter;
5773 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005775
5776 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5777 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5778 if ( NULL == pP2pAdapter )
5779 {
5780 hddLog(VOS_TRACE_LEVEL_FATAL,
5781 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005782 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005783 goto err_close_adapter;
5784 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005785 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005787
5788 if( pAdapter == NULL )
5789 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005790 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5791 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005793
Jeff Johnson295189b2012-06-20 16:38:30 -07005794#ifdef WLAN_BTAMP_FEATURE
5795 vStatus = WLANBAP_Open(pVosContext);
5796 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5797 {
5798 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5799 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005800 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005801 }
5802
5803 vStatus = BSL_Init(pVosContext);
5804 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5805 {
5806 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5807 "%s: Failed to Init BSL",__func__);
5808 goto err_bap_close;
5809 }
5810 vStatus = WLANBAP_Start(pVosContext);
5811 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5812 {
5813 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5814 "%s: Failed to start TL",__func__);
5815 goto err_bap_close;
5816 }
5817
5818 pConfig = pHddCtx->cfg_ini;
5819 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5820 status = WLANBAP_SetConfig(&btAmpConfig);
5821
5822#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005823
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005824#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5825 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5826 {
5827 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5828 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5829 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5830 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5831 }
5832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005833#ifdef FEATURE_WLAN_SCAN_PNO
5834 /*SME must send channel update configuration to RIVA*/
5835 sme_UpdateChannelConfig(pHddCtx->hHal);
5836#endif
5837
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 /* Register with platform driver as client for Suspend/Resume */
5839 status = hddRegisterPmOps(pHddCtx);
5840 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5841 {
5842 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5843#ifdef WLAN_BTAMP_FEATURE
5844 goto err_bap_stop;
5845#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005846 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005847#endif //WLAN_BTAMP_FEATURE
5848 }
5849
Yue Ma0d4891e2013-08-06 17:01:45 -07005850 /* Open debugfs interface */
5851 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5852 {
5853 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5854 "%s: hdd_debugfs_init failed!", __func__);
5855 goto err_close_debugfs;
5856 }
5857
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 /* Register TM level change handler function to the platform */
5859 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5860 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5861 {
5862 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5863 goto err_unregister_pmops;
5864 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005865
5866 /* register for riva power on lock to platform driver */
5867 if (req_riva_power_on_lock("wlan"))
5868 {
5869 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5870 __func__);
5871 goto err_unregister_pmops;
5872 }
5873
Jeff Johnson295189b2012-06-20 16:38:30 -07005874 // register net device notifier for device change notification
5875 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5876
5877 if(ret < 0)
5878 {
5879 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5880 goto err_free_power_on_lock;
5881 }
5882
5883 //Initialize the nlink service
5884 if(nl_srv_init() != 0)
5885 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 goto err_reg_netdev;
5888 }
5889
5890 //Initialize the BTC service
5891 if(btc_activate_service(pHddCtx) != 0)
5892 {
5893 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5894 goto err_nl_srv;
5895 }
5896
5897#ifdef PTT_SOCK_SVC_ENABLE
5898 //Initialize the PTT service
5899 if(ptt_sock_activate_svc(pHddCtx) != 0)
5900 {
5901 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5902 goto err_nl_srv;
5903 }
5904#endif
5905
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005907 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005909 /* Action frame registered in one adapter which will
5910 * applicable to all interfaces
5911 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005912 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005914
5915 mutex_init(&pHddCtx->sap_lock);
5916
5917 pHddCtx->isLoadUnloadInProgress = FALSE;
5918
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005919#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005920#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5921 /* Initialize the wake lcok */
5922 wake_lock_init(&pHddCtx->rx_wake_lock,
5923 WAKE_LOCK_SUSPEND,
5924 "qcom_rx_wakelock");
5925#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005926 /* Initialize the wake lcok */
5927 wake_lock_init(&pHddCtx->sap_wake_lock,
5928 WAKE_LOCK_SUSPEND,
5929 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005930#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005931
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005932 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5933 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005934
5935 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5936 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305937
Jeff Johnsone7245742012-09-05 17:12:55 -07005938 // Initialize the restart logic
5939 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305940
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305941 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5942 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5943 {
5944 hddLog(VOS_TRACE_LEVEL_ERROR,
5945 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5946 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005947
5948 //Register the traffic monitor timer now
5949 if ( pHddCtx->cfg_ini->dynSplitscan)
5950 {
5951 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
5952 VOS_TIMER_TYPE_SW,
5953 hdd_tx_rx_pkt_cnt_stat_timer_handler,
5954 (void *)pHddCtx);
5955 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 goto success;
5957
5958err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005959#ifdef WLAN_KD_READY_NOTIFIER
5960 nl_srv_exit(pHddCtx->ptt_pid);
5961#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005963#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005964err_reg_netdev:
5965 unregister_netdevice_notifier(&hdd_netdev_notifier);
5966
5967err_free_power_on_lock:
5968 free_riva_power_on_lock("wlan");
5969
5970err_unregister_pmops:
5971 hddDevTmUnregisterNotifyCallback(pHddCtx);
5972 hddDeregisterPmOps(pHddCtx);
5973
Yue Ma0d4891e2013-08-06 17:01:45 -07005974err_close_debugfs:
5975 hdd_debugfs_exit(pHddCtx);
5976
Jeff Johnson295189b2012-06-20 16:38:30 -07005977#ifdef WLAN_BTAMP_FEATURE
5978err_bap_stop:
5979 WLANBAP_Stop(pVosContext);
5980#endif
5981
5982#ifdef WLAN_BTAMP_FEATURE
5983err_bap_close:
5984 WLANBAP_Close(pVosContext);
5985#endif
5986
Jeff Johnson295189b2012-06-20 16:38:30 -07005987err_close_adapter:
5988 hdd_close_all_adapters( pHddCtx );
5989
5990err_vosstop:
5991 vos_stop(pVosContext);
5992
5993err_vosclose:
5994 status = vos_sched_close( pVosContext );
5995 if (!VOS_IS_STATUS_SUCCESS(status)) {
5996 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5997 "%s: Failed to close VOSS Scheduler", __func__);
5998 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5999 }
6000 vos_close(pVosContext );
6001
Jeff Johnson295189b2012-06-20 16:38:30 -07006002err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006003 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006004
6005err_wdclose:
6006 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6007 vos_watchdog_close(pVosContext);
6008
Jeff Johnson295189b2012-06-20 16:38:30 -07006009err_wiphy_reg:
6010 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006011
6012err_config:
6013 kfree(pHddCtx->cfg_ini);
6014 pHddCtx->cfg_ini= NULL;
6015
6016err_free_hdd_context:
6017 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 wiphy_free(wiphy) ;
6019 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 VOS_BUG(1);
6021
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006022 if (hdd_is_ssr_required())
6023 {
6024 /* WDI timeout had happened during load, so SSR is needed here */
6025 subsystem_restart("wcnss");
6026 msleep(5000);
6027 }
6028 hdd_set_ssr_required (VOS_FALSE);
6029
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006030 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006031
6032success:
6033 EXIT();
6034 return 0;
6035}
6036
6037/**---------------------------------------------------------------------------
6038
Jeff Johnson32d95a32012-09-10 13:15:23 -07006039 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006040
Jeff Johnson32d95a32012-09-10 13:15:23 -07006041 This is the driver entry point - called in different timeline depending
6042 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006043
6044 \param - None
6045
6046 \return - 0 for success, non zero for failure
6047
6048 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006049static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006050{
6051 VOS_STATUS status;
6052 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 struct device *dev = NULL;
6054 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006055#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6056 int max_retries = 0;
6057#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006058
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306059#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6060 vos_wconn_trace_init();
6061#endif
6062
Jeff Johnson295189b2012-06-20 16:38:30 -07006063 ENTER();
6064
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006065#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006067#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006068
6069 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6070 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6071
6072 //Power Up Libra WLAN card first if not already powered up
6073 status = vos_chipPowerUp(NULL,NULL,NULL);
6074 if (!VOS_IS_STATUS_SUCCESS(status))
6075 {
6076 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6077 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306078#ifdef WLAN_OPEN_SOURCE
6079 wake_lock_destroy(&wlan_wake_lock);
6080#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006081 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 }
6083
Jeff Johnson295189b2012-06-20 16:38:30 -07006084#ifdef ANI_BUS_TYPE_PCI
6085
6086 dev = wcnss_wlan_get_device();
6087
6088#endif // ANI_BUS_TYPE_PCI
6089
6090#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006091
6092#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6093 /* wait until WCNSS driver downloads NV */
6094 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6095 msleep(1000);
6096 }
6097 if (max_retries >= 5) {
6098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306099#ifdef WLAN_OPEN_SOURCE
6100 wake_lock_destroy(&wlan_wake_lock);
6101#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006102 return -ENODEV;
6103 }
6104#endif
6105
Jeff Johnson295189b2012-06-20 16:38:30 -07006106 dev = wcnss_wlan_get_device();
6107#endif // ANI_BUS_TYPE_PLATFORM
6108
6109
6110 do {
6111 if (NULL == dev) {
6112 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6113 ret_status = -1;
6114 break;
6115 }
6116
6117#ifdef MEMORY_DEBUG
6118 vos_mem_init();
6119#endif
6120
6121#ifdef TIMER_MANAGER
6122 vos_timer_manager_init();
6123#endif
6124
6125 /* Preopen VOSS so that it is ready to start at least SAL */
6126 status = vos_preOpen(&pVosContext);
6127
6128 if (!VOS_IS_STATUS_SUCCESS(status))
6129 {
6130 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6131 ret_status = -1;
6132 break;
6133 }
6134
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006135#ifndef MODULE
6136 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6137 */
6138 hdd_set_conparam((v_UINT_t)con_mode);
6139#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006140
6141 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006142 if (hdd_wlan_startup(dev))
6143 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006145 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006146 vos_preClose( &pVosContext );
6147 ret_status = -1;
6148 break;
6149 }
6150
6151 /* Cancel the vote for XO Core ON
6152 * This is done here for safety purposes in case we re-initialize without turning
6153 * it OFF in any error scenario.
6154 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006155 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006156 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006157 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006158 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6159 {
6160 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6161 " Power consumed will be high\n");
6162 }
6163 } while (0);
6164
6165 if (0 != ret_status)
6166 {
6167 //Assert Deep sleep signal now to put Libra HW in lowest power state
6168 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6169 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6170
6171 //Vote off any PMIC voltage supplies
6172 vos_chipPowerDown(NULL, NULL, NULL);
6173#ifdef TIMER_MANAGER
6174 vos_timer_exit();
6175#endif
6176#ifdef MEMORY_DEBUG
6177 vos_mem_exit();
6178#endif
6179
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006180#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006182#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6184 }
6185 else
6186 {
6187 //Send WLAN UP indication to Nlink Service
6188 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6189
6190 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 }
6192
6193 EXIT();
6194
6195 return ret_status;
6196}
6197
Jeff Johnson32d95a32012-09-10 13:15:23 -07006198/**---------------------------------------------------------------------------
6199
6200 \brief hdd_module_init() - Init Function
6201
6202 This is the driver entry point (invoked when module is loaded using insmod)
6203
6204 \param - None
6205
6206 \return - 0 for success, non zero for failure
6207
6208 --------------------------------------------------------------------------*/
6209#ifdef MODULE
6210static int __init hdd_module_init ( void)
6211{
6212 return hdd_driver_init();
6213}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006214#else /* #ifdef MODULE */
6215static int __init hdd_module_init ( void)
6216{
6217 /* Driver initialization is delayed to fwpath_changed_handler */
6218 return 0;
6219}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006220#endif /* #ifdef MODULE */
6221
Jeff Johnson295189b2012-06-20 16:38:30 -07006222
6223/**---------------------------------------------------------------------------
6224
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006225 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006226
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006227 This is the driver exit point (invoked when module is unloaded using rmmod
6228 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006229
6230 \param - None
6231
6232 \return - None
6233
6234 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006235static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006236{
6237 hdd_context_t *pHddCtx = NULL;
6238 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006239 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006240
6241 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6242
6243 //Get the global vos context
6244 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6245
6246 if(!pVosContext)
6247 {
6248 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6249 goto done;
6250 }
6251
6252 //Get the HDD context.
6253 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6254
6255 if(!pHddCtx)
6256 {
6257 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6258 }
6259 else
6260 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006261 while(isWDresetInProgress()) {
6262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6263 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006264 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006265
6266 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6268 "%s:SSR never completed, fatal error", __func__);
6269 VOS_BUG(0);
6270 }
6271 }
6272
Jeff Johnson295189b2012-06-20 16:38:30 -07006273
6274 pHddCtx->isLoadUnloadInProgress = TRUE;
6275 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6276
6277 //Do all the cleanup before deregistering the driver
6278 hdd_wlan_exit(pHddCtx);
6279 }
6280
Jeff Johnson295189b2012-06-20 16:38:30 -07006281 vos_preClose( &pVosContext );
6282
6283#ifdef TIMER_MANAGER
6284 vos_timer_exit();
6285#endif
6286#ifdef MEMORY_DEBUG
6287 vos_mem_exit();
6288#endif
6289
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306290#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6291 vos_wconn_trace_exit();
6292#endif
6293
Jeff Johnson295189b2012-06-20 16:38:30 -07006294done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006295#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006296 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006297#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006298 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6299}
6300
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006301/**---------------------------------------------------------------------------
6302
6303 \brief hdd_module_exit() - Exit function
6304
6305 This is the driver exit point (invoked when module is unloaded using rmmod)
6306
6307 \param - None
6308
6309 \return - None
6310
6311 --------------------------------------------------------------------------*/
6312static void __exit hdd_module_exit(void)
6313{
6314 hdd_driver_exit();
6315}
6316
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006317#ifdef MODULE
6318static int fwpath_changed_handler(const char *kmessage,
6319 struct kernel_param *kp)
6320{
Jeff Johnson76052702013-04-16 13:55:05 -07006321 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006322}
6323
6324static int con_mode_handler(const char *kmessage,
6325 struct kernel_param *kp)
6326{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006327 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006328}
6329#else /* #ifdef MODULE */
6330/**---------------------------------------------------------------------------
6331
Jeff Johnson76052702013-04-16 13:55:05 -07006332 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006333
Jeff Johnson76052702013-04-16 13:55:05 -07006334 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006335 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006336 - invoked when module parameter fwpath is modified from userspace to signal
6337 initializing the WLAN driver or when con_mode is modified from userspace
6338 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006339
6340 \return - 0 for success, non zero for failure
6341
6342 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006343static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006344{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006345 int ret_status;
6346
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006347 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006348 ret_status = hdd_driver_init();
6349 wlan_hdd_inited = ret_status ? 0 : 1;
6350 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006351 }
6352
6353 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006354
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006355 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006356
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006357 ret_status = hdd_driver_init();
6358 wlan_hdd_inited = ret_status ? 0 : 1;
6359 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006360}
6361
Jeff Johnson295189b2012-06-20 16:38:30 -07006362/**---------------------------------------------------------------------------
6363
Jeff Johnson76052702013-04-16 13:55:05 -07006364 \brief fwpath_changed_handler() - Handler Function
6365
6366 Handle changes to the fwpath parameter
6367
6368 \return - 0 for success, non zero for failure
6369
6370 --------------------------------------------------------------------------*/
6371static int fwpath_changed_handler(const char *kmessage,
6372 struct kernel_param *kp)
6373{
6374 int ret;
6375
6376 ret = param_set_copystring(kmessage, kp);
6377 if (0 == ret)
6378 ret = kickstart_driver();
6379 return ret;
6380}
6381
6382/**---------------------------------------------------------------------------
6383
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006384 \brief con_mode_handler() -
6385
6386 Handler function for module param con_mode when it is changed by userspace
6387 Dynamically linked - do nothing
6388 Statically linked - exit and init driver, as in rmmod and insmod
6389
Jeff Johnson76052702013-04-16 13:55:05 -07006390 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006391
Jeff Johnson76052702013-04-16 13:55:05 -07006392 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006393
6394 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006395static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006396{
Jeff Johnson76052702013-04-16 13:55:05 -07006397 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006398
Jeff Johnson76052702013-04-16 13:55:05 -07006399 ret = param_set_int(kmessage, kp);
6400 if (0 == ret)
6401 ret = kickstart_driver();
6402 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006403}
6404#endif /* #ifdef MODULE */
6405
6406/**---------------------------------------------------------------------------
6407
Jeff Johnson295189b2012-06-20 16:38:30 -07006408 \brief hdd_get_conparam() -
6409
6410 This is the driver exit point (invoked when module is unloaded using rmmod)
6411
6412 \param - None
6413
6414 \return - tVOS_CON_MODE
6415
6416 --------------------------------------------------------------------------*/
6417tVOS_CON_MODE hdd_get_conparam ( void )
6418{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006419#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006420 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006421#else
6422 return (tVOS_CON_MODE)curr_con_mode;
6423#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006424}
6425void hdd_set_conparam ( v_UINT_t newParam )
6426{
6427 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006428#ifndef MODULE
6429 curr_con_mode = con_mode;
6430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006431}
6432/**---------------------------------------------------------------------------
6433
6434 \brief hdd_softap_sta_deauth() - function
6435
6436 This to take counter measure to handle deauth req from HDD
6437
6438 \param - pAdapter - Pointer to the HDD
6439
6440 \param - enable - boolean value
6441
6442 \return - None
6443
6444 --------------------------------------------------------------------------*/
6445
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006446VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006447{
Jeff Johnson295189b2012-06-20 16:38:30 -07006448 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006449 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006450
6451 ENTER();
6452
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006453 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6454 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006455
6456 //Ignore request to deauth bcmc station
6457 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006458 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006460 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006461
6462 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006463 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006464}
6465
6466/**---------------------------------------------------------------------------
6467
6468 \brief hdd_softap_sta_disassoc() - function
6469
6470 This to take counter measure to handle deauth req from HDD
6471
6472 \param - pAdapter - Pointer to the HDD
6473
6474 \param - enable - boolean value
6475
6476 \return - None
6477
6478 --------------------------------------------------------------------------*/
6479
6480void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6481{
6482 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6483
6484 ENTER();
6485
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306486 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006487
6488 //Ignore request to disassoc bcmc station
6489 if( pDestMacAddress[0] & 0x1 )
6490 return;
6491
6492 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6493}
6494
6495void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6496{
6497 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6498
6499 ENTER();
6500
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306501 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006502
6503 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6504}
6505
Jeff Johnson295189b2012-06-20 16:38:30 -07006506/**---------------------------------------------------------------------------
6507 *
6508 * \brief hdd_get__concurrency_mode() -
6509 *
6510 *
6511 * \param - None
6512 *
6513 * \return - CONCURRENCY MODE
6514 *
6515 * --------------------------------------------------------------------------*/
6516tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6517{
6518 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6519 hdd_context_t *pHddCtx;
6520
6521 if (NULL != pVosContext)
6522 {
6523 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6524 if (NULL != pHddCtx)
6525 {
6526 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6527 }
6528 }
6529
6530 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006531 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 return VOS_STA;
6533}
6534
6535/* Decide whether to allow/not the apps power collapse.
6536 * Allow apps power collapse if we are in connected state.
6537 * if not, allow only if we are in IMPS */
6538v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6539{
6540 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006541 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006542 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006543 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6544 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6545 hdd_adapter_t *pAdapter = NULL;
6546 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006547 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006548
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6550 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006551
Yathish9f22e662012-12-10 14:21:35 -08006552 concurrent_state = hdd_get_concurrency_mode();
6553
6554#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6555 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6556 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6557 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6558 return TRUE;
6559#endif
6560
Jeff Johnson295189b2012-06-20 16:38:30 -07006561 /*loop through all adapters. TBD fix for Concurrency */
6562 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6563 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6564 {
6565 pAdapter = pAdapterNode->pAdapter;
6566 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6567 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6568 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006569 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006570 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006571 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006572 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6573 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006574 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006575 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006576 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6577 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006578 return FALSE;
6579 }
6580 }
6581 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6582 pAdapterNode = pNext;
6583 }
6584 return TRUE;
6585}
6586
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006587/* Decides whether to send suspend notification to Riva
6588 * if any adapter is in BMPS; then it is required */
6589v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6590{
6591 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6592 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6593
6594 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6595 {
6596 return TRUE;
6597 }
6598 return FALSE;
6599}
6600
Jeff Johnson295189b2012-06-20 16:38:30 -07006601void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6602{
6603 switch(mode)
6604 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006605 case VOS_STA_MODE:
6606 case VOS_P2P_CLIENT_MODE:
6607 case VOS_P2P_GO_MODE:
6608 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006609 pHddCtx->concurrency_mode |= (1 << mode);
6610 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006611 break;
6612 default:
6613 break;
6614
6615 }
6616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6617 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6618}
6619
6620
6621void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6622{
6623 switch(mode)
6624 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006625 case VOS_STA_MODE:
6626 case VOS_P2P_CLIENT_MODE:
6627 case VOS_P2P_GO_MODE:
6628 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006629 pHddCtx->no_of_sessions[mode]--;
6630 if (!(pHddCtx->no_of_sessions[mode]))
6631 pHddCtx->concurrency_mode &= (~(1 << mode));
6632 break;
6633 default:
6634 break;
6635 }
6636 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6637 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6638}
6639
Jeff Johnsone7245742012-09-05 17:12:55 -07006640/**---------------------------------------------------------------------------
6641 *
6642 * \brief wlan_hdd_restart_init
6643 *
6644 * This function initalizes restart timer/flag. An internal function.
6645 *
6646 * \param - pHddCtx
6647 *
6648 * \return - None
6649 *
6650 * --------------------------------------------------------------------------*/
6651
6652static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6653{
6654 /* Initialize */
6655 pHddCtx->hdd_restart_retries = 0;
6656 atomic_set(&pHddCtx->isRestartInProgress, 0);
6657 vos_timer_init(&pHddCtx->hdd_restart_timer,
6658 VOS_TIMER_TYPE_SW,
6659 wlan_hdd_restart_timer_cb,
6660 pHddCtx);
6661}
6662/**---------------------------------------------------------------------------
6663 *
6664 * \brief wlan_hdd_restart_deinit
6665 *
6666 * This function cleans up the resources used. An internal function.
6667 *
6668 * \param - pHddCtx
6669 *
6670 * \return - None
6671 *
6672 * --------------------------------------------------------------------------*/
6673
6674static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6675{
6676
6677 VOS_STATUS vos_status;
6678 /* Block any further calls */
6679 atomic_set(&pHddCtx->isRestartInProgress, 1);
6680 /* Cleanup */
6681 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6682 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006683 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006684 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6685 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006686 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006687
6688}
6689
6690/**---------------------------------------------------------------------------
6691 *
6692 * \brief wlan_hdd_framework_restart
6693 *
6694 * This function uses a cfg80211 API to start a framework initiated WLAN
6695 * driver module unload/load.
6696 *
6697 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6698 *
6699 *
6700 * \param - pHddCtx
6701 *
6702 * \return - VOS_STATUS_SUCCESS: Success
6703 * VOS_STATUS_E_EMPTY: Adapter is Empty
6704 * VOS_STATUS_E_NOMEM: No memory
6705
6706 * --------------------------------------------------------------------------*/
6707
6708static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6709{
6710 VOS_STATUS status = VOS_STATUS_SUCCESS;
6711 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006712 int len = (sizeof (struct ieee80211_mgmt));
6713 struct ieee80211_mgmt *mgmt = NULL;
6714
6715 /* Prepare the DEAUTH managment frame with reason code */
6716 mgmt = kzalloc(len, GFP_KERNEL);
6717 if(mgmt == NULL)
6718 {
6719 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6720 "%s: memory allocation failed (%d bytes)", __func__, len);
6721 return VOS_STATUS_E_NOMEM;
6722 }
6723 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006724
6725 /* Iterate over all adapters/devices */
6726 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6727 do
6728 {
6729 if( (status == VOS_STATUS_SUCCESS) &&
6730 pAdapterNode &&
6731 pAdapterNode->pAdapter)
6732 {
6733 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6734 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6735 pAdapterNode->pAdapter->dev->name,
6736 pAdapterNode->pAdapter->device_mode,
6737 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006738 /*
6739 * CFG80211 event to restart the driver
6740 *
6741 * 'cfg80211_send_unprot_deauth' sends a
6742 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6743 * of SME(Linux Kernel) state machine.
6744 *
6745 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6746 * the driver.
6747 *
6748 */
6749
6750 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006751 }
6752 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6753 pAdapterNode = pNext;
6754 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6755
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006756
6757 /* Free the allocated management frame */
6758 kfree(mgmt);
6759
Jeff Johnsone7245742012-09-05 17:12:55 -07006760 /* Retry until we unload or reach max count */
6761 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6762 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6763
6764 return status;
6765
6766}
6767/**---------------------------------------------------------------------------
6768 *
6769 * \brief wlan_hdd_restart_timer_cb
6770 *
6771 * Restart timer callback. An internal function.
6772 *
6773 * \param - User data:
6774 *
6775 * \return - None
6776 *
6777 * --------------------------------------------------------------------------*/
6778
6779void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6780{
6781 hdd_context_t *pHddCtx = usrDataForCallback;
6782 wlan_hdd_framework_restart(pHddCtx);
6783 return;
6784
6785}
6786
6787
6788/**---------------------------------------------------------------------------
6789 *
6790 * \brief wlan_hdd_restart_driver
6791 *
6792 * This function sends an event to supplicant to restart the WLAN driver.
6793 *
6794 * This function is called from vos_wlanRestart.
6795 *
6796 * \param - pHddCtx
6797 *
6798 * \return - VOS_STATUS_SUCCESS: Success
6799 * VOS_STATUS_E_EMPTY: Adapter is Empty
6800 * VOS_STATUS_E_ALREADY: Request already in progress
6801
6802 * --------------------------------------------------------------------------*/
6803VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6804{
6805 VOS_STATUS status = VOS_STATUS_SUCCESS;
6806
6807 /* A tight check to make sure reentrancy */
6808 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6809 {
6810 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6811 "%s: WLAN restart is already in progress", __func__);
6812
6813 return VOS_STATUS_E_ALREADY;
6814 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006815 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006816#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006817 wcnss_reset_intr();
6818#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006819
Jeff Johnsone7245742012-09-05 17:12:55 -07006820 return status;
6821}
6822
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006823/*
6824 * API to find if there is any STA or P2P-Client is connected
6825 */
6826VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6827{
6828 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6829}
Jeff Johnsone7245742012-09-05 17:12:55 -07006830
Jeff Johnson295189b2012-06-20 16:38:30 -07006831//Register the module init/exit functions
6832module_init(hdd_module_init);
6833module_exit(hdd_module_exit);
6834
6835MODULE_LICENSE("Dual BSD/GPL");
6836MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6837MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6838
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006839module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6840 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006841
Jeff Johnson76052702013-04-16 13:55:05 -07006842module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006843 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);