blob: 80af3ce6c7ded8c22ab6439a9ce74ea2afe4e0c0 [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 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002049 else {
2050 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2051 __func__, command);
2052 }
2053
Jeff Johnson295189b2012-06-20 16:38:30 -07002054 }
2055exit:
2056 if (command)
2057 {
2058 kfree(command);
2059 }
2060 return ret;
2061}
2062
Srinivas Girigowdade697412013-02-14 16:31:48 -08002063#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2064void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2065{
2066 eCsrBand band = -1;
2067 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2068 switch (band)
2069 {
2070 case eCSR_BAND_ALL:
2071 *pBand = WLAN_HDD_UI_BAND_AUTO;
2072 break;
2073
2074 case eCSR_BAND_24:
2075 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2076 break;
2077
2078 case eCSR_BAND_5G:
2079 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2080 break;
2081
2082 default:
2083 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2084 *pBand = -1;
2085 break;
2086 }
2087}
2088
2089/**---------------------------------------------------------------------------
2090
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002091 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2092
2093 This function parses the send action frame data passed in the format
2094 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2095
Srinivas Girigowda56076852013-08-20 14:00:50 -07002096 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002097 \param - pTargetApBssid Pointer to target Ap bssid
2098 \param - pChannel Pointer to the Target AP channel
2099 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2100 \param - pBuf Pointer to data
2101 \param - pBufLen Pointer to data length
2102
2103 \return - 0 for success non-zero for failure
2104
2105 --------------------------------------------------------------------------*/
2106VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2107 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2108{
2109 tANI_U8 *inPtr = pValue;
2110 tANI_U8 *dataEnd;
2111 int tempInt;
2112 int j = 0;
2113 int i = 0;
2114 int v = 0;
2115 tANI_U8 tempBuf[32];
2116 tANI_U8 tempByte = 0;
2117
2118 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2119 /*no argument after the command*/
2120 if (NULL == inPtr)
2121 {
2122 return -EINVAL;
2123 }
2124
2125 /*no space after the command*/
2126 else if (SPACE_ASCII_VALUE != *inPtr)
2127 {
2128 return -EINVAL;
2129 }
2130
2131 /*removing empty spaces*/
2132 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2133
2134 /*no argument followed by spaces*/
2135 if ('\0' == *inPtr)
2136 {
2137 return -EINVAL;
2138 }
2139
2140 /*getting the first argument ie the target AP bssid */
2141 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2142 {
2143 return -EINVAL;
2144 }
2145 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2146 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2147 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2148
2149 /* point to the next argument */
2150 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2151 /*no argument after the command*/
2152 if (NULL == inPtr) return -EINVAL;
2153
2154 /*removing empty spaces*/
2155 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2156
2157 /*no argument followed by spaces*/
2158 if ('\0' == *inPtr)
2159 {
2160 return -EINVAL;
2161 }
2162
2163 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002164 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002165 v = kstrtos32(tempBuf, 10, &tempInt);
2166 if ( v < 0) return -EINVAL;
2167
2168 *pChannel = tempInt;
2169
2170 /* point to the next argument */
2171 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2172 /*no argument after the command*/
2173 if (NULL == inPtr) return -EINVAL;
2174 /*removing empty spaces*/
2175 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2176
2177 /*no argument followed by spaces*/
2178 if ('\0' == *inPtr)
2179 {
2180 return -EINVAL;
2181 }
2182
2183 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002184 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002185 v = kstrtos32(tempBuf, 10, &tempInt);
2186 if ( v < 0) return -EINVAL;
2187
2188 *pDwellTime = tempInt;
2189
2190 /* point to the next argument */
2191 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2192 /*no argument after the command*/
2193 if (NULL == inPtr) return -EINVAL;
2194 /*removing empty spaces*/
2195 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2196
2197 /*no argument followed by spaces*/
2198 if ('\0' == *inPtr)
2199 {
2200 return -EINVAL;
2201 }
2202
2203 /* find the length of data */
2204 dataEnd = inPtr;
2205 while(('\0' != *dataEnd) )
2206 {
2207 dataEnd++;
2208 ++(*pBufLen);
2209 }
2210 if ( *pBufLen <= 0) return -EINVAL;
2211
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002212 /* Allocate the number of bytes based on the number of input characters
2213 whether it is even or odd.
2214 if the number of input characters are even, then we need N/2 byte.
2215 if the number of input characters are odd, then we need do (N+1)/2 to
2216 compensate rounding off.
2217 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2218 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2219 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002220 if (NULL == *pBuf)
2221 {
2222 hddLog(VOS_TRACE_LEVEL_FATAL,
2223 "%s: vos_mem_alloc failed ", __func__);
2224 return -EINVAL;
2225 }
2226
2227 /* the buffer received from the upper layer is character buffer,
2228 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2229 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2230 and f0 in 3rd location */
2231 for (i = 0, j = 0; j < *pBufLen; j += 2)
2232 {
2233 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2234 (*pBuf)[i++] = tempByte;
2235 }
2236 *pBufLen = i;
2237 return VOS_STATUS_SUCCESS;
2238}
2239
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002240/**---------------------------------------------------------------------------
2241
Srinivas Girigowdade697412013-02-14 16:31:48 -08002242 \brief hdd_parse_channellist() - HDD Parse channel list
2243
2244 This function parses the channel list passed in the format
2245 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002246 if the Number of channels (N) does not match with the actual number of channels passed
2247 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2248 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2249 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2250 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002251
2252 \param - pValue Pointer to input channel list
2253 \param - ChannelList Pointer to local output array to record channel list
2254 \param - pNumChannels Pointer to number of roam scan channels
2255
2256 \return - 0 for success non-zero for failure
2257
2258 --------------------------------------------------------------------------*/
2259VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2260{
2261 tANI_U8 *inPtr = pValue;
2262 int tempInt;
2263 int j = 0;
2264 int v = 0;
2265 char buf[32];
2266
2267 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2268 /*no argument after the command*/
2269 if (NULL == inPtr)
2270 {
2271 return -EINVAL;
2272 }
2273
2274 /*no space after the command*/
2275 else if (SPACE_ASCII_VALUE != *inPtr)
2276 {
2277 return -EINVAL;
2278 }
2279
2280 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002281 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002282
2283 /*no argument followed by spaces*/
2284 if ('\0' == *inPtr)
2285 {
2286 return -EINVAL;
2287 }
2288
2289 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002290 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002291 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002292 if ((v < 0) ||
2293 (tempInt <= 0) ||
2294 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2295 {
2296 return -EINVAL;
2297 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002298
2299 *pNumChannels = tempInt;
2300
2301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2302 "Number of channels are: %d", *pNumChannels);
2303
2304 for (j = 0; j < (*pNumChannels); j++)
2305 {
2306 /*inPtr pointing to the beginning of first space after number of channels*/
2307 inPtr = strpbrk( inPtr, " " );
2308 /*no channel list after the number of channels argument*/
2309 if (NULL == inPtr)
2310 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002311 if (0 != j)
2312 {
2313 *pNumChannels = j;
2314 return VOS_STATUS_SUCCESS;
2315 }
2316 else
2317 {
2318 return -EINVAL;
2319 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002320 }
2321
2322 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002323 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002324
2325 /*no channel list after the number of channels argument and spaces*/
2326 if ( '\0' == *inPtr )
2327 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002328 if (0 != j)
2329 {
2330 *pNumChannels = j;
2331 return VOS_STATUS_SUCCESS;
2332 }
2333 else
2334 {
2335 return -EINVAL;
2336 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337 }
2338
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002339 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002340 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002341 if ((v < 0) ||
2342 (tempInt <= 0) ||
2343 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2344 {
2345 return -EINVAL;
2346 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002347 pChannelList[j] = tempInt;
2348
2349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2350 "Channel %d added to preferred channel list",
2351 pChannelList[j] );
2352 }
2353
Srinivas Girigowdade697412013-02-14 16:31:48 -08002354 return VOS_STATUS_SUCCESS;
2355}
2356
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002357
2358/**---------------------------------------------------------------------------
2359
2360 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2361
2362 This function parses the reasoc command data passed in the format
2363 REASSOC<space><bssid><space><channel>
2364
Srinivas Girigowda56076852013-08-20 14:00:50 -07002365 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002366 \param - pTargetApBssid Pointer to target Ap bssid
2367 \param - pChannel Pointer to the Target AP channel
2368
2369 \return - 0 for success non-zero for failure
2370
2371 --------------------------------------------------------------------------*/
2372VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2373{
2374 tANI_U8 *inPtr = pValue;
2375 int tempInt;
2376 int v = 0;
2377 tANI_U8 tempBuf[32];
2378
2379 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2380 /*no argument after the command*/
2381 if (NULL == inPtr)
2382 {
2383 return -EINVAL;
2384 }
2385
2386 /*no space after the command*/
2387 else if (SPACE_ASCII_VALUE != *inPtr)
2388 {
2389 return -EINVAL;
2390 }
2391
2392 /*removing empty spaces*/
2393 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2394
2395 /*no argument followed by spaces*/
2396 if ('\0' == *inPtr)
2397 {
2398 return -EINVAL;
2399 }
2400
2401 /*getting the first argument ie the target AP bssid */
2402 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2403 {
2404 return -EINVAL;
2405 }
2406 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2407 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2408 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2409
2410 /* point to the next argument */
2411 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2412 /*no argument after the command*/
2413 if (NULL == inPtr) return -EINVAL;
2414
2415 /*removing empty spaces*/
2416 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2417
2418 /*no argument followed by spaces*/
2419 if ('\0' == *inPtr)
2420 {
2421 return -EINVAL;
2422 }
2423
2424 /*getting the next argument ie the channel number */
2425 sscanf(inPtr, "%s ", tempBuf);
2426 v = kstrtos32(tempBuf, 10, &tempInt);
2427 if ( v < 0) return -EINVAL;
2428
2429 *pChannel = tempInt;
2430 return VOS_STATUS_SUCCESS;
2431}
2432
2433#endif
2434
Jeff Johnson295189b2012-06-20 16:38:30 -07002435/**---------------------------------------------------------------------------
2436
2437 \brief hdd_open() - HDD Open function
2438
2439 This is called in response to ifconfig up
2440
2441 \param - dev Pointer to net_device structure
2442
2443 \return - 0 for success non-zero for failure
2444
2445 --------------------------------------------------------------------------*/
2446int hdd_open (struct net_device *dev)
2447{
2448 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2449 hdd_context_t *pHddCtx;
2450 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2451 VOS_STATUS status;
2452 v_BOOL_t in_standby = TRUE;
2453
2454 if (NULL == pAdapter)
2455 {
2456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002457 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002458 return -ENODEV;
2459 }
2460
2461 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2462 if (NULL == pHddCtx)
2463 {
2464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002465 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002466 return -ENODEV;
2467 }
2468
2469 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2470 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2471 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002472 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2473 {
2474 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302475 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002476 in_standby = FALSE;
2477 break;
2478 }
2479 else
2480 {
2481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2482 pAdapterNode = pNext;
2483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002484 }
2485
2486 if (TRUE == in_standby)
2487 {
2488 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2489 {
2490 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2491 "wlan out of power save", __func__);
2492 return -EINVAL;
2493 }
2494 }
2495
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002496 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2498 {
2499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002500 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002501 /* Enable TX queues only when we are connected */
2502 netif_tx_start_all_queues(dev);
2503 }
2504
2505 return 0;
2506}
2507
2508int hdd_mon_open (struct net_device *dev)
2509{
2510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2511
2512 if(pAdapter == NULL) {
2513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002514 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002515 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 }
2517
2518 netif_start_queue(dev);
2519
2520 return 0;
2521}
2522/**---------------------------------------------------------------------------
2523
2524 \brief hdd_stop() - HDD stop function
2525
2526 This is called in response to ifconfig down
2527
2528 \param - dev Pointer to net_device structure
2529
2530 \return - 0 for success non-zero for failure
2531
2532 --------------------------------------------------------------------------*/
2533
2534int hdd_stop (struct net_device *dev)
2535{
2536 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2537 hdd_context_t *pHddCtx;
2538 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2539 VOS_STATUS status;
2540 v_BOOL_t enter_standby = TRUE;
2541
2542 ENTER();
2543
2544 if (NULL == pAdapter)
2545 {
2546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002547 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002548 return -ENODEV;
2549 }
2550
2551 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2552 if (NULL == pHddCtx)
2553 {
2554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002555 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002556 return -ENODEV;
2557 }
2558
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002559 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2561 netif_tx_disable(pAdapter->dev);
2562 netif_carrier_off(pAdapter->dev);
2563
2564
2565 /* SoftAP ifaces should never go in power save mode
2566 making sure same here. */
2567 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2568 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002569 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 )
2571 {
2572 /* SoftAP mode, so return from here */
2573 EXIT();
2574 return 0;
2575 }
2576
2577 /* Find if any iface is up then
2578 if any iface is up then can't put device to sleep/ power save mode. */
2579 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2580 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2581 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002582 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2583 {
2584 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302585 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002586 enter_standby = FALSE;
2587 break;
2588 }
2589 else
2590 {
2591 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2592 pAdapterNode = pNext;
2593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002594 }
2595
2596 if (TRUE == enter_standby)
2597 {
2598 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2599 "entering standby", __func__);
2600 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2601 {
2602 /*log and return success*/
2603 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2604 "wlan in power save", __func__);
2605 }
2606 }
2607
2608 EXIT();
2609 return 0;
2610}
2611
2612/**---------------------------------------------------------------------------
2613
2614 \brief hdd_uninit() - HDD uninit function
2615
2616 This is called during the netdev unregister to uninitialize all data
2617associated with the device
2618
2619 \param - dev Pointer to net_device structure
2620
2621 \return - void
2622
2623 --------------------------------------------------------------------------*/
2624static void hdd_uninit (struct net_device *dev)
2625{
2626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2627
2628 ENTER();
2629
2630 do
2631 {
2632 if (NULL == pAdapter)
2633 {
2634 hddLog(VOS_TRACE_LEVEL_FATAL,
2635 "%s: NULL pAdapter", __func__);
2636 break;
2637 }
2638
2639 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2640 {
2641 hddLog(VOS_TRACE_LEVEL_FATAL,
2642 "%s: Invalid magic", __func__);
2643 break;
2644 }
2645
2646 if (NULL == pAdapter->pHddCtx)
2647 {
2648 hddLog(VOS_TRACE_LEVEL_FATAL,
2649 "%s: NULL pHddCtx", __func__);
2650 break;
2651 }
2652
2653 if (dev != pAdapter->dev)
2654 {
2655 hddLog(VOS_TRACE_LEVEL_FATAL,
2656 "%s: Invalid device reference", __func__);
2657 /* we haven't validated all cases so let this go for now */
2658 }
2659
2660 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2661
2662 /* after uninit our adapter structure will no longer be valid */
2663 pAdapter->dev = NULL;
2664 pAdapter->magic = 0;
2665 } while (0);
2666
2667 EXIT();
2668}
2669
2670/**---------------------------------------------------------------------------
2671
2672 \brief hdd_release_firmware() -
2673
2674 This function calls the release firmware API to free the firmware buffer.
2675
2676 \param - pFileName Pointer to the File Name.
2677 pCtx - Pointer to the adapter .
2678
2679
2680 \return - 0 for success, non zero for failure
2681
2682 --------------------------------------------------------------------------*/
2683
2684VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2685{
2686 VOS_STATUS status = VOS_STATUS_SUCCESS;
2687 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2688 ENTER();
2689
2690
2691 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2692
2693 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2694
2695 if(pHddCtx->fw) {
2696 release_firmware(pHddCtx->fw);
2697 pHddCtx->fw = NULL;
2698 }
2699 else
2700 status = VOS_STATUS_E_FAILURE;
2701 }
2702 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2703 if(pHddCtx->nv) {
2704 release_firmware(pHddCtx->nv);
2705 pHddCtx->nv = NULL;
2706 }
2707 else
2708 status = VOS_STATUS_E_FAILURE;
2709
2710 }
2711
2712 EXIT();
2713 return status;
2714}
2715
2716/**---------------------------------------------------------------------------
2717
2718 \brief hdd_request_firmware() -
2719
2720 This function reads the firmware file using the request firmware
2721 API and returns the the firmware data and the firmware file size.
2722
2723 \param - pfileName - Pointer to the file name.
2724 - pCtx - Pointer to the adapter .
2725 - ppfw_data - Pointer to the pointer of the firmware data.
2726 - pSize - Pointer to the file size.
2727
2728 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2729
2730 --------------------------------------------------------------------------*/
2731
2732
2733VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2734{
2735 int status;
2736 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2737 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2738 ENTER();
2739
2740 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2741
2742 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2743
2744 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2745 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2746 __func__, pfileName);
2747 retval = VOS_STATUS_E_FAILURE;
2748 }
2749
2750 else {
2751 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2752 *pSize = pHddCtx->fw->size;
2753 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2754 __func__, *pSize);
2755 }
2756 }
2757 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2758
2759 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2760
2761 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2762 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2763 __func__, pfileName);
2764 retval = VOS_STATUS_E_FAILURE;
2765 }
2766
2767 else {
2768 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2769 *pSize = pHddCtx->nv->size;
2770 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2771 __func__, *pSize);
2772 }
2773 }
2774
2775 EXIT();
2776 return retval;
2777}
2778/**---------------------------------------------------------------------------
2779 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2780
2781 This is the function invoked by SME to inform the result of a full power
2782 request issued by HDD
2783
2784 \param - callbackcontext - Pointer to cookie
2785 status - result of request
2786
2787 \return - None
2788
2789--------------------------------------------------------------------------*/
2790void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2791{
2792 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2793
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002794 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002795 if(&pHddCtx->full_pwr_comp_var)
2796 {
2797 complete(&pHddCtx->full_pwr_comp_var);
2798 }
2799}
2800
2801/**---------------------------------------------------------------------------
2802
2803 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2804
2805 This is the function invoked by SME to inform the result of BMPS
2806 request issued by HDD
2807
2808 \param - callbackcontext - Pointer to cookie
2809 status - result of request
2810
2811 \return - None
2812
2813--------------------------------------------------------------------------*/
2814void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2815{
2816
2817 struct completion *completion_var = (struct completion*) callbackContext;
2818
2819 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2820 if(completion_var != NULL)
2821 {
2822 complete(completion_var);
2823 }
2824}
2825
2826/**---------------------------------------------------------------------------
2827
2828 \brief hdd_get_cfg_file_size() -
2829
2830 This function reads the configuration file using the request firmware
2831 API and returns the configuration file size.
2832
2833 \param - pCtx - Pointer to the adapter .
2834 - pFileName - Pointer to the file name.
2835 - pBufSize - Pointer to the buffer size.
2836
2837 \return - 0 for success, non zero for failure
2838
2839 --------------------------------------------------------------------------*/
2840
2841VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2842{
2843 int status;
2844 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2845
2846 ENTER();
2847
2848 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2849
2850 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2851 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2852 status = VOS_STATUS_E_FAILURE;
2853 }
2854 else {
2855 *pBufSize = pHddCtx->fw->size;
2856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2857 release_firmware(pHddCtx->fw);
2858 pHddCtx->fw = NULL;
2859 }
2860
2861 EXIT();
2862 return VOS_STATUS_SUCCESS;
2863}
2864
2865/**---------------------------------------------------------------------------
2866
2867 \brief hdd_read_cfg_file() -
2868
2869 This function reads the configuration file using the request firmware
2870 API and returns the cfg data and the buffer size of the configuration file.
2871
2872 \param - pCtx - Pointer to the adapter .
2873 - pFileName - Pointer to the file name.
2874 - pBuffer - Pointer to the data buffer.
2875 - pBufSize - Pointer to the buffer size.
2876
2877 \return - 0 for success, non zero for failure
2878
2879 --------------------------------------------------------------------------*/
2880
2881VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2882 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2883{
2884 int status;
2885 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2886
2887 ENTER();
2888
2889 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2890
2891 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2892 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2893 return VOS_STATUS_E_FAILURE;
2894 }
2895 else {
2896 if(*pBufSize != pHddCtx->fw->size) {
2897 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2898 "file size", __func__);
2899 release_firmware(pHddCtx->fw);
2900 pHddCtx->fw = NULL;
2901 return VOS_STATUS_E_FAILURE;
2902 }
2903 else {
2904 if(pBuffer) {
2905 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2906 }
2907 release_firmware(pHddCtx->fw);
2908 pHddCtx->fw = NULL;
2909 }
2910 }
2911
2912 EXIT();
2913
2914 return VOS_STATUS_SUCCESS;
2915}
2916
2917/**---------------------------------------------------------------------------
2918
Jeff Johnson295189b2012-06-20 16:38:30 -07002919 \brief hdd_set_mac_address() -
2920
2921 This function sets the user specified mac address using
2922 the command ifconfig wlanX hw ether <mac adress>.
2923
2924 \param - dev - Pointer to the net device.
2925 - addr - Pointer to the sockaddr.
2926 \return - 0 for success, non zero for failure
2927
2928 --------------------------------------------------------------------------*/
2929
2930static int hdd_set_mac_address(struct net_device *dev, void *addr)
2931{
2932 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2933 struct sockaddr *psta_mac_addr = addr;
2934 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2935
2936 ENTER();
2937
2938 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2939
2940#ifdef HDD_SESSIONIZE
2941 // set the MAC address though the STA ID CFG.
2942 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2943 (v_U8_t *)&pAdapter->macAddressCurrent,
2944 sizeof( pAdapter->macAddressCurrent ),
2945 hdd_set_mac_addr_cb, VOS_FALSE );
2946#endif
2947
2948 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2949
2950 EXIT();
2951 return halStatus;
2952}
2953
2954tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2955{
2956 int i;
2957 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2958 {
2959 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2960 break;
2961 }
2962
2963 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2964 return NULL;
2965
2966 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2967 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2968}
2969
2970void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2971{
2972 int i;
2973 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2974 {
2975 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2976 {
2977 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2978 break;
2979 }
2980 }
2981 return;
2982}
2983
2984#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2985 static struct net_device_ops wlan_drv_ops = {
2986 .ndo_open = hdd_open,
2987 .ndo_stop = hdd_stop,
2988 .ndo_uninit = hdd_uninit,
2989 .ndo_start_xmit = hdd_hard_start_xmit,
2990 .ndo_tx_timeout = hdd_tx_timeout,
2991 .ndo_get_stats = hdd_stats,
2992 .ndo_do_ioctl = hdd_ioctl,
2993 .ndo_set_mac_address = hdd_set_mac_address,
2994 .ndo_select_queue = hdd_select_queue,
2995#ifdef WLAN_FEATURE_PACKET_FILTERING
2996#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2997 .ndo_set_rx_mode = hdd_set_multicast_list,
2998#else
2999 .ndo_set_multicast_list = hdd_set_multicast_list,
3000#endif //LINUX_VERSION_CODE
3001#endif
3002 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003003 static struct net_device_ops wlan_mon_drv_ops = {
3004 .ndo_open = hdd_mon_open,
3005 .ndo_stop = hdd_stop,
3006 .ndo_uninit = hdd_uninit,
3007 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3008 .ndo_tx_timeout = hdd_tx_timeout,
3009 .ndo_get_stats = hdd_stats,
3010 .ndo_do_ioctl = hdd_ioctl,
3011 .ndo_set_mac_address = hdd_set_mac_address,
3012 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003013
3014#endif
3015
3016void hdd_set_station_ops( struct net_device *pWlanDev )
3017{
3018#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3019 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3020 pWlanDev->netdev_ops = &wlan_drv_ops;
3021#else
3022 pWlanDev->open = hdd_open;
3023 pWlanDev->stop = hdd_stop;
3024 pWlanDev->uninit = hdd_uninit;
3025 pWlanDev->hard_start_xmit = NULL;
3026 pWlanDev->tx_timeout = hdd_tx_timeout;
3027 pWlanDev->get_stats = hdd_stats;
3028 pWlanDev->do_ioctl = hdd_ioctl;
3029 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3030 pWlanDev->set_mac_address = hdd_set_mac_address;
3031#endif
3032}
3033
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003034static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003035{
3036 struct net_device *pWlanDev = NULL;
3037 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003038 /*
3039 * cfg80211 initialization and registration....
3040 */
3041 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3042
Jeff Johnson295189b2012-06-20 16:38:30 -07003043 if(pWlanDev != NULL)
3044 {
3045
3046 //Save the pointer to the net_device in the HDD adapter
3047 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3048
Jeff Johnson295189b2012-06-20 16:38:30 -07003049 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3050
3051 pAdapter->dev = pWlanDev;
3052 pAdapter->pHddCtx = pHddCtx;
3053 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3054
3055 init_completion(&pAdapter->session_open_comp_var);
3056 init_completion(&pAdapter->session_close_comp_var);
3057 init_completion(&pAdapter->disconnect_comp_var);
3058 init_completion(&pAdapter->linkup_event_var);
3059 init_completion(&pAdapter->cancel_rem_on_chan_var);
3060 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003061#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3062 init_completion(&pAdapter->offchannel_tx_event);
3063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003064 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003065#ifdef FEATURE_WLAN_TDLS
3066 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003067 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003068 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303069 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003070#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003071 init_completion(&pHddCtx->mc_sus_event_var);
3072 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303073 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003074 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003075
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 pAdapter->isLinkUpSvcNeeded = FALSE;
3077 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3078 //Init the net_device structure
3079 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3080
3081 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3082 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3083 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3084 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3085
3086 hdd_set_station_ops( pAdapter->dev );
3087
3088 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3090 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3091 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 /* set pWlanDev's parent to underlying device */
3093 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3094 }
3095
3096 return pAdapter;
3097}
3098
3099VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3100{
3101 struct net_device *pWlanDev = pAdapter->dev;
3102 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3103 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3104 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3105
3106 if( rtnl_lock_held )
3107 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003108 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3110 {
3111 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3112 return VOS_STATUS_E_FAILURE;
3113 }
3114 }
3115 if (register_netdevice(pWlanDev))
3116 {
3117 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3118 return VOS_STATUS_E_FAILURE;
3119 }
3120 }
3121 else
3122 {
3123 if(register_netdev(pWlanDev))
3124 {
3125 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3126 return VOS_STATUS_E_FAILURE;
3127 }
3128 }
3129 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3130
3131 return VOS_STATUS_SUCCESS;
3132}
3133
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003134static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003135{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003136 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003137
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003138 if (NULL == pAdapter)
3139 {
3140 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3141 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003143
3144 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3145 {
3146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3147 return eHAL_STATUS_NOT_INITIALIZED;
3148 }
3149
3150 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3151
3152 /* need to make sure all of our scheduled work has completed.
3153 * This callback is called from MC thread context, so it is safe to
3154 * to call below flush workqueue API from here.
3155 */
3156 flush_scheduled_work();
3157
3158 /* We can be blocked while waiting for scheduled work to be
3159 * flushed, and the adapter structure can potentially be freed, in
3160 * which case the magic will have been reset. So make sure the
3161 * magic is still good, and hence the adapter structure is still
3162 * valid, before signaling completion */
3163 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3164 {
3165 complete(&pAdapter->session_close_comp_var);
3166 }
3167
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 return eHAL_STATUS_SUCCESS;
3169}
3170
3171VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3172{
3173 struct net_device *pWlanDev = pAdapter->dev;
3174 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3175 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3176 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3177 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3178 int rc = 0;
3179
3180 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003181 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003182 //Open a SME session for future operation
3183 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003184 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003185 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3186 {
3187 hddLog(VOS_TRACE_LEVEL_FATAL,
3188 "sme_OpenSession() failed with status code %08d [x%08lx]",
3189 halStatus, halStatus );
3190 status = VOS_STATUS_E_FAILURE;
3191 goto error_sme_open;
3192 }
3193
3194 //Block on a completion variable. Can't wait forever though.
3195 rc = wait_for_completion_interruptible_timeout(
3196 &pAdapter->session_open_comp_var,
3197 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3198 if (!rc)
3199 {
3200 hddLog(VOS_TRACE_LEVEL_FATAL,
3201 "Session is not opened within timeout period code %08d", rc );
3202 status = VOS_STATUS_E_FAILURE;
3203 goto error_sme_open;
3204 }
3205
3206 // Register wireless extensions
3207 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3208 {
3209 hddLog(VOS_TRACE_LEVEL_FATAL,
3210 "hdd_register_wext() failed with status code %08d [x%08lx]",
3211 halStatus, halStatus );
3212 status = VOS_STATUS_E_FAILURE;
3213 goto error_register_wext;
3214 }
3215 //Safe to register the hard_start_xmit function again
3216#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3217 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3218#else
3219 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3220#endif
3221
3222 //Set the Connection State to Not Connected
3223 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3224
3225 //Set the default operation channel
3226 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3227
3228 /* Make the default Auth Type as OPEN*/
3229 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3230
3231 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3232 {
3233 hddLog(VOS_TRACE_LEVEL_FATAL,
3234 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3235 status, status );
3236 goto error_init_txrx;
3237 }
3238
3239 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3240
3241 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3242 {
3243 hddLog(VOS_TRACE_LEVEL_FATAL,
3244 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3245 status, status );
3246 goto error_wmm_init;
3247 }
3248
3249 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3250
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003251#ifdef FEATURE_WLAN_TDLS
3252 if(0 != wlan_hdd_tdls_init(pAdapter))
3253 {
3254 status = VOS_STATUS_E_FAILURE;
3255 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3256 goto error_tdls_init;
3257 }
3258 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3259#endif
3260
Jeff Johnson295189b2012-06-20 16:38:30 -07003261 return VOS_STATUS_SUCCESS;
3262
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003263#ifdef FEATURE_WLAN_TDLS
3264error_tdls_init:
3265 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3266 hdd_wmm_adapter_close(pAdapter);
3267#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003268error_wmm_init:
3269 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3270 hdd_deinit_tx_rx(pAdapter);
3271error_init_txrx:
3272 hdd_UnregisterWext(pWlanDev);
3273error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003274 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003275 {
3276 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003277 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003278 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003279 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 {
3281 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003282 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003283 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003284 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 }
3286}
3287error_sme_open:
3288 return status;
3289}
3290
Jeff Johnson295189b2012-06-20 16:38:30 -07003291void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3292{
3293 hdd_cfg80211_state_t *cfgState;
3294
3295 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3296
3297 if( NULL != cfgState->buf )
3298 {
3299 int rc;
3300 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3301 rc = wait_for_completion_interruptible_timeout(
3302 &pAdapter->tx_action_cnf_event,
3303 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3304 if(!rc)
3305 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003307 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3308 }
3309 }
3310 return;
3311}
Jeff Johnson295189b2012-06-20 16:38:30 -07003312
3313void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3314{
3315 ENTER();
3316 switch ( pAdapter->device_mode )
3317 {
3318 case WLAN_HDD_INFRA_STATION:
3319 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003320 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003321 {
3322 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3323 {
3324 hdd_deinit_tx_rx( pAdapter );
3325 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3326 }
3327
3328 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3329 {
3330 hdd_wmm_adapter_close( pAdapter );
3331 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3332 }
3333
Jeff Johnson295189b2012-06-20 16:38:30 -07003334 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003335#ifdef FEATURE_WLAN_TDLS
3336 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3337 {
3338 wlan_hdd_tdls_exit(pAdapter);
3339 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3340 }
3341#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003342
3343 break;
3344 }
3345
3346 case WLAN_HDD_SOFTAP:
3347 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003349 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003350
3351 hdd_unregister_hostapd(pAdapter);
3352 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003353 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003354 break;
3355 }
3356
3357 case WLAN_HDD_MONITOR:
3358 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003359 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003360 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3361 {
3362 hdd_deinit_tx_rx( pAdapter );
3363 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3364 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003365 if(NULL != pAdapterforTx)
3366 {
3367 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3368 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 break;
3370 }
3371
3372
3373 default:
3374 break;
3375 }
3376
3377 EXIT();
3378}
3379
3380void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3381{
3382 struct net_device *pWlanDev = pAdapter->dev;
3383
3384 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3385 if( rtnl_held )
3386 {
3387 unregister_netdevice(pWlanDev);
3388 }
3389 else
3390 {
3391 unregister_netdev(pWlanDev);
3392 }
3393 // note that the pAdapter is no longer valid at this point
3394 // since the memory has been reclaimed
3395 }
3396
3397}
3398
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003399void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3400{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303401 VOS_STATUS status;
3402 hdd_adapter_t *pAdapter = NULL;
3403 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003404
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303405 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003406
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303407 /*loop through all adapters.*/
3408 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003409 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303410 pAdapter = pAdapterNode->pAdapter;
3411 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3412 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003413
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303414 { // we skip this registration for modes other than STA and P2P client modes.
3415 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3416 pAdapterNode = pNext;
3417 continue;
3418 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003419
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303420 //Apply Dynamic DTIM For P2P
3421 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3422 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3423 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3424 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3425 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3426 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3427 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3428 (eConnectionState_Associated ==
3429 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3430 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3431 {
3432 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003433
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303434 powerRequest.uIgnoreDTIM = 1;
3435 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3436
3437 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3438 {
3439 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3440 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3441 }
3442 else
3443 {
3444 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3445 }
3446
3447 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3448 * specified during Enter/Exit BMPS when LCD off*/
3449 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3450 NULL, eANI_BOOLEAN_FALSE);
3451 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3452 NULL, eANI_BOOLEAN_FALSE);
3453
3454 /* switch to the DTIM specified in cfg.ini */
3455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3456 "Switch to DTIM %d", powerRequest.uListenInterval);
3457 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3458 break;
3459
3460 }
3461
3462 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3463 pAdapterNode = pNext;
3464 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003465}
3466
3467void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3468{
3469 /*Switch back to DTIM 1*/
3470 tSirSetPowerParamsReq powerRequest = { 0 };
3471
3472 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3473 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003474 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003475
3476 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3477 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3478 NULL, eANI_BOOLEAN_FALSE);
3479 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3480 NULL, eANI_BOOLEAN_FALSE);
3481
3482 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3483 "Switch to DTIM%d",powerRequest.uListenInterval);
3484 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3485
3486}
3487
Jeff Johnson295189b2012-06-20 16:38:30 -07003488VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3489{
3490 VOS_STATUS status = VOS_STATUS_SUCCESS;
3491
3492 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3493 {
3494 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3495 }
3496
3497 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3498 {
3499 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3500 }
3501
3502 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3503 {
3504 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3505 }
3506
3507 return status;
3508}
3509
3510VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3511{
3512 hdd_adapter_t *pAdapter = NULL;
3513 eHalStatus halStatus;
3514 VOS_STATUS status = VOS_STATUS_E_INVAL;
3515 v_BOOL_t disableBmps = FALSE;
3516 v_BOOL_t disableImps = FALSE;
3517
3518 switch(session_type)
3519 {
3520 case WLAN_HDD_INFRA_STATION:
3521 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003522 case WLAN_HDD_P2P_CLIENT:
3523 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 //Exit BMPS -> Is Sta/P2P Client is already connected
3525 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3526 if((NULL != pAdapter)&&
3527 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3528 {
3529 disableBmps = TRUE;
3530 }
3531
3532 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3533 if((NULL != pAdapter)&&
3534 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3535 {
3536 disableBmps = TRUE;
3537 }
3538
3539 //Exit both Bmps and Imps incase of Go/SAP Mode
3540 if((WLAN_HDD_SOFTAP == session_type) ||
3541 (WLAN_HDD_P2P_GO == session_type))
3542 {
3543 disableBmps = TRUE;
3544 disableImps = TRUE;
3545 }
3546
3547 if(TRUE == disableImps)
3548 {
3549 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3550 {
3551 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3552 }
3553 }
3554
3555 if(TRUE == disableBmps)
3556 {
3557 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3558 {
3559 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3560
3561 if(eHAL_STATUS_SUCCESS != halStatus)
3562 {
3563 status = VOS_STATUS_E_FAILURE;
3564 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3565 VOS_ASSERT(0);
3566 return status;
3567 }
3568 }
3569
3570 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3571 {
3572 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3573
3574 if(eHAL_STATUS_SUCCESS != halStatus)
3575 {
3576 status = VOS_STATUS_E_FAILURE;
3577 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3578 VOS_ASSERT(0);
3579 return status;
3580 }
3581 }
3582 }
3583
3584 if((TRUE == disableBmps) ||
3585 (TRUE == disableImps))
3586 {
3587 /* Now, get the chip into Full Power now */
3588 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3589 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3590 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3591
3592 if(halStatus != eHAL_STATUS_SUCCESS)
3593 {
3594 if(halStatus == eHAL_STATUS_PMC_PENDING)
3595 {
3596 //Block on a completion variable. Can't wait forever though
3597 wait_for_completion_interruptible_timeout(
3598 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3599 }
3600 else
3601 {
3602 status = VOS_STATUS_E_FAILURE;
3603 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3604 VOS_ASSERT(0);
3605 return status;
3606 }
3607 }
3608
3609 status = VOS_STATUS_SUCCESS;
3610 }
3611
3612 break;
3613 }
3614 return status;
3615}
3616
3617hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003618 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 tANI_U8 rtnl_held )
3620{
3621 hdd_adapter_t *pAdapter = NULL;
3622 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3623 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3624 VOS_STATUS exitbmpsStatus;
3625
3626 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3627
3628 //Disable BMPS incase of Concurrency
3629 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3630
3631 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3632 {
3633 //Fail to Exit BMPS
3634 VOS_ASSERT(0);
3635 return NULL;
3636 }
3637
3638 switch(session_type)
3639 {
3640 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003641 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003642 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003643 {
3644 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3645
3646 if( NULL == pAdapter )
3647 return NULL;
3648
Jeff Johnsone7245742012-09-05 17:12:55 -07003649 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3650 NL80211_IFTYPE_P2P_CLIENT:
3651 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003652
Jeff Johnson295189b2012-06-20 16:38:30 -07003653 pAdapter->device_mode = session_type;
3654
3655 status = hdd_init_station_mode( pAdapter );
3656 if( VOS_STATUS_SUCCESS != status )
3657 goto err_free_netdev;
3658
3659 status = hdd_register_interface( pAdapter, rtnl_held );
3660 if( VOS_STATUS_SUCCESS != status )
3661 {
3662 hdd_deinit_adapter(pHddCtx, pAdapter);
3663 goto err_free_netdev;
3664 }
3665 //Stop the Interface TX queue.
3666 netif_tx_disable(pAdapter->dev);
3667 //netif_tx_disable(pWlanDev);
3668 netif_carrier_off(pAdapter->dev);
3669
3670 break;
3671 }
3672
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003674 case WLAN_HDD_SOFTAP:
3675 {
3676 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3677 if( NULL == pAdapter )
3678 return NULL;
3679
Jeff Johnson295189b2012-06-20 16:38:30 -07003680 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3681 NL80211_IFTYPE_AP:
3682 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003683 pAdapter->device_mode = session_type;
3684
3685 status = hdd_init_ap_mode(pAdapter);
3686 if( VOS_STATUS_SUCCESS != status )
3687 goto err_free_netdev;
3688
3689 status = hdd_register_hostapd( pAdapter, rtnl_held );
3690 if( VOS_STATUS_SUCCESS != status )
3691 {
3692 hdd_deinit_adapter(pHddCtx, pAdapter);
3693 goto err_free_netdev;
3694 }
3695
3696 netif_tx_disable(pAdapter->dev);
3697 netif_carrier_off(pAdapter->dev);
3698
3699 hdd_set_conparam( 1 );
3700 break;
3701 }
3702 case WLAN_HDD_MONITOR:
3703 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003704 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3705 if( NULL == pAdapter )
3706 return NULL;
3707
3708 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3709 pAdapter->device_mode = session_type;
3710 status = hdd_register_interface( pAdapter, rtnl_held );
3711#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3712 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3713#else
3714 pAdapter->dev->open = hdd_mon_open;
3715 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3716#endif
3717 hdd_init_tx_rx( pAdapter );
3718 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3719 //Set adapter to be used for data tx. It will use either GO or softap.
3720 pAdapter->sessionCtx.monitor.pAdapterForTx =
3721 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003722 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3723 {
3724 pAdapter->sessionCtx.monitor.pAdapterForTx =
3725 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3726 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 /* This workqueue will be used to transmit management packet over
3728 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003729 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3730 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3731 return NULL;
3732 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003733
Jeff Johnson295189b2012-06-20 16:38:30 -07003734 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3735 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003736 }
3737 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003738 case WLAN_HDD_FTM:
3739 {
3740 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3741
3742 if( NULL == pAdapter )
3743 return NULL;
3744 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3745 * message while loading driver in FTM mode. */
3746 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3747 pAdapter->device_mode = session_type;
3748 status = hdd_register_interface( pAdapter, rtnl_held );
3749 }
3750 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 default:
3752 {
3753 VOS_ASSERT(0);
3754 return NULL;
3755 }
3756 }
3757
3758
3759 if( VOS_STATUS_SUCCESS == status )
3760 {
3761 //Add it to the hdd's session list.
3762 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3763 if( NULL == pHddAdapterNode )
3764 {
3765 status = VOS_STATUS_E_NOMEM;
3766 }
3767 else
3768 {
3769 pHddAdapterNode->pAdapter = pAdapter;
3770 status = hdd_add_adapter_back ( pHddCtx,
3771 pHddAdapterNode );
3772 }
3773 }
3774
3775 if( VOS_STATUS_SUCCESS != status )
3776 {
3777 if( NULL != pAdapter )
3778 {
3779 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3780 pAdapter = NULL;
3781 }
3782 if( NULL != pHddAdapterNode )
3783 {
3784 vos_mem_free( pHddAdapterNode );
3785 }
3786
3787 goto resume_bmps;
3788 }
3789
3790 if(VOS_STATUS_SUCCESS == status)
3791 {
3792 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3793
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003794 //Initialize the WoWL service
3795 if(!hdd_init_wowl(pAdapter))
3796 {
3797 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3798 goto err_free_netdev;
3799 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 return pAdapter;
3802
3803err_free_netdev:
3804 free_netdev(pAdapter->dev);
3805 wlan_hdd_release_intf_addr( pHddCtx,
3806 pAdapter->macAddressCurrent.bytes );
3807
3808resume_bmps:
3809 //If bmps disabled enable it
3810 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3811 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303812 if (pHddCtx->hdd_wlan_suspended)
3813 {
3814 hdd_set_pwrparams(pHddCtx);
3815 }
3816 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003817 }
3818 return NULL;
3819}
3820
3821VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3822 tANI_U8 rtnl_held )
3823{
3824 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3825 VOS_STATUS status;
3826
3827 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3828 if( VOS_STATUS_SUCCESS != status )
3829 return status;
3830
3831 while ( pCurrent->pAdapter != pAdapter )
3832 {
3833 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3834 if( VOS_STATUS_SUCCESS != status )
3835 break;
3836
3837 pCurrent = pNext;
3838 }
3839 pAdapterNode = pCurrent;
3840 if( VOS_STATUS_SUCCESS == status )
3841 {
3842 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3843 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3844 hdd_remove_adapter( pHddCtx, pAdapterNode );
3845 vos_mem_free( pAdapterNode );
3846
Jeff Johnson295189b2012-06-20 16:38:30 -07003847
3848 /* If there is a single session of STA/P2P client, re-enable BMPS */
3849 if ((!vos_concurrent_sessions_running()) &&
3850 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3851 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3852 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303853 if (pHddCtx->hdd_wlan_suspended)
3854 {
3855 hdd_set_pwrparams(pHddCtx);
3856 }
3857 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003858 }
3859
3860 return VOS_STATUS_SUCCESS;
3861 }
3862
3863 return VOS_STATUS_E_FAILURE;
3864}
3865
3866VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3867{
3868 hdd_adapter_list_node_t *pHddAdapterNode;
3869 VOS_STATUS status;
3870
3871 ENTER();
3872
3873 do
3874 {
3875 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3876 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3877 {
3878 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3879 vos_mem_free( pHddAdapterNode );
3880 }
3881 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3882
3883 EXIT();
3884
3885 return VOS_STATUS_SUCCESS;
3886}
3887
3888void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3889{
3890 v_U8_t addIE[1] = {0};
3891
3892 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3893 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3894 eANI_BOOLEAN_FALSE) )
3895 {
3896 hddLog(LOGE,
3897 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3898 }
3899
3900 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3901 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3902 eANI_BOOLEAN_FALSE) )
3903 {
3904 hddLog(LOGE,
3905 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3906 }
3907
3908 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3909 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3910 eANI_BOOLEAN_FALSE) )
3911 {
3912 hddLog(LOGE,
3913 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3914 }
3915}
3916
3917VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3918{
3919 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3920 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3921 union iwreq_data wrqu;
3922
3923 ENTER();
3924
3925 switch(pAdapter->device_mode)
3926 {
3927 case WLAN_HDD_INFRA_STATION:
3928 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003929 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003930 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3931 {
3932 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3933 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3934 pAdapter->sessionId,
3935 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3936 else
3937 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3938 pAdapter->sessionId,
3939 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3940 //success implies disconnect command got queued up successfully
3941 if(halStatus == eHAL_STATUS_SUCCESS)
3942 {
3943 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3944 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3945 }
3946 memset(&wrqu, '\0', sizeof(wrqu));
3947 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3948 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3949 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3950 }
3951 else
3952 {
3953 hdd_abort_mac_scan(pHddCtx);
3954 }
3955
3956 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3957 {
3958 INIT_COMPLETION(pAdapter->session_close_comp_var);
3959 if (eHAL_STATUS_SUCCESS ==
3960 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3961 hdd_smeCloseSessionCallback, pAdapter))
3962 {
3963 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003964 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003965 &pAdapter->session_close_comp_var,
3966 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3967 }
3968 }
3969
3970 break;
3971
3972 case WLAN_HDD_SOFTAP:
3973 case WLAN_HDD_P2P_GO:
3974 //Any softap specific cleanup here...
3975 mutex_lock(&pHddCtx->sap_lock);
3976 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3977 {
3978 VOS_STATUS status;
3979 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3980
3981 //Stop Bss.
3982 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3983 if (VOS_IS_STATUS_SUCCESS(status))
3984 {
3985 hdd_hostapd_state_t *pHostapdState =
3986 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3987
3988 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3989
3990 if (!VOS_IS_STATUS_SUCCESS(status))
3991 {
3992 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003993 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003994 }
3995 }
3996 else
3997 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003998 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003999 }
4000 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4001
4002 if (eHAL_STATUS_FAILURE ==
4003 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4004 0, NULL, eANI_BOOLEAN_FALSE))
4005 {
4006 hddLog(LOGE,
4007 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004008 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004009 }
4010
4011 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4012 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4013 eANI_BOOLEAN_FALSE) )
4014 {
4015 hddLog(LOGE,
4016 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4017 }
4018
4019 // Reset WNI_CFG_PROBE_RSP Flags
4020 wlan_hdd_reset_prob_rspies(pAdapter);
4021 kfree(pAdapter->sessionCtx.ap.beacon);
4022 pAdapter->sessionCtx.ap.beacon = NULL;
4023 }
4024 mutex_unlock(&pHddCtx->sap_lock);
4025 break;
4026 case WLAN_HDD_MONITOR:
4027 break;
4028 default:
4029 break;
4030 }
4031
4032 EXIT();
4033 return VOS_STATUS_SUCCESS;
4034}
4035
4036VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4037{
4038 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4039 VOS_STATUS status;
4040 hdd_adapter_t *pAdapter;
4041
4042 ENTER();
4043
4044 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4045
4046 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4047 {
4048 pAdapter = pAdapterNode->pAdapter;
4049 netif_tx_disable(pAdapter->dev);
4050 netif_carrier_off(pAdapter->dev);
4051
4052 hdd_stop_adapter( pHddCtx, pAdapter );
4053
4054 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4055 pAdapterNode = pNext;
4056 }
4057
4058 EXIT();
4059
4060 return VOS_STATUS_SUCCESS;
4061}
4062
4063VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4064{
4065 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4066 VOS_STATUS status;
4067 hdd_adapter_t *pAdapter;
4068
4069 ENTER();
4070
4071 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4072
4073 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4074 {
4075 pAdapter = pAdapterNode->pAdapter;
4076 netif_tx_disable(pAdapter->dev);
4077 netif_carrier_off(pAdapter->dev);
4078
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004079 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4080
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 hdd_deinit_tx_rx(pAdapter);
4082 hdd_wmm_adapter_close(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_start_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 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304099 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004100
4101 ENTER();
4102
4103 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4104
4105 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4106 {
4107 pAdapter = pAdapterNode->pAdapter;
4108
4109 switch(pAdapter->device_mode)
4110 {
4111 case WLAN_HDD_INFRA_STATION:
4112 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004113 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304114
4115 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4116
Jeff Johnson295189b2012-06-20 16:38:30 -07004117 hdd_init_station_mode(pAdapter);
4118 /* Open the gates for HDD to receive Wext commands */
4119 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004120 pHddCtx->scan_info.mScanPending = FALSE;
4121 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004122
4123 //Trigger the initial scan
4124 hdd_wlan_initial_scan(pAdapter);
4125
4126 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304127 if (eConnectionState_Associated == connState ||
4128 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004129 {
4130 union iwreq_data wrqu;
4131 memset(&wrqu, '\0', sizeof(wrqu));
4132 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4133 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4134 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004135 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004136
Jeff Johnson295189b2012-06-20 16:38:30 -07004137 /* indicate disconnected event to nl80211 */
4138 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4139 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304141 else if (eConnectionState_Connecting == connState)
4142 {
4143 /*
4144 * Indicate connect failure to supplicant if we were in the
4145 * process of connecting
4146 */
4147 cfg80211_connect_result(pAdapter->dev, NULL,
4148 NULL, 0, NULL, 0,
4149 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4150 GFP_KERNEL);
4151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004152 break;
4153
4154 case WLAN_HDD_SOFTAP:
4155 /* softAP can handle SSR */
4156 break;
4157
4158 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4160 __func__);
4161 /* event supplicant to restart */
4162 cfg80211_del_sta(pAdapter->dev,
4163 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004164 break;
4165
4166 case WLAN_HDD_MONITOR:
4167 /* monitor interface start */
4168 break;
4169 default:
4170 break;
4171 }
4172
4173 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4174 pAdapterNode = pNext;
4175 }
4176
4177 EXIT();
4178
4179 return VOS_STATUS_SUCCESS;
4180}
4181
4182VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4183{
4184 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4185 hdd_adapter_t *pAdapter;
4186 VOS_STATUS status;
4187 v_U32_t roamId;
4188
4189 ENTER();
4190
4191 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4192
4193 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4194 {
4195 pAdapter = pAdapterNode->pAdapter;
4196
4197 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4198 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4199 {
4200 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4201 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4202
4203 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4204 init_completion(&pAdapter->disconnect_comp_var);
4205 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4206 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4207
4208 wait_for_completion_interruptible_timeout(
4209 &pAdapter->disconnect_comp_var,
4210 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4211
4212 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4213 pHddCtx->isAmpAllowed = VOS_FALSE;
4214 sme_RoamConnect(pHddCtx->hHal,
4215 pAdapter->sessionId, &(pWextState->roamProfile),
4216 &roamId);
4217 }
4218
4219 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4220 pAdapterNode = pNext;
4221 }
4222
4223 EXIT();
4224
4225 return VOS_STATUS_SUCCESS;
4226}
4227
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004228void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4229{
4230 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4231 VOS_STATUS status;
4232 hdd_adapter_t *pAdapter;
4233 hdd_station_ctx_t *pHddStaCtx;
4234 hdd_ap_ctx_t *pHddApCtx;
4235 hdd_hostapd_state_t * pHostapdState;
4236 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4237 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4238 const char *p2pMode = "DEV";
4239 const char *ccMode = "Standalone";
4240 int n;
4241
4242 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4243 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4244 {
4245 pAdapter = pAdapterNode->pAdapter;
4246 switch (pAdapter->device_mode) {
4247 case WLAN_HDD_INFRA_STATION:
4248 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4249 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4250 staChannel = pHddStaCtx->conn_info.operationChannel;
4251 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4252 }
4253 break;
4254 case WLAN_HDD_P2P_CLIENT:
4255 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4256 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4257 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4258 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4259 p2pMode = "CLI";
4260 }
4261 break;
4262 case WLAN_HDD_P2P_GO:
4263 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4264 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4265 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4266 p2pChannel = pHddApCtx->operatingChannel;
4267 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4268 }
4269 p2pMode = "GO";
4270 break;
4271 case WLAN_HDD_SOFTAP:
4272 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4273 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4274 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4275 apChannel = pHddApCtx->operatingChannel;
4276 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4277 }
4278 break;
4279 default:
4280 break;
4281 }
4282 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4283 pAdapterNode = pNext;
4284 }
4285 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4286 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4287 }
4288 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4289 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4290 if (p2pChannel > 0) {
4291 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4292 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4293 }
4294 if (apChannel > 0) {
4295 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4296 apChannel, MAC_ADDR_ARRAY(apBssid));
4297 }
4298
4299 if (p2pChannel > 0 && apChannel > 0) {
4300 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4301 }
4302}
4303
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004304bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004305{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004306 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004307}
4308
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004309/* Once SSR is disabled then it cannot be set. */
4310void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004311{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004312 if (HDD_SSR_DISABLED == isSsrRequired)
4313 return;
4314
Jeff Johnson295189b2012-06-20 16:38:30 -07004315 isSsrRequired = value;
4316}
4317
4318VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4319 hdd_adapter_list_node_t** ppAdapterNode)
4320{
4321 VOS_STATUS status;
4322 spin_lock(&pHddCtx->hddAdapters.lock);
4323 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4324 (hdd_list_node_t**) ppAdapterNode );
4325 spin_unlock(&pHddCtx->hddAdapters.lock);
4326 return status;
4327}
4328
4329VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4330 hdd_adapter_list_node_t* pAdapterNode,
4331 hdd_adapter_list_node_t** pNextAdapterNode)
4332{
4333 VOS_STATUS status;
4334 spin_lock(&pHddCtx->hddAdapters.lock);
4335 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4336 (hdd_list_node_t*) pAdapterNode,
4337 (hdd_list_node_t**)pNextAdapterNode );
4338
4339 spin_unlock(&pHddCtx->hddAdapters.lock);
4340 return status;
4341}
4342
4343VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4344 hdd_adapter_list_node_t* pAdapterNode)
4345{
4346 VOS_STATUS status;
4347 spin_lock(&pHddCtx->hddAdapters.lock);
4348 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4349 &pAdapterNode->node );
4350 spin_unlock(&pHddCtx->hddAdapters.lock);
4351 return status;
4352}
4353
4354VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4355 hdd_adapter_list_node_t** ppAdapterNode)
4356{
4357 VOS_STATUS status;
4358 spin_lock(&pHddCtx->hddAdapters.lock);
4359 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4360 (hdd_list_node_t**) ppAdapterNode );
4361 spin_unlock(&pHddCtx->hddAdapters.lock);
4362 return status;
4363}
4364
4365VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4366 hdd_adapter_list_node_t* pAdapterNode)
4367{
4368 VOS_STATUS status;
4369 spin_lock(&pHddCtx->hddAdapters.lock);
4370 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4371 (hdd_list_node_t*) pAdapterNode );
4372 spin_unlock(&pHddCtx->hddAdapters.lock);
4373 return status;
4374}
4375
4376VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4377 hdd_adapter_list_node_t* pAdapterNode)
4378{
4379 VOS_STATUS status;
4380 spin_lock(&pHddCtx->hddAdapters.lock);
4381 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4382 (hdd_list_node_t*) pAdapterNode );
4383 spin_unlock(&pHddCtx->hddAdapters.lock);
4384 return status;
4385}
4386
4387hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4388 tSirMacAddr macAddr )
4389{
4390 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4391 hdd_adapter_t *pAdapter;
4392 VOS_STATUS status;
4393
4394 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4395
4396 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4397 {
4398 pAdapter = pAdapterNode->pAdapter;
4399
4400 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4401 macAddr, sizeof(tSirMacAddr) ) )
4402 {
4403 return pAdapter;
4404 }
4405 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4406 pAdapterNode = pNext;
4407 }
4408
4409 return NULL;
4410
4411}
4412
4413hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4414{
4415 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4416 hdd_adapter_t *pAdapter;
4417 VOS_STATUS status;
4418
4419 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4420
4421 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4422 {
4423 pAdapter = pAdapterNode->pAdapter;
4424
4425 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4426 IFNAMSIZ ) )
4427 {
4428 return pAdapter;
4429 }
4430 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4431 pAdapterNode = pNext;
4432 }
4433
4434 return NULL;
4435
4436}
4437
4438hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4439{
4440 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4441 hdd_adapter_t *pAdapter;
4442 VOS_STATUS status;
4443
4444 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4445
4446 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4447 {
4448 pAdapter = pAdapterNode->pAdapter;
4449
4450 if( pAdapter && (mode == pAdapter->device_mode) )
4451 {
4452 return pAdapter;
4453 }
4454 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4455 pAdapterNode = pNext;
4456 }
4457
4458 return NULL;
4459
4460}
4461
4462//Remove this function later
4463hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4464{
4465 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4466 hdd_adapter_t *pAdapter;
4467 VOS_STATUS status;
4468
4469 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4470
4471 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4472 {
4473 pAdapter = pAdapterNode->pAdapter;
4474
4475 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4476 {
4477 return pAdapter;
4478 }
4479
4480 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4481 pAdapterNode = pNext;
4482 }
4483
4484 return NULL;
4485
4486}
4487
Jeff Johnson295189b2012-06-20 16:38:30 -07004488/**---------------------------------------------------------------------------
4489
4490 \brief hdd_set_monitor_tx_adapter() -
4491
4492 This API initializes the adapter to be used while transmitting on monitor
4493 adapter.
4494
4495 \param - pHddCtx - Pointer to the HDD context.
4496 pAdapter - Adapter that will used for TX. This can be NULL.
4497 \return - None.
4498 --------------------------------------------------------------------------*/
4499void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4500{
4501 hdd_adapter_t *pMonAdapter;
4502
4503 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4504
4505 if( NULL != pMonAdapter )
4506 {
4507 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4508 }
4509}
Jeff Johnson295189b2012-06-20 16:38:30 -07004510/**---------------------------------------------------------------------------
4511
4512 \brief hdd_select_queue() -
4513
4514 This API returns the operating channel of the requested device mode
4515
4516 \param - pHddCtx - Pointer to the HDD context.
4517 - mode - Device mode for which operating channel is required
4518 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4519 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4520 \return - channel number. "0" id the requested device is not found OR it is not connected.
4521 --------------------------------------------------------------------------*/
4522v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4523{
4524 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4525 VOS_STATUS status;
4526 hdd_adapter_t *pAdapter;
4527 v_U8_t operatingChannel = 0;
4528
4529 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4530
4531 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4532 {
4533 pAdapter = pAdapterNode->pAdapter;
4534
4535 if( mode == pAdapter->device_mode )
4536 {
4537 switch(pAdapter->device_mode)
4538 {
4539 case WLAN_HDD_INFRA_STATION:
4540 case WLAN_HDD_P2P_CLIENT:
4541 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4542 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4543 break;
4544 case WLAN_HDD_SOFTAP:
4545 case WLAN_HDD_P2P_GO:
4546 /*softap connection info */
4547 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4548 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4549 break;
4550 default:
4551 break;
4552 }
4553
4554 break; //Found the device of interest. break the loop
4555 }
4556
4557 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4558 pAdapterNode = pNext;
4559 }
4560 return operatingChannel;
4561}
4562
4563#ifdef WLAN_FEATURE_PACKET_FILTERING
4564/**---------------------------------------------------------------------------
4565
4566 \brief hdd_set_multicast_list() -
4567
4568 This used to set the multicast address list.
4569
4570 \param - dev - Pointer to the WLAN device.
4571 - skb - Pointer to OS packet (sk_buff).
4572 \return - success/fail
4573
4574 --------------------------------------------------------------------------*/
4575static void hdd_set_multicast_list(struct net_device *dev)
4576{
4577 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004578 int mc_count;
4579 int i = 0;
4580 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304581
4582 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004583 {
4584 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304585 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 return;
4587 }
4588
4589 if (dev->flags & IFF_ALLMULTI)
4590 {
4591 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004592 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304593 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 }
4595 else
4596 {
4597 mc_count = netdev_mc_count(dev);
4598 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004599 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004600 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4601 {
4602 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004603 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304604 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 return;
4606 }
4607
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304608 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004609
4610 netdev_for_each_mc_addr(ha, dev) {
4611 if (i == mc_count)
4612 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304613 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4614 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4615 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004616 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304617 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004618 i++;
4619 }
4620 }
4621 return;
4622}
4623#endif
4624
4625/**---------------------------------------------------------------------------
4626
4627 \brief hdd_select_queue() -
4628
4629 This function is registered with the Linux OS for network
4630 core to decide which queue to use first.
4631
4632 \param - dev - Pointer to the WLAN device.
4633 - skb - Pointer to OS packet (sk_buff).
4634 \return - ac, Queue Index/access category corresponding to UP in IP header
4635
4636 --------------------------------------------------------------------------*/
4637v_U16_t hdd_select_queue(struct net_device *dev,
4638 struct sk_buff *skb)
4639{
4640 return hdd_wmm_select_queue(dev, skb);
4641}
4642
4643
4644/**---------------------------------------------------------------------------
4645
4646 \brief hdd_wlan_initial_scan() -
4647
4648 This function triggers the initial scan
4649
4650 \param - pAdapter - Pointer to the HDD adapter.
4651
4652 --------------------------------------------------------------------------*/
4653void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4654{
4655 tCsrScanRequest scanReq;
4656 tCsrChannelInfo channelInfo;
4657 eHalStatus halStatus;
4658 unsigned long scanId;
4659 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4660
4661 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4662 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4663 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4664
4665 if(sme_Is11dSupported(pHddCtx->hHal))
4666 {
4667 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4668 if ( HAL_STATUS_SUCCESS( halStatus ) )
4669 {
4670 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4671 if( !scanReq.ChannelInfo.ChannelList )
4672 {
4673 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4674 vos_mem_free(channelInfo.ChannelList);
4675 return;
4676 }
4677 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4678 channelInfo.numOfChannels);
4679 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4680 vos_mem_free(channelInfo.ChannelList);
4681 }
4682
4683 scanReq.scanType = eSIR_PASSIVE_SCAN;
4684 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4685 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4686 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4687 }
4688 else
4689 {
4690 scanReq.scanType = eSIR_ACTIVE_SCAN;
4691 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4692 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4693 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4694 }
4695
4696 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4697 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4698 {
4699 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4700 __func__, halStatus );
4701 }
4702
4703 if(sme_Is11dSupported(pHddCtx->hHal))
4704 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4705}
4706
4707struct fullPowerContext
4708{
4709 struct completion completion;
4710 unsigned int magic;
4711};
4712#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4713
4714/**---------------------------------------------------------------------------
4715
4716 \brief hdd_full_power_callback() - HDD full power callback function
4717
4718 This is the function invoked by SME to inform the result of a full power
4719 request issued by HDD
4720
4721 \param - callbackcontext - Pointer to cookie
4722 \param - status - result of request
4723
4724 \return - None
4725
4726 --------------------------------------------------------------------------*/
4727static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4728{
4729 struct fullPowerContext *pContext = callbackContext;
4730
4731 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304732 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004733
4734 if (NULL == callbackContext)
4735 {
4736 hddLog(VOS_TRACE_LEVEL_ERROR,
4737 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004738 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 return;
4740 }
4741
4742 /* there is a race condition that exists between this callback function
4743 and the caller since the caller could time out either before or
4744 while this code is executing. we'll assume the timeout hasn't
4745 occurred, but we'll verify that right before we save our work */
4746
4747 if (POWER_CONTEXT_MAGIC != pContext->magic)
4748 {
4749 /* the caller presumably timed out so there is nothing we can do */
4750 hddLog(VOS_TRACE_LEVEL_WARN,
4751 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004752 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 return;
4754 }
4755
4756 /* the race is on. caller could have timed out immediately after
4757 we verified the magic, but if so, caller will wait a short time
4758 for us to notify the caller, so the context will stay valid */
4759 complete(&pContext->completion);
4760}
4761
4762/**---------------------------------------------------------------------------
4763
4764 \brief hdd_wlan_exit() - HDD WLAN exit function
4765
4766 This is the driver exit point (invoked during rmmod)
4767
4768 \param - pHddCtx - Pointer to the HDD Context
4769
4770 \return - None
4771
4772 --------------------------------------------------------------------------*/
4773void hdd_wlan_exit(hdd_context_t *pHddCtx)
4774{
4775 eHalStatus halStatus;
4776 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4777 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304778 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004779 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004780 struct fullPowerContext powerContext;
4781 long lrc;
4782
4783 ENTER();
4784
Jeff Johnson88ba7742013-02-27 14:36:02 -08004785 if (VOS_FTM_MODE != hdd_get_conparam())
4786 {
4787 // Unloading, restart logic is no more required.
4788 wlan_hdd_restart_deinit(pHddCtx);
4789 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004790
Jeff Johnson295189b2012-06-20 16:38:30 -07004791 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004792 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 {
4795 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4796 WLAN_HDD_INFRA_STATION);
4797 if (pAdapter == NULL)
4798 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4799
4800 if (pAdapter != NULL)
4801 {
4802 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4803 hdd_UnregisterWext(pAdapter->dev);
4804 }
4805 }
4806 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004807
Jeff Johnson295189b2012-06-20 16:38:30 -07004808 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004809 {
4810 wlan_hdd_ftm_close(pHddCtx);
4811 goto free_hdd_ctx;
4812 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 //Stop the Interface TX queue.
4814 //netif_tx_disable(pWlanDev);
4815 //netif_carrier_off(pWlanDev);
4816
Jeff Johnson295189b2012-06-20 16:38:30 -07004817 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4818 {
4819 pAdapter = hdd_get_adapter(pHddCtx,
4820 WLAN_HDD_SOFTAP);
4821 }
4822 else
4823 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 {
4826 pAdapter = hdd_get_adapter(pHddCtx,
4827 WLAN_HDD_INFRA_STATION);
4828 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 /* DeRegister with platform driver as client for Suspend/Resume */
4831 vosStatus = hddDeregisterPmOps(pHddCtx);
4832 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4833 {
4834 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4835 VOS_ASSERT(0);
4836 }
4837
4838 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4839 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4840 {
4841 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4842 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004843
4844 // Cancel any outstanding scan requests. We are about to close all
4845 // of our adapters, but an adapter structure is what SME passes back
4846 // to our callback function. Hence if there are any outstanding scan
4847 // requests then there is a race condition between when the adapter
4848 // is closed and when the callback is invoked. We try to resolve that
4849 // race condition here by canceling any outstanding scans before we
4850 // close the adapters.
4851 // Note that the scans may be cancelled in an asynchronous manner, so
4852 // ideally there needs to be some kind of synchronization. Rather than
4853 // introduce a new synchronization here, we will utilize the fact that
4854 // we are about to Request Full Power, and since that is synchronized,
4855 // the expectation is that by the time Request Full Power has completed,
4856 // all scans will be cancelled.
4857 hdd_abort_mac_scan( pHddCtx );
4858
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304859 //Stop the timer if already running
4860 if (VOS_TIMER_STATE_RUNNING ==
4861 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4862 {
4863 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4864 }
4865
4866 // Destroy hdd_p2p_go_conn_is_in_progress timer
4867 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4868 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4869 {
4870 hddLog(VOS_TRACE_LEVEL_ERROR,
4871 "%s: Cannot deallocate p2p connection timer", __func__);
4872 }
4873
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004874 //Stop the traffic monitor timer
4875 if ( VOS_TIMER_STATE_RUNNING ==
4876 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
4877 {
4878 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
4879 }
4880
4881 // Destroy the traffic monitor timer
4882 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4883 &pHddCtx->tx_rx_trafficTmr)))
4884 {
4885 hddLog(VOS_TRACE_LEVEL_ERROR,
4886 "%s: Cannot deallocate Traffic monitor timer", __func__);
4887 }
4888
Jeff Johnson295189b2012-06-20 16:38:30 -07004889 //Disable IMPS/BMPS as we do not want the device to enter any power
4890 //save mode during shutdown
4891 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4892 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4893 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4894
4895 //Ensure that device is in full power as we will touch H/W during vos_Stop
4896 init_completion(&powerContext.completion);
4897 powerContext.magic = POWER_CONTEXT_MAGIC;
4898
4899 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4900 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4901
4902 if (eHAL_STATUS_SUCCESS != halStatus)
4903 {
4904 if (eHAL_STATUS_PMC_PENDING == halStatus)
4905 {
4906 /* request was sent -- wait for the response */
4907 lrc = wait_for_completion_interruptible_timeout(
4908 &powerContext.completion,
4909 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4910 /* either we have a response or we timed out
4911 either way, first invalidate our magic */
4912 powerContext.magic = 0;
4913 if (lrc <= 0)
4914 {
4915 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004916 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004917 /* there is a race condition such that the callback
4918 function could be executing at the same time we are. of
4919 primary concern is if the callback function had already
4920 verified the "magic" but hasn't yet set the completion
4921 variable. Since the completion variable is on our
4922 stack, we'll delay just a bit to make sure the data is
4923 still valid if that is the case */
4924 msleep(50);
4925 }
4926 }
4927 else
4928 {
4929 hddLog(VOS_TRACE_LEVEL_ERROR,
4930 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004931 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 VOS_ASSERT(0);
4933 /* continue -- need to clean up as much as possible */
4934 }
4935 }
4936
Yue Ma0d4891e2013-08-06 17:01:45 -07004937 hdd_debugfs_exit(pHddCtx);
4938
Jeff Johnson295189b2012-06-20 16:38:30 -07004939 // Unregister the Net Device Notifier
4940 unregister_netdevice_notifier(&hdd_netdev_notifier);
4941
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 hdd_stop_all_adapters( pHddCtx );
4943
Jeff Johnson295189b2012-06-20 16:38:30 -07004944#ifdef WLAN_BTAMP_FEATURE
4945 vosStatus = WLANBAP_Stop(pVosContext);
4946 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4947 {
4948 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4949 "%s: Failed to stop BAP",__func__);
4950 }
4951#endif //WLAN_BTAMP_FEATURE
4952
4953 //Stop all the modules
4954 vosStatus = vos_stop( pVosContext );
4955 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4956 {
4957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4958 "%s: Failed to stop VOSS",__func__);
4959 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4960 }
4961
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 //Assert Deep sleep signal now to put Libra HW in lowest power state
4963 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4964 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4965
4966 //Vote off any PMIC voltage supplies
4967 vos_chipPowerDown(NULL, NULL, NULL);
4968
4969 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4970
Leo Chang59cdc7e2013-07-10 10:08:21 -07004971
Jeff Johnson295189b2012-06-20 16:38:30 -07004972 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004973 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004974
4975 //Close the scheduler before calling vos_close to make sure no thread is
4976 // scheduled after the each module close is called i.e after all the data
4977 // structures are freed.
4978 vosStatus = vos_sched_close( pVosContext );
4979 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4980 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4981 "%s: Failed to close VOSS Scheduler",__func__);
4982 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4983 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004984#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004985#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4986 /* Destroy the wake lock */
4987 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4988#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004989 /* Destroy the wake lock */
4990 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004991#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004992
4993 //Close VOSS
4994 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4995 vos_close(pVosContext);
4996
Jeff Johnson295189b2012-06-20 16:38:30 -07004997 //Close Watchdog
4998 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4999 vos_watchdog_close(pVosContext);
5000
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305001 //Clean up HDD Nlink Service
5002 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005003#ifdef WLAN_KD_READY_NOTIFIER
5004 nl_srv_exit(pHddCtx->ptt_pid);
5005#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305006 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005007#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305008
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 /* Cancel the vote for XO Core ON.
5010 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5011 * exited at this point
5012 */
5013 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5014 " when WLAN is turned OFF\n");
5015 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5016 {
5017 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5018 " Not returning failure."
5019 " Power consumed will be high\n");
5020 }
5021
5022 hdd_close_all_adapters( pHddCtx );
5023
5024
5025 //Free up dynamically allocated members inside HDD Adapter
5026 kfree(pHddCtx->cfg_ini);
5027 pHddCtx->cfg_ini= NULL;
5028
5029 /* free the power on lock from platform driver */
5030 if (free_riva_power_on_lock("wlan"))
5031 {
5032 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5033 __func__);
5034 }
5035
Jeff Johnson88ba7742013-02-27 14:36:02 -08005036free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005037 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005039 if (hdd_is_ssr_required())
5040 {
5041 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005042 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005043 msleep(5000);
5044 }
5045 hdd_set_ssr_required (VOS_FALSE);
5046}
5047
5048
5049/**---------------------------------------------------------------------------
5050
5051 \brief hdd_update_config_from_nv() - Function to update the contents of
5052 the running configuration with parameters taken from NV storage
5053
5054 \param - pHddCtx - Pointer to the HDD global context
5055
5056 \return - VOS_STATUS_SUCCESS if successful
5057
5058 --------------------------------------------------------------------------*/
5059static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5060{
Jeff Johnson295189b2012-06-20 16:38:30 -07005061 v_BOOL_t itemIsValid = VOS_FALSE;
5062 VOS_STATUS status;
5063 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5064 v_U8_t macLoop;
5065
5066 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5067 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5068 if(status != VOS_STATUS_SUCCESS)
5069 {
5070 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5071 return VOS_STATUS_E_FAILURE;
5072 }
5073
5074 if (itemIsValid == VOS_TRUE)
5075 {
5076 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5077 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5078 VOS_MAX_CONCURRENCY_PERSONA);
5079 if(status != VOS_STATUS_SUCCESS)
5080 {
5081 /* Get MAC from NV fail, not update CFG info
5082 * INI MAC value will be used for MAC setting */
5083 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5084 return VOS_STATUS_E_FAILURE;
5085 }
5086
5087 /* If first MAC is not valid, treat all others are not valid
5088 * Then all MACs will be got from ini file */
5089 if(vos_is_macaddr_zero(&macFromNV[0]))
5090 {
5091 /* MAC address in NV file is not configured yet */
5092 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5093 return VOS_STATUS_E_INVAL;
5094 }
5095
5096 /* Get MAC address from NV, update CFG info */
5097 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5098 {
5099 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5100 {
5101 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5102 /* This MAC is not valid, skip it
5103 * This MAC will be got from ini file */
5104 }
5105 else
5106 {
5107 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5108 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5109 VOS_MAC_ADDR_SIZE);
5110 }
5111 }
5112 }
5113 else
5114 {
5115 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5116 return VOS_STATUS_E_FAILURE;
5117 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005118
Jeff Johnson295189b2012-06-20 16:38:30 -07005119
5120 return VOS_STATUS_SUCCESS;
5121}
5122
5123/**---------------------------------------------------------------------------
5124
5125 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5126
5127 \param - pAdapter - Pointer to the HDD
5128
5129 \return - None
5130
5131 --------------------------------------------------------------------------*/
5132VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5133{
5134 eHalStatus halStatus;
5135 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305136 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005137
Jeff Johnson295189b2012-06-20 16:38:30 -07005138
5139 // Send ready indication to the HDD. This will kick off the MAC
5140 // into a 'running' state and should kick off an initial scan.
5141 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5142 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5143 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305144 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 "code %08d [x%08x]",__func__, halStatus, halStatus );
5146 return VOS_STATUS_E_FAILURE;
5147 }
5148
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305149 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5151 // And RIVA will crash
5152 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5153 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305154 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5155 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5156
5157
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 return VOS_STATUS_SUCCESS;
5159}
5160
Jeff Johnson295189b2012-06-20 16:38:30 -07005161/* wake lock APIs for HDD */
5162void hdd_prevent_suspend(void)
5163{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005164#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005166#else
5167 wcnss_prevent_suspend();
5168#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005169}
5170
5171void hdd_allow_suspend(void)
5172{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005173#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005174 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005175#else
5176 wcnss_allow_suspend();
5177#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005178}
5179
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005180void hdd_allow_suspend_timeout(v_U32_t timeout)
5181{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005182#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005183 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005184#else
5185 /* Do nothing as there is no API in wcnss for timeout*/
5186#endif
5187}
5188
Jeff Johnson295189b2012-06-20 16:38:30 -07005189/**---------------------------------------------------------------------------
5190
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005191 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5192 information between Host and Riva
5193
5194 This function gets reported version of FW
5195 It also finds the version of Riva headers used to compile the host
5196 It compares the above two and prints a warning if they are different
5197 It gets the SW and HW version string
5198 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5199 indicating the features they support through a bitmap
5200
5201 \param - pHddCtx - Pointer to HDD context
5202
5203 \return - void
5204
5205 --------------------------------------------------------------------------*/
5206
5207void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5208{
5209
5210 tSirVersionType versionCompiled;
5211 tSirVersionType versionReported;
5212 tSirVersionString versionString;
5213 tANI_U8 fwFeatCapsMsgSupported = 0;
5214 VOS_STATUS vstatus;
5215
5216 /* retrieve and display WCNSS version information */
5217 do {
5218
5219 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5220 &versionCompiled);
5221 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5222 {
5223 hddLog(VOS_TRACE_LEVEL_FATAL,
5224 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005225 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005226 break;
5227 }
5228
5229 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5230 &versionReported);
5231 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5232 {
5233 hddLog(VOS_TRACE_LEVEL_FATAL,
5234 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005235 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005236 break;
5237 }
5238
5239 if ((versionCompiled.major != versionReported.major) ||
5240 (versionCompiled.minor != versionReported.minor) ||
5241 (versionCompiled.version != versionReported.version) ||
5242 (versionCompiled.revision != versionReported.revision))
5243 {
5244 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5245 "Host expected %u.%u.%u.%u\n",
5246 WLAN_MODULE_NAME,
5247 (int)versionReported.major,
5248 (int)versionReported.minor,
5249 (int)versionReported.version,
5250 (int)versionReported.revision,
5251 (int)versionCompiled.major,
5252 (int)versionCompiled.minor,
5253 (int)versionCompiled.version,
5254 (int)versionCompiled.revision);
5255 }
5256 else
5257 {
5258 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5259 WLAN_MODULE_NAME,
5260 (int)versionReported.major,
5261 (int)versionReported.minor,
5262 (int)versionReported.version,
5263 (int)versionReported.revision);
5264 }
5265
5266 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5267 versionString,
5268 sizeof(versionString));
5269 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5270 {
5271 hddLog(VOS_TRACE_LEVEL_FATAL,
5272 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005273 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005274 break;
5275 }
5276
5277 pr_info("%s: WCNSS software version %s\n",
5278 WLAN_MODULE_NAME, versionString);
5279
5280 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5281 versionString,
5282 sizeof(versionString));
5283 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5284 {
5285 hddLog(VOS_TRACE_LEVEL_FATAL,
5286 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005287 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005288 break;
5289 }
5290
5291 pr_info("%s: WCNSS hardware version %s\n",
5292 WLAN_MODULE_NAME, versionString);
5293
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005294 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5295 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005296 send the message only if it the riva is 1.1
5297 minor numbers for different riva branches:
5298 0 -> (1.0)Mainline Build
5299 1 -> (1.1)Mainline Build
5300 2->(1.04) Stability Build
5301 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005302 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005303 ((versionReported.minor>=1) && (versionReported.version>=1)))
5304 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5305 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005306
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005307 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005308 {
5309#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5310 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5311 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5312#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005313 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5314 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5315 {
5316 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5317 }
5318
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005319 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005320 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005321
5322 } while (0);
5323
5324}
5325
5326/**---------------------------------------------------------------------------
5327
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305328 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5329
5330 \param - pHddCtx - Pointer to the hdd context
5331
5332 \return - true if hardware supports 5GHz
5333
5334 --------------------------------------------------------------------------*/
5335static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5336{
5337 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5338 * then hardware support 5Ghz.
5339 */
5340 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5341 {
5342 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5343 return true;
5344 }
5345 else
5346 {
5347 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5348 __func__);
5349 return false;
5350 }
5351}
5352
5353
5354/**---------------------------------------------------------------------------
5355
Jeff Johnson295189b2012-06-20 16:38:30 -07005356 \brief hdd_wlan_startup() - HDD init function
5357
5358 This is the driver startup code executed once a WLAN device has been detected
5359
5360 \param - dev - Pointer to the underlying device
5361
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005362 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005363
5364 --------------------------------------------------------------------------*/
5365
5366int hdd_wlan_startup(struct device *dev )
5367{
5368 VOS_STATUS status;
5369 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005370 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005371 hdd_context_t *pHddCtx = NULL;
5372 v_CONTEXT_t pVosContext= NULL;
5373#ifdef WLAN_BTAMP_FEATURE
5374 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5375 WLANBAP_ConfigType btAmpConfig;
5376 hdd_config_t *pConfig;
5377#endif
5378 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005380
5381 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 /*
5383 * cfg80211: wiphy allocation
5384 */
5385 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5386
5387 if(wiphy == NULL)
5388 {
5389 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005390 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 }
5392
5393 pHddCtx = wiphy_priv(wiphy);
5394
Jeff Johnson295189b2012-06-20 16:38:30 -07005395 //Initialize the adapter context to zeros.
5396 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5397
Jeff Johnson295189b2012-06-20 16:38:30 -07005398 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005399 hdd_prevent_suspend();
5400 pHddCtx->isLoadUnloadInProgress = TRUE;
5401
5402 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5403
5404 /*Get vos context here bcoz vos_open requires it*/
5405 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5406
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005407 if(pVosContext == NULL)
5408 {
5409 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5410 goto err_free_hdd_context;
5411 }
5412
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 //Save the Global VOSS context in adapter context for future.
5414 pHddCtx->pvosContext = pVosContext;
5415
5416 //Save the adapter context in global context for future.
5417 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5418
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 pHddCtx->parent_dev = dev;
5420
5421 init_completion(&pHddCtx->full_pwr_comp_var);
5422 init_completion(&pHddCtx->standby_comp_var);
5423 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005424 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005425 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +05305426 init_completion(&pHddCtx->driver_crda_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005427
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305428 spin_lock_init(&pHddCtx->schedScan_lock);
5429
Jeff Johnson295189b2012-06-20 16:38:30 -07005430 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5431
5432 // Load all config first as TL config is needed during vos_open
5433 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5434 if(pHddCtx->cfg_ini == NULL)
5435 {
5436 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5437 goto err_free_hdd_context;
5438 }
5439
5440 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5441
5442 // Read and parse the qcom_cfg.ini file
5443 status = hdd_parse_config_ini( pHddCtx );
5444 if ( VOS_STATUS_SUCCESS != status )
5445 {
5446 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5447 __func__, WLAN_INI_FILE);
5448 goto err_config;
5449 }
5450
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305451 /* INI has been read, initialise the configuredMcastBcastFilter with
5452 * INI value as this will serve as the default value
5453 */
5454 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5455 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5456 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305457
5458 if (false == hdd_is_5g_supported(pHddCtx))
5459 {
5460 //5Ghz is not supported.
5461 if (1 != pHddCtx->cfg_ini->nBandCapability)
5462 {
5463 hddLog(VOS_TRACE_LEVEL_INFO,
5464 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5465 pHddCtx->cfg_ini->nBandCapability = 1;
5466 }
5467 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305468
5469 /* If SNR Monitoring is enabled, FW has to parse all beacons
5470 * for calcaluting and storing the average SNR, so set Nth beacon
5471 * filter to 1 to enable FW to parse all the beaocons
5472 */
5473 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5474 {
5475 /* The log level is deliberately set to WARN as overriding
5476 * nthBeaconFilter to 1 will increase power cosumption and this
5477 * might just prove helpful to detect the power issue.
5478 */
5479 hddLog(VOS_TRACE_LEVEL_WARN,
5480 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5481 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5482 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 /*
5484 * cfg80211: Initialization and registration ...
5485 */
5486 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5487 {
5488 hddLog(VOS_TRACE_LEVEL_FATAL,
5489 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5490 goto err_wiphy_reg;
5491 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005492
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005493 // Update VOS trace levels based upon the cfg.ini
5494 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5495 pHddCtx->cfg_ini->vosTraceEnableBAP);
5496 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5497 pHddCtx->cfg_ini->vosTraceEnableTL);
5498 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5499 pHddCtx->cfg_ini->vosTraceEnableWDI);
5500 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5501 pHddCtx->cfg_ini->vosTraceEnableHDD);
5502 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5503 pHddCtx->cfg_ini->vosTraceEnableSME);
5504 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5505 pHddCtx->cfg_ini->vosTraceEnablePE);
5506 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5507 pHddCtx->cfg_ini->vosTraceEnableWDA);
5508 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5509 pHddCtx->cfg_ini->vosTraceEnableSYS);
5510 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5511 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005512 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5513 pHddCtx->cfg_ini->vosTraceEnableSAP);
5514 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5515 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005516
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 // Update WDI trace levels based upon the cfg.ini
5518 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5519 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5520 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5521 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5522 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5523 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5524 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5525 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005526
Jeff Johnson88ba7742013-02-27 14:36:02 -08005527 if (VOS_FTM_MODE == hdd_get_conparam())
5528 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5530 {
5531 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5532 goto err_free_hdd_context;
5533 }
5534 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5535 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005536 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005537
Jeff Johnson88ba7742013-02-27 14:36:02 -08005538 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5540 {
5541 status = vos_watchdog_open(pVosContext,
5542 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5543
5544 if(!VOS_IS_STATUS_SUCCESS( status ))
5545 {
5546 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005547 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005548 }
5549 }
5550
5551 pHddCtx->isLogpInProgress = FALSE;
5552 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5553
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5555 if(!VOS_IS_STATUS_SUCCESS(status))
5556 {
5557 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005558 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005559 }
5560
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 status = vos_open( &pVosContext, 0);
5562 if ( !VOS_IS_STATUS_SUCCESS( status ))
5563 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005564 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5565 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 }
5567
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5569
5570 if ( NULL == pHddCtx->hHal )
5571 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005572 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 goto err_vosclose;
5574 }
5575
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005576 status = vos_preStart( pHddCtx->pvosContext );
5577 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5578 {
5579 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5580 goto err_vosclose;
5581 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005582
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005583 /* Note that the vos_preStart() sequence triggers the cfg download.
5584 The cfg download must occur before we update the SME config
5585 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 status = hdd_set_sme_config( pHddCtx );
5587
5588 if ( VOS_STATUS_SUCCESS != status )
5589 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005590 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5591 goto err_vosclose;
5592 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005593
5594 //Initialize the WMM module
5595 status = hdd_wmm_init(pHddCtx);
5596 if (!VOS_IS_STATUS_SUCCESS(status))
5597 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005598 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 goto err_vosclose;
5600 }
5601
Jeff Johnson295189b2012-06-20 16:38:30 -07005602 /* In the integrated architecture we update the configuration from
5603 the INI file and from NV before vOSS has been started so that
5604 the final contents are available to send down to the cCPU */
5605
5606 // Apply the cfg.ini to cfg.dat
5607 if (FALSE == hdd_update_config_dat(pHddCtx))
5608 {
5609 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5610 goto err_vosclose;
5611 }
5612
5613 // Apply the NV to cfg.dat
5614 /* Prima Update MAC address only at here */
5615 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5616 {
5617#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5618 /* There was not a valid set of MAC Addresses in NV. See if the
5619 default addresses were modified by the cfg.ini settings. If so,
5620 we'll use them, but if not, we'll autogenerate a set of MAC
5621 addresses based upon the device serial number */
5622
5623 static const v_MACADDR_t default_address =
5624 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5625 unsigned int serialno;
5626 int i;
5627
5628 serialno = wcnss_get_serial_number();
5629 if ((0 != serialno) &&
5630 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5631 sizeof(default_address))))
5632 {
5633 /* cfg.ini has the default address, invoke autogen logic */
5634
5635 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5636 bytes of the serial number that can be used to generate
5637 the other 3 bytes of the MAC address. Mask off all but
5638 the lower 3 bytes (this will also make sure we don't
5639 overflow in the next step) */
5640 serialno &= 0x00FFFFFF;
5641
5642 /* we need a unique address for each session */
5643 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5644
5645 /* autogen all addresses */
5646 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5647 {
5648 /* start with the entire default address */
5649 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5650 /* then replace the lower 3 bytes */
5651 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5652 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5653 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5654
5655 serialno++;
5656 }
5657
5658 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5659 MAC_ADDRESS_STR,
5660 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5661 }
5662 else
5663#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5664 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005665 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005666 "%s: Invalid MAC address in NV, using MAC from ini file "
5667 MAC_ADDRESS_STR, __func__,
5668 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5669 }
5670 }
5671 {
5672 eHalStatus halStatus;
5673 // Set the MAC Address
5674 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5675 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5676 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5677 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5678
5679 if (!HAL_STATUS_SUCCESS( halStatus ))
5680 {
5681 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5682 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005683 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005684 }
5685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005686
5687 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5688 Note: Firmware image will be read and downloaded inside vos_start API */
5689 status = vos_start( pHddCtx->pvosContext );
5690 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5691 {
5692 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5693 goto err_vosclose;
5694 }
5695
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005696 /* Exchange capability info between Host and FW and also get versioning info from FW */
5697 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005698
5699 status = hdd_post_voss_start_config( pHddCtx );
5700 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5701 {
5702 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5703 __func__);
5704 goto err_vosstop;
5705 }
5706
Jeff Johnson295189b2012-06-20 16:38:30 -07005707 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5708 {
5709 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5710 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5711 }
5712 else
5713 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5715 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5716 if (pAdapter != NULL)
5717 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305718 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005719 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305720 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5721 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5722 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005723
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305724 /* Generate the P2P Device Address. This consists of the device's
5725 * primary MAC address with the locally administered bit set.
5726 */
5727 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005728 }
5729 else
5730 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305731 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5732 if (p2p_dev_addr != NULL)
5733 {
5734 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5735 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5736 }
5737 else
5738 {
5739 hddLog(VOS_TRACE_LEVEL_FATAL,
5740 "%s: Failed to allocate mac_address for p2p_device",
5741 __func__);
5742 goto err_close_adapter;
5743 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005745
5746 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5747 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5748 if ( NULL == pP2pAdapter )
5749 {
5750 hddLog(VOS_TRACE_LEVEL_FATAL,
5751 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005752 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005753 goto err_close_adapter;
5754 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005755 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005756 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005757
5758 if( pAdapter == NULL )
5759 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005760 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5761 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005762 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005763
Jeff Johnson295189b2012-06-20 16:38:30 -07005764#ifdef WLAN_BTAMP_FEATURE
5765 vStatus = WLANBAP_Open(pVosContext);
5766 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5767 {
5768 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5769 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005770 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 }
5772
5773 vStatus = BSL_Init(pVosContext);
5774 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5775 {
5776 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5777 "%s: Failed to Init BSL",__func__);
5778 goto err_bap_close;
5779 }
5780 vStatus = WLANBAP_Start(pVosContext);
5781 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5782 {
5783 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5784 "%s: Failed to start TL",__func__);
5785 goto err_bap_close;
5786 }
5787
5788 pConfig = pHddCtx->cfg_ini;
5789 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5790 status = WLANBAP_SetConfig(&btAmpConfig);
5791
5792#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005793
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005794#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5795 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5796 {
5797 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5798 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5799 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5800 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5801 }
5802#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005803#ifdef FEATURE_WLAN_SCAN_PNO
5804 /*SME must send channel update configuration to RIVA*/
5805 sme_UpdateChannelConfig(pHddCtx->hHal);
5806#endif
5807
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 /* Register with platform driver as client for Suspend/Resume */
5809 status = hddRegisterPmOps(pHddCtx);
5810 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5811 {
5812 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5813#ifdef WLAN_BTAMP_FEATURE
5814 goto err_bap_stop;
5815#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005816 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005817#endif //WLAN_BTAMP_FEATURE
5818 }
5819
Yue Ma0d4891e2013-08-06 17:01:45 -07005820 /* Open debugfs interface */
5821 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5822 {
5823 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5824 "%s: hdd_debugfs_init failed!", __func__);
5825 goto err_close_debugfs;
5826 }
5827
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 /* Register TM level change handler function to the platform */
5829 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5830 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5831 {
5832 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5833 goto err_unregister_pmops;
5834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005835
5836 /* register for riva power on lock to platform driver */
5837 if (req_riva_power_on_lock("wlan"))
5838 {
5839 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5840 __func__);
5841 goto err_unregister_pmops;
5842 }
5843
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 // register net device notifier for device change notification
5845 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5846
5847 if(ret < 0)
5848 {
5849 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5850 goto err_free_power_on_lock;
5851 }
5852
5853 //Initialize the nlink service
5854 if(nl_srv_init() != 0)
5855 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 goto err_reg_netdev;
5858 }
5859
5860 //Initialize the BTC service
5861 if(btc_activate_service(pHddCtx) != 0)
5862 {
5863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5864 goto err_nl_srv;
5865 }
5866
5867#ifdef PTT_SOCK_SVC_ENABLE
5868 //Initialize the PTT service
5869 if(ptt_sock_activate_svc(pHddCtx) != 0)
5870 {
5871 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5872 goto err_nl_srv;
5873 }
5874#endif
5875
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005877 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005879 /* Action frame registered in one adapter which will
5880 * applicable to all interfaces
5881 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005882 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005884
5885 mutex_init(&pHddCtx->sap_lock);
5886
5887 pHddCtx->isLoadUnloadInProgress = FALSE;
5888
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005889#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005890#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5891 /* Initialize the wake lcok */
5892 wake_lock_init(&pHddCtx->rx_wake_lock,
5893 WAKE_LOCK_SUSPEND,
5894 "qcom_rx_wakelock");
5895#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005896 /* Initialize the wake lcok */
5897 wake_lock_init(&pHddCtx->sap_wake_lock,
5898 WAKE_LOCK_SUSPEND,
5899 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005900#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005901
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005902 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5903 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005904
5905 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5906 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305907
Jeff Johnsone7245742012-09-05 17:12:55 -07005908 // Initialize the restart logic
5909 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305910
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305911 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5912 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5913 {
5914 hddLog(VOS_TRACE_LEVEL_ERROR,
5915 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5916 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005917
5918 //Register the traffic monitor timer now
5919 if ( pHddCtx->cfg_ini->dynSplitscan)
5920 {
5921 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
5922 VOS_TIMER_TYPE_SW,
5923 hdd_tx_rx_pkt_cnt_stat_timer_handler,
5924 (void *)pHddCtx);
5925 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 goto success;
5927
5928err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005929#ifdef WLAN_KD_READY_NOTIFIER
5930 nl_srv_exit(pHddCtx->ptt_pid);
5931#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005932 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005933#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005934err_reg_netdev:
5935 unregister_netdevice_notifier(&hdd_netdev_notifier);
5936
5937err_free_power_on_lock:
5938 free_riva_power_on_lock("wlan");
5939
5940err_unregister_pmops:
5941 hddDevTmUnregisterNotifyCallback(pHddCtx);
5942 hddDeregisterPmOps(pHddCtx);
5943
Yue Ma0d4891e2013-08-06 17:01:45 -07005944err_close_debugfs:
5945 hdd_debugfs_exit(pHddCtx);
5946
Jeff Johnson295189b2012-06-20 16:38:30 -07005947#ifdef WLAN_BTAMP_FEATURE
5948err_bap_stop:
5949 WLANBAP_Stop(pVosContext);
5950#endif
5951
5952#ifdef WLAN_BTAMP_FEATURE
5953err_bap_close:
5954 WLANBAP_Close(pVosContext);
5955#endif
5956
Jeff Johnson295189b2012-06-20 16:38:30 -07005957err_close_adapter:
5958 hdd_close_all_adapters( pHddCtx );
5959
5960err_vosstop:
5961 vos_stop(pVosContext);
5962
5963err_vosclose:
5964 status = vos_sched_close( pVosContext );
5965 if (!VOS_IS_STATUS_SUCCESS(status)) {
5966 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5967 "%s: Failed to close VOSS Scheduler", __func__);
5968 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5969 }
5970 vos_close(pVosContext );
5971
Jeff Johnson295189b2012-06-20 16:38:30 -07005972err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005973 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005974
5975err_wdclose:
5976 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5977 vos_watchdog_close(pVosContext);
5978
Jeff Johnson295189b2012-06-20 16:38:30 -07005979err_wiphy_reg:
5980 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005981
5982err_config:
5983 kfree(pHddCtx->cfg_ini);
5984 pHddCtx->cfg_ini= NULL;
5985
5986err_free_hdd_context:
5987 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 wiphy_free(wiphy) ;
5989 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005990 VOS_BUG(1);
5991
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005992 if (hdd_is_ssr_required())
5993 {
5994 /* WDI timeout had happened during load, so SSR is needed here */
5995 subsystem_restart("wcnss");
5996 msleep(5000);
5997 }
5998 hdd_set_ssr_required (VOS_FALSE);
5999
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006000 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006001
6002success:
6003 EXIT();
6004 return 0;
6005}
6006
6007/**---------------------------------------------------------------------------
6008
Jeff Johnson32d95a32012-09-10 13:15:23 -07006009 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006010
Jeff Johnson32d95a32012-09-10 13:15:23 -07006011 This is the driver entry point - called in different timeline depending
6012 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006013
6014 \param - None
6015
6016 \return - 0 for success, non zero for failure
6017
6018 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006019static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006020{
6021 VOS_STATUS status;
6022 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006023 struct device *dev = NULL;
6024 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006025#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6026 int max_retries = 0;
6027#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306029#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6030 vos_wconn_trace_init();
6031#endif
6032
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 ENTER();
6034
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006035#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006036 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006037#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006038
6039 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6040 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6041
6042 //Power Up Libra WLAN card first if not already powered up
6043 status = vos_chipPowerUp(NULL,NULL,NULL);
6044 if (!VOS_IS_STATUS_SUCCESS(status))
6045 {
6046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6047 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306048#ifdef WLAN_OPEN_SOURCE
6049 wake_lock_destroy(&wlan_wake_lock);
6050#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006051 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006052 }
6053
Jeff Johnson295189b2012-06-20 16:38:30 -07006054#ifdef ANI_BUS_TYPE_PCI
6055
6056 dev = wcnss_wlan_get_device();
6057
6058#endif // ANI_BUS_TYPE_PCI
6059
6060#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006061
6062#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6063 /* wait until WCNSS driver downloads NV */
6064 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6065 msleep(1000);
6066 }
6067 if (max_retries >= 5) {
6068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306069#ifdef WLAN_OPEN_SOURCE
6070 wake_lock_destroy(&wlan_wake_lock);
6071#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006072 return -ENODEV;
6073 }
6074#endif
6075
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 dev = wcnss_wlan_get_device();
6077#endif // ANI_BUS_TYPE_PLATFORM
6078
6079
6080 do {
6081 if (NULL == dev) {
6082 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6083 ret_status = -1;
6084 break;
6085 }
6086
6087#ifdef MEMORY_DEBUG
6088 vos_mem_init();
6089#endif
6090
6091#ifdef TIMER_MANAGER
6092 vos_timer_manager_init();
6093#endif
6094
6095 /* Preopen VOSS so that it is ready to start at least SAL */
6096 status = vos_preOpen(&pVosContext);
6097
6098 if (!VOS_IS_STATUS_SUCCESS(status))
6099 {
6100 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6101 ret_status = -1;
6102 break;
6103 }
6104
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006105#ifndef MODULE
6106 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6107 */
6108 hdd_set_conparam((v_UINT_t)con_mode);
6109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006110
6111 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006112 if (hdd_wlan_startup(dev))
6113 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006114 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006115 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006116 vos_preClose( &pVosContext );
6117 ret_status = -1;
6118 break;
6119 }
6120
6121 /* Cancel the vote for XO Core ON
6122 * This is done here for safety purposes in case we re-initialize without turning
6123 * it OFF in any error scenario.
6124 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006125 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006126 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006127 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006128 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6129 {
6130 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6131 " Power consumed will be high\n");
6132 }
6133 } while (0);
6134
6135 if (0 != ret_status)
6136 {
6137 //Assert Deep sleep signal now to put Libra HW in lowest power state
6138 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6139 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6140
6141 //Vote off any PMIC voltage supplies
6142 vos_chipPowerDown(NULL, NULL, NULL);
6143#ifdef TIMER_MANAGER
6144 vos_timer_exit();
6145#endif
6146#ifdef MEMORY_DEBUG
6147 vos_mem_exit();
6148#endif
6149
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006150#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6154 }
6155 else
6156 {
6157 //Send WLAN UP indication to Nlink Service
6158 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6159
6160 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006161 }
6162
6163 EXIT();
6164
6165 return ret_status;
6166}
6167
Jeff Johnson32d95a32012-09-10 13:15:23 -07006168/**---------------------------------------------------------------------------
6169
6170 \brief hdd_module_init() - Init Function
6171
6172 This is the driver entry point (invoked when module is loaded using insmod)
6173
6174 \param - None
6175
6176 \return - 0 for success, non zero for failure
6177
6178 --------------------------------------------------------------------------*/
6179#ifdef MODULE
6180static int __init hdd_module_init ( void)
6181{
6182 return hdd_driver_init();
6183}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006184#else /* #ifdef MODULE */
6185static int __init hdd_module_init ( void)
6186{
6187 /* Driver initialization is delayed to fwpath_changed_handler */
6188 return 0;
6189}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006190#endif /* #ifdef MODULE */
6191
Jeff Johnson295189b2012-06-20 16:38:30 -07006192
6193/**---------------------------------------------------------------------------
6194
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006195 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006196
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006197 This is the driver exit point (invoked when module is unloaded using rmmod
6198 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006199
6200 \param - None
6201
6202 \return - None
6203
6204 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006205static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006206{
6207 hdd_context_t *pHddCtx = NULL;
6208 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006209 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006210
6211 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6212
6213 //Get the global vos context
6214 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6215
6216 if(!pVosContext)
6217 {
6218 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6219 goto done;
6220 }
6221
6222 //Get the HDD context.
6223 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6224
6225 if(!pHddCtx)
6226 {
6227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6228 }
6229 else
6230 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006231 while(isWDresetInProgress()) {
6232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6233 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006234 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006235
6236 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6238 "%s:SSR never completed, fatal error", __func__);
6239 VOS_BUG(0);
6240 }
6241 }
6242
Jeff Johnson295189b2012-06-20 16:38:30 -07006243
6244 pHddCtx->isLoadUnloadInProgress = TRUE;
6245 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6246
6247 //Do all the cleanup before deregistering the driver
6248 hdd_wlan_exit(pHddCtx);
6249 }
6250
Jeff Johnson295189b2012-06-20 16:38:30 -07006251 vos_preClose( &pVosContext );
6252
6253#ifdef TIMER_MANAGER
6254 vos_timer_exit();
6255#endif
6256#ifdef MEMORY_DEBUG
6257 vos_mem_exit();
6258#endif
6259
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306260#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6261 vos_wconn_trace_exit();
6262#endif
6263
Jeff Johnson295189b2012-06-20 16:38:30 -07006264done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006265#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006267#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6269}
6270
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006271/**---------------------------------------------------------------------------
6272
6273 \brief hdd_module_exit() - Exit function
6274
6275 This is the driver exit point (invoked when module is unloaded using rmmod)
6276
6277 \param - None
6278
6279 \return - None
6280
6281 --------------------------------------------------------------------------*/
6282static void __exit hdd_module_exit(void)
6283{
6284 hdd_driver_exit();
6285}
6286
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006287#ifdef MODULE
6288static int fwpath_changed_handler(const char *kmessage,
6289 struct kernel_param *kp)
6290{
Jeff Johnson76052702013-04-16 13:55:05 -07006291 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006292}
6293
6294static int con_mode_handler(const char *kmessage,
6295 struct kernel_param *kp)
6296{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006297 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006298}
6299#else /* #ifdef MODULE */
6300/**---------------------------------------------------------------------------
6301
Jeff Johnson76052702013-04-16 13:55:05 -07006302 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006303
Jeff Johnson76052702013-04-16 13:55:05 -07006304 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006305 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006306 - invoked when module parameter fwpath is modified from userspace to signal
6307 initializing the WLAN driver or when con_mode is modified from userspace
6308 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006309
6310 \return - 0 for success, non zero for failure
6311
6312 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006313static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006314{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006315 int ret_status;
6316
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006317 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006318 ret_status = hdd_driver_init();
6319 wlan_hdd_inited = ret_status ? 0 : 1;
6320 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006321 }
6322
6323 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006324
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006325 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006326
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006327 ret_status = hdd_driver_init();
6328 wlan_hdd_inited = ret_status ? 0 : 1;
6329 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006330}
6331
Jeff Johnson295189b2012-06-20 16:38:30 -07006332/**---------------------------------------------------------------------------
6333
Jeff Johnson76052702013-04-16 13:55:05 -07006334 \brief fwpath_changed_handler() - Handler Function
6335
6336 Handle changes to the fwpath parameter
6337
6338 \return - 0 for success, non zero for failure
6339
6340 --------------------------------------------------------------------------*/
6341static int fwpath_changed_handler(const char *kmessage,
6342 struct kernel_param *kp)
6343{
6344 int ret;
6345
6346 ret = param_set_copystring(kmessage, kp);
6347 if (0 == ret)
6348 ret = kickstart_driver();
6349 return ret;
6350}
6351
6352/**---------------------------------------------------------------------------
6353
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006354 \brief con_mode_handler() -
6355
6356 Handler function for module param con_mode when it is changed by userspace
6357 Dynamically linked - do nothing
6358 Statically linked - exit and init driver, as in rmmod and insmod
6359
Jeff Johnson76052702013-04-16 13:55:05 -07006360 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006361
Jeff Johnson76052702013-04-16 13:55:05 -07006362 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006363
6364 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006365static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006366{
Jeff Johnson76052702013-04-16 13:55:05 -07006367 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006368
Jeff Johnson76052702013-04-16 13:55:05 -07006369 ret = param_set_int(kmessage, kp);
6370 if (0 == ret)
6371 ret = kickstart_driver();
6372 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006373}
6374#endif /* #ifdef MODULE */
6375
6376/**---------------------------------------------------------------------------
6377
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 \brief hdd_get_conparam() -
6379
6380 This is the driver exit point (invoked when module is unloaded using rmmod)
6381
6382 \param - None
6383
6384 \return - tVOS_CON_MODE
6385
6386 --------------------------------------------------------------------------*/
6387tVOS_CON_MODE hdd_get_conparam ( void )
6388{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006389#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006390 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006391#else
6392 return (tVOS_CON_MODE)curr_con_mode;
6393#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006394}
6395void hdd_set_conparam ( v_UINT_t newParam )
6396{
6397 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006398#ifndef MODULE
6399 curr_con_mode = con_mode;
6400#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006401}
6402/**---------------------------------------------------------------------------
6403
6404 \brief hdd_softap_sta_deauth() - function
6405
6406 This to take counter measure to handle deauth req from HDD
6407
6408 \param - pAdapter - Pointer to the HDD
6409
6410 \param - enable - boolean value
6411
6412 \return - None
6413
6414 --------------------------------------------------------------------------*/
6415
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006416VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006417{
Jeff Johnson295189b2012-06-20 16:38:30 -07006418 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006419 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006420
6421 ENTER();
6422
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006423 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6424 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006425
6426 //Ignore request to deauth bcmc station
6427 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006428 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006429
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006430 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006431
6432 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006433 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006434}
6435
6436/**---------------------------------------------------------------------------
6437
6438 \brief hdd_softap_sta_disassoc() - function
6439
6440 This to take counter measure to handle deauth req from HDD
6441
6442 \param - pAdapter - Pointer to the HDD
6443
6444 \param - enable - boolean value
6445
6446 \return - None
6447
6448 --------------------------------------------------------------------------*/
6449
6450void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6451{
6452 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6453
6454 ENTER();
6455
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306456 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006457
6458 //Ignore request to disassoc bcmc station
6459 if( pDestMacAddress[0] & 0x1 )
6460 return;
6461
6462 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6463}
6464
6465void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6466{
6467 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6468
6469 ENTER();
6470
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306471 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006472
6473 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6474}
6475
Jeff Johnson295189b2012-06-20 16:38:30 -07006476/**---------------------------------------------------------------------------
6477 *
6478 * \brief hdd_get__concurrency_mode() -
6479 *
6480 *
6481 * \param - None
6482 *
6483 * \return - CONCURRENCY MODE
6484 *
6485 * --------------------------------------------------------------------------*/
6486tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6487{
6488 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6489 hdd_context_t *pHddCtx;
6490
6491 if (NULL != pVosContext)
6492 {
6493 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6494 if (NULL != pHddCtx)
6495 {
6496 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6497 }
6498 }
6499
6500 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006501 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006502 return VOS_STA;
6503}
6504
6505/* Decide whether to allow/not the apps power collapse.
6506 * Allow apps power collapse if we are in connected state.
6507 * if not, allow only if we are in IMPS */
6508v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6509{
6510 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006511 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006512 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006513 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6514 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6515 hdd_adapter_t *pAdapter = NULL;
6516 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006517 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006518
Jeff Johnson295189b2012-06-20 16:38:30 -07006519 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6520 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006521
Yathish9f22e662012-12-10 14:21:35 -08006522 concurrent_state = hdd_get_concurrency_mode();
6523
6524#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6525 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6526 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6527 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6528 return TRUE;
6529#endif
6530
Jeff Johnson295189b2012-06-20 16:38:30 -07006531 /*loop through all adapters. TBD fix for Concurrency */
6532 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6533 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6534 {
6535 pAdapter = pAdapterNode->pAdapter;
6536 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6537 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6538 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006539 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006541 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006542 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6543 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006545 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006546 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6547 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006548 return FALSE;
6549 }
6550 }
6551 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6552 pAdapterNode = pNext;
6553 }
6554 return TRUE;
6555}
6556
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006557/* Decides whether to send suspend notification to Riva
6558 * if any adapter is in BMPS; then it is required */
6559v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6560{
6561 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6562 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6563
6564 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6565 {
6566 return TRUE;
6567 }
6568 return FALSE;
6569}
6570
Jeff Johnson295189b2012-06-20 16:38:30 -07006571void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6572{
6573 switch(mode)
6574 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006575 case VOS_STA_MODE:
6576 case VOS_P2P_CLIENT_MODE:
6577 case VOS_P2P_GO_MODE:
6578 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006579 pHddCtx->concurrency_mode |= (1 << mode);
6580 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006581 break;
6582 default:
6583 break;
6584
6585 }
6586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6587 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6588}
6589
6590
6591void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6592{
6593 switch(mode)
6594 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006595 case VOS_STA_MODE:
6596 case VOS_P2P_CLIENT_MODE:
6597 case VOS_P2P_GO_MODE:
6598 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006599 pHddCtx->no_of_sessions[mode]--;
6600 if (!(pHddCtx->no_of_sessions[mode]))
6601 pHddCtx->concurrency_mode &= (~(1 << mode));
6602 break;
6603 default:
6604 break;
6605 }
6606 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6607 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6608}
6609
Jeff Johnsone7245742012-09-05 17:12:55 -07006610/**---------------------------------------------------------------------------
6611 *
6612 * \brief wlan_hdd_restart_init
6613 *
6614 * This function initalizes restart timer/flag. An internal function.
6615 *
6616 * \param - pHddCtx
6617 *
6618 * \return - None
6619 *
6620 * --------------------------------------------------------------------------*/
6621
6622static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6623{
6624 /* Initialize */
6625 pHddCtx->hdd_restart_retries = 0;
6626 atomic_set(&pHddCtx->isRestartInProgress, 0);
6627 vos_timer_init(&pHddCtx->hdd_restart_timer,
6628 VOS_TIMER_TYPE_SW,
6629 wlan_hdd_restart_timer_cb,
6630 pHddCtx);
6631}
6632/**---------------------------------------------------------------------------
6633 *
6634 * \brief wlan_hdd_restart_deinit
6635 *
6636 * This function cleans up the resources used. An internal function.
6637 *
6638 * \param - pHddCtx
6639 *
6640 * \return - None
6641 *
6642 * --------------------------------------------------------------------------*/
6643
6644static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6645{
6646
6647 VOS_STATUS vos_status;
6648 /* Block any further calls */
6649 atomic_set(&pHddCtx->isRestartInProgress, 1);
6650 /* Cleanup */
6651 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6652 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006653 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006654 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6655 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006656 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006657
6658}
6659
6660/**---------------------------------------------------------------------------
6661 *
6662 * \brief wlan_hdd_framework_restart
6663 *
6664 * This function uses a cfg80211 API to start a framework initiated WLAN
6665 * driver module unload/load.
6666 *
6667 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6668 *
6669 *
6670 * \param - pHddCtx
6671 *
6672 * \return - VOS_STATUS_SUCCESS: Success
6673 * VOS_STATUS_E_EMPTY: Adapter is Empty
6674 * VOS_STATUS_E_NOMEM: No memory
6675
6676 * --------------------------------------------------------------------------*/
6677
6678static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6679{
6680 VOS_STATUS status = VOS_STATUS_SUCCESS;
6681 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006682 int len = (sizeof (struct ieee80211_mgmt));
6683 struct ieee80211_mgmt *mgmt = NULL;
6684
6685 /* Prepare the DEAUTH managment frame with reason code */
6686 mgmt = kzalloc(len, GFP_KERNEL);
6687 if(mgmt == NULL)
6688 {
6689 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6690 "%s: memory allocation failed (%d bytes)", __func__, len);
6691 return VOS_STATUS_E_NOMEM;
6692 }
6693 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006694
6695 /* Iterate over all adapters/devices */
6696 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6697 do
6698 {
6699 if( (status == VOS_STATUS_SUCCESS) &&
6700 pAdapterNode &&
6701 pAdapterNode->pAdapter)
6702 {
6703 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6704 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6705 pAdapterNode->pAdapter->dev->name,
6706 pAdapterNode->pAdapter->device_mode,
6707 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006708 /*
6709 * CFG80211 event to restart the driver
6710 *
6711 * 'cfg80211_send_unprot_deauth' sends a
6712 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6713 * of SME(Linux Kernel) state machine.
6714 *
6715 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6716 * the driver.
6717 *
6718 */
6719
6720 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006721 }
6722 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6723 pAdapterNode = pNext;
6724 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6725
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006726
6727 /* Free the allocated management frame */
6728 kfree(mgmt);
6729
Jeff Johnsone7245742012-09-05 17:12:55 -07006730 /* Retry until we unload or reach max count */
6731 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6732 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6733
6734 return status;
6735
6736}
6737/**---------------------------------------------------------------------------
6738 *
6739 * \brief wlan_hdd_restart_timer_cb
6740 *
6741 * Restart timer callback. An internal function.
6742 *
6743 * \param - User data:
6744 *
6745 * \return - None
6746 *
6747 * --------------------------------------------------------------------------*/
6748
6749void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6750{
6751 hdd_context_t *pHddCtx = usrDataForCallback;
6752 wlan_hdd_framework_restart(pHddCtx);
6753 return;
6754
6755}
6756
6757
6758/**---------------------------------------------------------------------------
6759 *
6760 * \brief wlan_hdd_restart_driver
6761 *
6762 * This function sends an event to supplicant to restart the WLAN driver.
6763 *
6764 * This function is called from vos_wlanRestart.
6765 *
6766 * \param - pHddCtx
6767 *
6768 * \return - VOS_STATUS_SUCCESS: Success
6769 * VOS_STATUS_E_EMPTY: Adapter is Empty
6770 * VOS_STATUS_E_ALREADY: Request already in progress
6771
6772 * --------------------------------------------------------------------------*/
6773VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6774{
6775 VOS_STATUS status = VOS_STATUS_SUCCESS;
6776
6777 /* A tight check to make sure reentrancy */
6778 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6779 {
6780 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6781 "%s: WLAN restart is already in progress", __func__);
6782
6783 return VOS_STATUS_E_ALREADY;
6784 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006785 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006786#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006787 wcnss_reset_intr();
6788#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006789
Jeff Johnsone7245742012-09-05 17:12:55 -07006790 return status;
6791}
6792
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006793/*
6794 * API to find if there is any STA or P2P-Client is connected
6795 */
6796VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6797{
6798 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6799}
Jeff Johnsone7245742012-09-05 17:12:55 -07006800
Jeff Johnson295189b2012-06-20 16:38:30 -07006801//Register the module init/exit functions
6802module_init(hdd_module_init);
6803module_exit(hdd_module_exit);
6804
6805MODULE_LICENSE("Dual BSD/GPL");
6806MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6807MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6808
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006809module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6810 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006811
Jeff Johnson76052702013-04-16 13:55:05 -07006812module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006813 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);