blob: 75ec020b1d39f09620e17befbdd3a3c24084e435 [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
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800171#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700172static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700173#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700174/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700175static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700176
177//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700178static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
180static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
181void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800182void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700183
Jeff Johnson295189b2012-06-20 16:38:30 -0700184v_U16_t hdd_select_queue(struct net_device *dev,
185 struct sk_buff *skb);
186
187#ifdef WLAN_FEATURE_PACKET_FILTERING
188static void hdd_set_multicast_list(struct net_device *dev);
189#endif
190
191void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700192int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700193
194extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800195#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
196void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
197static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700201static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
202 tANI_U8 *pTargetApBssid,
203 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700205static int hdd_netdev_notifier_call(struct notifier_block * nb,
206 unsigned long state,
207 void *ndev)
208{
209 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700212#ifdef WLAN_BTAMP_FEATURE
213 VOS_STATUS status;
214 hdd_context_t *pHddCtx;
215#endif
216
217 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700219 (strncmp(dev->name, "p2p", 3)))
220 return NOTIFY_DONE;
221
222 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 return NOTIFY_DONE;
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
Jeff Johnson27cee452013-03-27 11:10:24 -0700228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
236 if (NULL == pHddCtx)
237 {
238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
244 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245
246 switch (state) {
247 case NETDEV_REGISTER:
248 break;
249
250 case NETDEV_UNREGISTER:
251 break;
252
253 case NETDEV_UP:
254 break;
255
256 case NETDEV_DOWN:
257 break;
258
259 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 if(TRUE == pAdapter->isLinkUpSvcNeeded)
261 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 break;
263
264 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 {
267 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 hdd_abort_mac_scan(pAdapter->pHddCtx);
270 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800271 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
273 if(!result)
274 {
275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800276 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279 }
280 else
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
285#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 status = WLANBAP_StopAmp();
288 if(VOS_STATUS_SUCCESS != status )
289 {
290 pHddCtx->isAmpAllowed = VOS_TRUE;
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Failed to stop AMP", __func__);
293 }
294 else
295 {
296 //a state m/c implementation in PAL is TBD to avoid this delay
297 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700298 if ( pHddCtx->isAmpAllowed )
299 {
300 WLANBAP_DeregisterFromHCI();
301 pHddCtx->isAmpAllowed = VOS_FALSE;
302 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#endif //WLAN_BTAMP_FEATURE
305 break;
306
307 default:
308 break;
309 }
310
311 return NOTIFY_DONE;
312}
313
314struct notifier_block hdd_netdev_notifier = {
315 .notifier_call = hdd_netdev_notifier_call,
316};
317
318/*---------------------------------------------------------------------------
319 * Function definitions
320 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700321void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
322void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700325#ifndef MODULE
326/* current con_mode - used only for statically linked driver
327 * con_mode is changed by userspace to indicate a mode change which will
328 * result in calling the module exit and init functions. The module
329 * exit function will clean up based on the value of con_mode prior to it
330 * being changed by userspace. So curr_con_mode records the current con_mode
331 * for exit when con_mode becomes the next mode for init
332 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700333static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700334#endif
335
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800336/**---------------------------------------------------------------------------
337
338 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
339
340 Called immediately after the cfg.ini is read in order to configure
341 the desired trace levels.
342
343 \param - moduleId - module whose trace level is being configured
344 \param - bitmask - bitmask of log levels to be enabled
345
346 \return - void
347
348 --------------------------------------------------------------------------*/
349static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
350{
351 wpt_tracelevel level;
352
353 /* if the bitmask is the default value, then a bitmask was not
354 specified in cfg.ini, so leave the logging level alone (it
355 will remain at the "compiled in" default value) */
356 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
357 {
358 return;
359 }
360
361 /* a mask was specified. start by disabling all logging */
362 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
363
364 /* now cycle through the bitmask until all "set" bits are serviced */
365 level = VOS_TRACE_LEVEL_FATAL;
366 while (0 != bitmask)
367 {
368 if (bitmask & 1)
369 {
370 vos_trace_setValue(moduleId, level, 1);
371 }
372 level++;
373 bitmask >>= 1;
374 }
375}
376
377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378/**---------------------------------------------------------------------------
379
380 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels in the WDI.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 wpalTraceSetLevel(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
Jeff Johnson295189b2012-06-20 16:38:30 -0700418
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530419/*
420 * FUNCTION: wlan_hdd_validate_context
421 * This function is used to check the HDD context
422 */
423int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
424{
425 ENTER();
426
427 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: HDD context is Null", __func__);
431 return -ENODEV;
432 }
433
434 if (pHddCtx->isLogpInProgress)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: LOGP in Progress. Ignore!!!", __func__);
438 return -EAGAIN;
439 }
440
441 if (pHddCtx->isLoadUnloadInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447 return 0;
448}
449
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530450void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
451{
452 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
454 hdd_config_t *cfg_param;
455 eCsrPhyMode phyMode;
456
457 if (NULL == pHddCtx)
458 {
459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
460 "HDD Context is null !!");
461 return ;
462 }
463
464 cfg_param = pHddCtx->cfg_ini;
465
466 if (NULL == cfg_param)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
469 "cfg_params not available !!");
470 return ;
471 }
472
473 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
474
475 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
476 {
477 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
478 (eCSR_DOT11_MODE_11ac == phyMode) ||
479 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
482 "Setting phymode to 11n!!");
483 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
484 }
485 }
486 else
487 {
488 /*New country Supports 11ac as well resetting value back from .ini*/
489 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
490 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
491 return ;
492 }
493
494 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
495 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
496 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
497 {
498 VOS_STATUS vosStatus;
499
500 // need to issue a disconnect to CSR.
501 INIT_COMPLETION(pAdapter->disconnect_comp_var);
502 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
503 pAdapter->sessionId,
504 eCSR_DISCONNECT_REASON_UNSPECIFIED );
505
506 if (VOS_STATUS_SUCCESS == vosStatus)
507 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
509
510 }
511}
512
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700513void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
514{
515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
516 hdd_config_t *cfg_param;
517
518 if (NULL == pHddCtx)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "HDD Context is null !!");
522 return ;
523 }
524
525 cfg_param = pHddCtx->cfg_ini;
526
527 if (NULL == cfg_param)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
530 "cfg_params not available !!");
531 return ;
532 }
533
534 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
535 {
536 /*New country doesn't support DFS */
537 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
538 }
539 else
540 {
541 /*New country Supports DFS as well resetting value back from .ini*/
542 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
543 }
544
545}
546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
548{
549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
550 hdd_priv_data_t priv_data;
551 tANI_U8 *command = NULL;
552 int ret = 0;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 ret = -ENODEV;
559 goto exit;
560 }
561
Jeff Johnsone7245742012-09-05 17:12:55 -0700562 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 {
564 ret = -EINVAL;
565 goto exit;
566 }
567
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700568 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
569 {
570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s:LOGP in Progress. Ignore!!!", __func__);
572 ret = -EBUSY;
573 goto exit;
574 }
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
577 {
578 ret = -EFAULT;
579 goto exit;
580 }
581
582 command = kmalloc(priv_data.total_len, GFP_KERNEL);
583 if (!command)
584 {
585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 ret = -ENOMEM;
588 goto exit;
589 }
590
591 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
592 {
593 ret = -EFAULT;
594 goto exit;
595 }
596
597 if ((SIOCDEVPRIVATE + 1) == cmd)
598 {
599 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
600
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700602 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700603
604 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
605 {
606 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
607 sizeof(tSirMacAddr)))
608 {
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 ret = -EFAULT;
612 }
613 }
Amar Singhal0974e402013-02-12 14:27:46 -0800614 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 {
Amar Singhal0974e402013-02-12 14:27:46 -0800616 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800620
621 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800624 "%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 -0700625 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626 ret = hdd_setBand_helper(dev, ptr);
627 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700628 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
629 {
630 char *country_code;
631
632 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633
634 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530637 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700638 if( 0 != ret )
639 {
640 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
641 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
642
643 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700644 }
645 /*
646 command should be a string having format
647 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
648 */
Amar Singhal0974e402013-02-12 14:27:46 -0800649 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700650 {
Amar Singhal0974e402013-02-12 14:27:46 -0800651 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700652
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700654 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700655
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800656 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700657 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800658 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
659 {
660 int suspend = 0;
661 tANI_U8 *ptr = (tANI_U8*)command + 15;
662
663 suspend = *ptr - '0';
664 hdd_set_wlan_suspend_mode(suspend);
665 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800666#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
667 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
668 {
669 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700670 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800671 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
672 eHalStatus status = eHAL_STATUS_SUCCESS;
673
674 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
675 value = value + 15;
676
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700677 /* Convert the value from ascii to integer */
678 ret = kstrtos8(value, 10, &rssi);
679 if (ret < 0)
680 {
681 /* If the input value is greater than max value of datatype, then also
682 kstrtou8 fails */
683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
684 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
685 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
686 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
687 ret = -EINVAL;
688 goto exit;
689 }
690
Srinivas Girigowdade697412013-02-14 16:31:48 -0800691 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700692
Srinivas Girigowdade697412013-02-14 16:31:48 -0800693 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
694 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
695 {
696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
697 "Neighbor lookup threshold value %d is out of range"
698 " (Min: %d Max: %d)", lookUpThreshold,
699 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
700 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
701 ret = -EINVAL;
702 goto exit;
703 }
704
705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
706 "%s: Received Command to Set Roam trigger"
707 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
708
709 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
710 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
711 if (eHAL_STATUS_SUCCESS != status)
712 {
713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
714 "%s: Failed to set roam trigger, try again", __func__);
715 ret = -EPERM;
716 goto exit;
717 }
718
719 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
720 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
721 }
722 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
723 {
724 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
725 int rssi = (-1) * lookUpThreshold;
726 char extra[32];
727 tANI_U8 len = 0;
728
729 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
730 if (copy_to_user(priv_data.buf, &extra, len + 1))
731 {
732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
733 "%s: failed to copy data to user buffer", __func__);
734 ret = -EFAULT;
735 goto exit;
736 }
737 }
738 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
739 {
740 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700741 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700742 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700743
Srinivas Girigowdade697412013-02-14 16:31:48 -0800744 /* input refresh period is in terms of seconds */
745 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
746 value = value + 18;
747 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700748 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800749 if (ret < 0)
750 {
751 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700752 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700754 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800755 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700756 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
757 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800758 ret = -EINVAL;
759 goto exit;
760 }
761
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700762 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
763 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800764 {
765 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700766 "Roam scan period value %d is out of range"
767 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700768 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
769 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800770 ret = -EINVAL;
771 goto exit;
772 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700773 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800774
775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
776 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700777 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800778
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700779 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
780 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800781 }
782 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
783 {
784 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
785 char extra[32];
786 tANI_U8 len = 0;
787
788 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
789 /* Returned value is in units of seconds */
790 if (copy_to_user(priv_data.buf, &extra, len + 1))
791 {
792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
793 "%s: failed to copy data to user buffer", __func__);
794 ret = -EFAULT;
795 goto exit;
796 }
797 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700798 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
799 {
800 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700801 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700802 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700803
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700804 /* input refresh period is in terms of seconds */
805 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
806 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700807
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700808 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700809 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700810 if (ret < 0)
811 {
812 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700813 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700815 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700816 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700817 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
818 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
819 ret = -EINVAL;
820 goto exit;
821 }
822
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700823 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
824 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
825 {
826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
827 "Neighbor scan results refresh period value %d is out of range"
828 " (Min: %d Max: %d)", roamScanRefreshPeriod,
829 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
830 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
831 ret = -EINVAL;
832 goto exit;
833 }
834 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
835
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
837 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700838 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700839
840 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
841 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
842 }
843 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
844 {
845 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
846 char extra[32];
847 tANI_U8 len = 0;
848
849 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
850 /* Returned value is in units of seconds */
851 if (copy_to_user(priv_data.buf, &extra, len + 1))
852 {
853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
854 "%s: failed to copy data to user buffer", __func__);
855 ret = -EFAULT;
856 goto exit;
857 }
858 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700859#ifdef FEATURE_WLAN_LFR
860 /* SETROAMMODE */
861 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
862 {
863 tANI_U8 *value = command;
864 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
865
866 /* Move pointer to ahead of SETROAMMODE<delimiter> */
867 value = value + SIZE_OF_SETROAMMODE + 1;
868
869 /* Convert the value from ascii to integer */
870 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
871 if (ret < 0)
872 {
873 /* If the input value is greater than max value of datatype, then also
874 kstrtou8 fails */
875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
876 "%s: kstrtou8 failed range [%d - %d]", __func__,
877 CFG_LFR_FEATURE_ENABLED_MIN,
878 CFG_LFR_FEATURE_ENABLED_MAX);
879 ret = -EINVAL;
880 goto exit;
881 }
882 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
883 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
884 {
885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
886 "Roam Mode value %d is out of range"
887 " (Min: %d Max: %d)", roamMode,
888 CFG_LFR_FEATURE_ENABLED_MIN,
889 CFG_LFR_FEATURE_ENABLED_MAX);
890 ret = -EINVAL;
891 goto exit;
892 }
893
894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
895 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
896 /*
897 * Note that
898 * SETROAMMODE 0 is to enable LFR while
899 * SETROAMMODE 1 is to disable LFR, but
900 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
901 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
902 */
903 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
904 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
905 else
906 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
907
908 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
909 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
910 }
911 /* GETROAMMODE */
912 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
913 {
914 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
915 char extra[32];
916 tANI_U8 len = 0;
917
918 /*
919 * roamMode value shall be inverted because the sementics is different.
920 */
921 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
922 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
923 else
924 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
925
926 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
927 if (copy_to_user(priv_data.buf, &extra, len + 1))
928 {
929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
930 "%s: failed to copy data to user buffer", __func__);
931 ret = -EFAULT;
932 goto exit;
933 }
934 }
935#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800936#endif
937#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
938 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
939 {
940 tANI_U8 *value = command;
941 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
942
943 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
944 value = value + 13;
945 /* Convert the value from ascii to integer */
946 ret = kstrtou8(value, 10, &roamRssiDiff);
947 if (ret < 0)
948 {
949 /* If the input value is greater than max value of datatype, then also
950 kstrtou8 fails */
951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
952 "%s: kstrtou8 failed range [%d - %d]", __func__,
953 CFG_ROAM_RSSI_DIFF_MIN,
954 CFG_ROAM_RSSI_DIFF_MAX);
955 ret = -EINVAL;
956 goto exit;
957 }
958
959 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
960 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
961 {
962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
963 "Roam rssi diff value %d is out of range"
964 " (Min: %d Max: %d)", roamRssiDiff,
965 CFG_ROAM_RSSI_DIFF_MIN,
966 CFG_ROAM_RSSI_DIFF_MAX);
967 ret = -EINVAL;
968 goto exit;
969 }
970
971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
972 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
973
974 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
975 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
976 }
977 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
978 {
979 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
980 char extra[32];
981 tANI_U8 len = 0;
982
983 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
984 if (copy_to_user(priv_data.buf, &extra, len + 1))
985 {
986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
987 "%s: failed to copy data to user buffer", __func__);
988 ret = -EFAULT;
989 goto exit;
990 }
991 }
992#endif
993#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
994 else if (strncmp(command, "GETBAND", 7) == 0)
995 {
996 int band = -1;
997 char extra[32];
998 tANI_U8 len = 0;
999 hdd_getBand_helper(pHddCtx, &band);
1000
1001 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1002 if (copy_to_user(priv_data.buf, &extra, len + 1))
1003 {
1004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1005 "%s: failed to copy data to user buffer", __func__);
1006 ret = -EFAULT;
1007 goto exit;
1008 }
1009 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001010 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1011 {
1012 tANI_U8 *value = command;
1013 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1014 tANI_U8 numChannels = 0;
1015 eHalStatus status = eHAL_STATUS_SUCCESS;
1016
1017 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1018 if (eHAL_STATUS_SUCCESS != status)
1019 {
1020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1021 "%s: Failed to parse channel list information", __func__);
1022 ret = -EINVAL;
1023 goto exit;
1024 }
1025
1026 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1027 {
1028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1029 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1030 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1031 ret = -EINVAL;
1032 goto exit;
1033 }
1034 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1035 numChannels);
1036 if (eHAL_STATUS_SUCCESS != status)
1037 {
1038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1039 "%s: Failed to update channel list information", __func__);
1040 ret = -EINVAL;
1041 goto exit;
1042 }
1043 }
1044 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1045 {
1046 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1047 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001048 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001049 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001050 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001051
1052 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1053 ChannelList, &numChannels ))
1054 {
1055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1056 "%s: failed to get roam scan channel list", __func__);
1057 ret = -EFAULT;
1058 goto exit;
1059 }
1060 /* output channel list is of the format
1061 [Number of roam scan channels][Channel1][Channel2]... */
1062 /* copy the number of channels in the 0th index */
1063 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1064 for (j = 0; (j < numChannels); j++)
1065 {
1066 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1067 }
1068
1069 if (copy_to_user(priv_data.buf, &extra, len + 1))
1070 {
1071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1072 "%s: failed to copy data to user buffer", __func__);
1073 ret = -EFAULT;
1074 goto exit;
1075 }
1076 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001077 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1078 {
1079 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1080 char extra[32];
1081 tANI_U8 len = 0;
1082
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001083 /* Check if the features OKC/CCX/11R are supported simultaneously,
1084 then this operation is not permitted (return FAILURE) */
1085 if (ccxMode &&
1086 hdd_is_okc_mode_enabled(pHddCtx) &&
1087 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1088 {
1089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1090 "%s: OKC/CCX/11R are supported simultaneously"
1091 " hence this operation is not permitted!", __func__);
1092 ret = -EPERM;
1093 goto exit;
1094 }
1095
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001096 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1097 if (copy_to_user(priv_data.buf, &extra, len + 1))
1098 {
1099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: failed to copy data to user buffer", __func__);
1101 ret = -EFAULT;
1102 goto exit;
1103 }
1104 }
1105 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1106 {
1107 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1108 char extra[32];
1109 tANI_U8 len = 0;
1110
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001111 /* Check if the features OKC/CCX/11R are supported simultaneously,
1112 then this operation is not permitted (return FAILURE) */
1113 if (okcMode &&
1114 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1115 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1118 "%s: OKC/CCX/11R are supported simultaneously"
1119 " hence this operation is not permitted!", __func__);
1120 ret = -EPERM;
1121 goto exit;
1122 }
1123
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001124 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1125 if (copy_to_user(priv_data.buf, &extra, len + 1))
1126 {
1127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1128 "%s: failed to copy data to user buffer", __func__);
1129 ret = -EFAULT;
1130 goto exit;
1131 }
1132 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001133 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001134 {
1135 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1136 char extra[32];
1137 tANI_U8 len = 0;
1138
1139 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1140 if (copy_to_user(priv_data.buf, &extra, len + 1))
1141 {
1142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1143 "%s: failed to copy data to user buffer", __func__);
1144 ret = -EFAULT;
1145 goto exit;
1146 }
1147 }
1148 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1149 {
1150 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1151 char extra[32];
1152 tANI_U8 len = 0;
1153
1154 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1155 if (copy_to_user(priv_data.buf, &extra, len + 1))
1156 {
1157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1158 "%s: failed to copy data to user buffer", __func__);
1159 ret = -EFAULT;
1160 goto exit;
1161 }
1162 }
1163 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1164 {
1165 tANI_U8 *value = command;
1166 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1167
1168 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1169 value = value + 26;
1170 /* Convert the value from ascii to integer */
1171 ret = kstrtou8(value, 10, &minTime);
1172 if (ret < 0)
1173 {
1174 /* If the input value is greater than max value of datatype, then also
1175 kstrtou8 fails */
1176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: kstrtou8 failed range [%d - %d]", __func__,
1178 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1179 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1180 ret = -EINVAL;
1181 goto exit;
1182 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001183 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1184 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1185 {
1186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1187 "scan min channel time value %d is out of range"
1188 " (Min: %d Max: %d)", minTime,
1189 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1190 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1191 ret = -EINVAL;
1192 goto exit;
1193 }
1194
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1196 "%s: Received Command to change channel min time = %d", __func__, minTime);
1197
1198 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1199 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1200 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001201 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1202 {
1203 tANI_U8 *value = command;
1204 tANI_U8 channel = 0;
1205 tANI_U8 dwellTime = 0;
1206 tANI_U8 bufLen = 0;
1207 tANI_U8 *buf = NULL;
1208 tSirMacAddr targetApBssid;
1209 eHalStatus status = eHAL_STATUS_SUCCESS;
1210 struct ieee80211_channel chan;
1211 tANI_U8 finalLen = 0;
1212 tANI_U8 *finalBuf = NULL;
1213 tANI_U8 temp = 0;
1214 u64 cookie;
1215 hdd_station_ctx_t *pHddStaCtx = NULL;
1216 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1217
1218 /* if not associated, no need to send action frame */
1219 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1220 {
1221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1222 ret = -EINVAL;
1223 goto exit;
1224 }
1225
1226 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1227 &dwellTime, &buf, &bufLen);
1228 if (eHAL_STATUS_SUCCESS != status)
1229 {
1230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1231 "%s: Failed to parse send action frame data", __func__);
1232 ret = -EINVAL;
1233 goto exit;
1234 }
1235
1236 /* if the target bssid is different from currently associated AP,
1237 then no need to send action frame */
1238 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1239 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1240 {
1241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1242 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001243 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001244 goto exit;
1245 }
1246
1247 /* if the channel number is different from operating channel then
1248 no need to send action frame */
1249 if (channel != pHddStaCtx->conn_info.operationChannel)
1250 {
1251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1252 "%s: channel(%d) is different from operating channel(%d)",
1253 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1254 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001255 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001256 goto exit;
1257 }
1258 chan.center_freq = sme_ChnToFreq(channel);
1259
1260 finalLen = bufLen + 24;
1261 finalBuf = vos_mem_malloc(finalLen);
1262 if (NULL == finalBuf)
1263 {
1264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1265 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001266 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001267 goto exit;
1268 }
1269 vos_mem_zero(finalBuf, finalLen);
1270
1271 /* Fill subtype */
1272 temp = SIR_MAC_MGMT_ACTION << 4;
1273 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1274
1275 /* Fill type */
1276 temp = SIR_MAC_MGMT_FRAME;
1277 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1278
1279 /* Fill destination address (bssid of the AP) */
1280 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1281
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001282 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001283 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1284
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001285 /* Fill BSSID (AP mac address) */
1286 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001287
1288 /* Fill received buffer from 24th address */
1289 vos_mem_copy(finalBuf + 24, buf, bufLen);
1290
Jeff Johnson11c33152013-04-16 17:52:40 -07001291 /* done with the parsed buffer */
1292 vos_mem_free(buf);
1293
Yue Maf49ba872013-08-19 12:04:25 -07001294 wlan_hdd_action( NULL,
1295#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1296 &(pAdapter->wdev),
1297#else
1298 dev,
1299#endif
1300 &chan, 0,
1301#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1302 NL80211_CHAN_HT20, 1,
1303#endif
1304 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001305 1, &cookie );
1306 vos_mem_free(finalBuf);
1307 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001308 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1309 {
1310 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1311 char extra[32];
1312 tANI_U8 len = 0;
1313
1314 /* value is interms of msec */
1315 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1316 if (copy_to_user(priv_data.buf, &extra, len + 1))
1317 {
1318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1319 "%s: failed to copy data to user buffer", __func__);
1320 ret = -EFAULT;
1321 goto exit;
1322 }
1323 }
1324 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1325 {
1326 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001327 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001328 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001329
1330 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1331 value = value + 19;
1332 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001333 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001334 if (ret < 0)
1335 {
1336 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001337 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001339 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001340 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1341 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1342 ret = -EINVAL;
1343 goto exit;
1344 }
1345
1346 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1347 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1348 {
1349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1350 "lfr mode value %d is out of range"
1351 " (Min: %d Max: %d)", maxTime,
1352 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1353 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1354 ret = -EINVAL;
1355 goto exit;
1356 }
1357
1358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1359 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1360
1361 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001362
1363 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1364 * where RFS is the RF Switching time. It is twice RFS to consider the
1365 * time to go off channel and return to the home channel. */
1366 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1367 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1368 {
1369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1370 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1371 " Hence enforcing home away time to disable (0)",
1372 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1373 homeAwayTime = 0;
1374 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1375 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1376 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001377 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1378 }
1379 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1380 {
1381 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1382 char extra[32];
1383 tANI_U8 len = 0;
1384
1385 /* value is interms of msec */
1386 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1387 if (copy_to_user(priv_data.buf, &extra, len + 1))
1388 {
1389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1390 "%s: failed to copy data to user buffer", __func__);
1391 ret = -EFAULT;
1392 goto exit;
1393 }
1394 }
1395 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1396 {
1397 tANI_U8 *value = command;
1398 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1399
1400 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1401 value = value + 16;
1402 /* Convert the value from ascii to integer */
1403 ret = kstrtou16(value, 10, &val);
1404 if (ret < 0)
1405 {
1406 /* If the input value is greater than max value of datatype, then also
1407 kstrtou16 fails */
1408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1409 "%s: kstrtou16 failed range [%d - %d]", __func__,
1410 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1411 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1412 ret = -EINVAL;
1413 goto exit;
1414 }
1415
1416 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1417 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1418 {
1419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1420 "scan home time value %d is out of range"
1421 " (Min: %d Max: %d)", val,
1422 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1423 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1424 ret = -EINVAL;
1425 goto exit;
1426 }
1427
1428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1429 "%s: Received Command to change scan home time = %d", __func__, val);
1430
1431 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1432 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1433 }
1434 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1435 {
1436 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1437 char extra[32];
1438 tANI_U8 len = 0;
1439
1440 /* value is interms of msec */
1441 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1442 if (copy_to_user(priv_data.buf, &extra, len + 1))
1443 {
1444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1445 "%s: failed to copy data to user buffer", __func__);
1446 ret = -EFAULT;
1447 goto exit;
1448 }
1449 }
1450 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1451 {
1452 tANI_U8 *value = command;
1453 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1454
1455 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1456 value = value + 17;
1457 /* Convert the value from ascii to integer */
1458 ret = kstrtou8(value, 10, &val);
1459 if (ret < 0)
1460 {
1461 /* If the input value is greater than max value of datatype, then also
1462 kstrtou8 fails */
1463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1464 "%s: kstrtou8 failed range [%d - %d]", __func__,
1465 CFG_ROAM_INTRA_BAND_MIN,
1466 CFG_ROAM_INTRA_BAND_MAX);
1467 ret = -EINVAL;
1468 goto exit;
1469 }
1470
1471 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1472 (val > CFG_ROAM_INTRA_BAND_MAX))
1473 {
1474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1475 "intra band mode value %d is out of range"
1476 " (Min: %d Max: %d)", val,
1477 CFG_ROAM_INTRA_BAND_MIN,
1478 CFG_ROAM_INTRA_BAND_MAX);
1479 ret = -EINVAL;
1480 goto exit;
1481 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1483 "%s: Received Command to change intra band = %d", __func__, val);
1484
1485 pHddCtx->cfg_ini->nRoamIntraBand = val;
1486 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1487 }
1488 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1489 {
1490 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1491 char extra[32];
1492 tANI_U8 len = 0;
1493
1494 /* value is interms of msec */
1495 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1496 if (copy_to_user(priv_data.buf, &extra, len + 1))
1497 {
1498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1499 "%s: failed to copy data to user buffer", __func__);
1500 ret = -EFAULT;
1501 goto exit;
1502 }
1503 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001504 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1505 {
1506 tANI_U8 *value = command;
1507 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1508
1509 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1510 value = value + 15;
1511 /* Convert the value from ascii to integer */
1512 ret = kstrtou8(value, 10, &nProbes);
1513 if (ret < 0)
1514 {
1515 /* If the input value is greater than max value of datatype, then also
1516 kstrtou8 fails */
1517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1518 "%s: kstrtou8 failed range [%d - %d]", __func__,
1519 CFG_ROAM_SCAN_N_PROBES_MIN,
1520 CFG_ROAM_SCAN_N_PROBES_MAX);
1521 ret = -EINVAL;
1522 goto exit;
1523 }
1524
1525 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1526 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1527 {
1528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1529 "NProbes value %d is out of range"
1530 " (Min: %d Max: %d)", nProbes,
1531 CFG_ROAM_SCAN_N_PROBES_MIN,
1532 CFG_ROAM_SCAN_N_PROBES_MAX);
1533 ret = -EINVAL;
1534 goto exit;
1535 }
1536
1537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1538 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1539
1540 pHddCtx->cfg_ini->nProbes = nProbes;
1541 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1542 }
1543 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1544 {
1545 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1546 char extra[32];
1547 tANI_U8 len = 0;
1548
1549 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1550 if (copy_to_user(priv_data.buf, &extra, len + 1))
1551 {
1552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1553 "%s: failed to copy data to user buffer", __func__);
1554 ret = -EFAULT;
1555 goto exit;
1556 }
1557 }
1558 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1559 {
1560 tANI_U8 *value = command;
1561 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001562 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001563
1564 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1565 /* input value is in units of msec */
1566 value = value + 20;
1567 /* Convert the value from ascii to integer */
1568 ret = kstrtou16(value, 10, &homeAwayTime);
1569 if (ret < 0)
1570 {
1571 /* If the input value is greater than max value of datatype, then also
1572 kstrtou8 fails */
1573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1574 "%s: kstrtou8 failed range [%d - %d]", __func__,
1575 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1576 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1577 ret = -EINVAL;
1578 goto exit;
1579 }
1580
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001581 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1582 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1583 {
1584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1585 "homeAwayTime value %d is out of range"
1586 " (Min: %d Max: %d)", homeAwayTime,
1587 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1588 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1589 ret = -EINVAL;
1590 goto exit;
1591 }
1592
1593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1594 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1595
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001596 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1597 * where RFS is the RF Switching time. It is twice RFS to consider the
1598 * time to go off channel and return to the home channel. */
1599 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1600 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1601 {
1602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1603 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1604 " Hence enforcing home away time to disable (0)",
1605 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1606 homeAwayTime = 0;
1607 }
1608
1609 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1610 {
1611 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1612 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1613 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001614 }
1615 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1616 {
1617 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1618 char extra[32];
1619 tANI_U8 len = 0;
1620
1621 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1622 if (copy_to_user(priv_data.buf, &extra, len + 1))
1623 {
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1625 "%s: failed to copy data to user buffer", __func__);
1626 ret = -EFAULT;
1627 goto exit;
1628 }
1629 }
1630 else if (strncmp(command, "REASSOC", 7) == 0)
1631 {
1632 tANI_U8 *value = command;
1633 tANI_U8 channel = 0;
1634 tSirMacAddr targetApBssid;
1635 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001636#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1637 tCsrHandoffRequest handoffInfo;
1638#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001639 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001640 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1641
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001642 /* if not associated, no need to proceed with reassoc */
1643 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1644 {
1645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1646 ret = -EINVAL;
1647 goto exit;
1648 }
1649
1650 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1651 if (eHAL_STATUS_SUCCESS != status)
1652 {
1653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1654 "%s: Failed to parse reassoc command data", __func__);
1655 ret = -EINVAL;
1656 goto exit;
1657 }
1658
1659 /* if the target bssid is same as currently associated AP,
1660 then no need to proceed with reassoc */
1661 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1662 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1663 {
1664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1665 ret = -EINVAL;
1666 goto exit;
1667 }
1668
1669 /* Check channel number is a valid channel number */
1670 if(VOS_STATUS_SUCCESS !=
1671 wlan_hdd_validate_operation_channel(pAdapter, channel))
1672 {
1673 hddLog(VOS_TRACE_LEVEL_ERROR,
1674 "%s: Invalid Channel [%d] \n", __func__, channel);
1675 return -EINVAL;
1676 }
1677
1678 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001679#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1680 handoffInfo.channel = channel;
1681 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1682 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1683#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001684 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001685#endif
1686#ifdef FEATURE_WLAN_LFR
1687 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1688 {
1689 tANI_U8 *value = command;
1690 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1691
1692 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1693 value = value + 12;
1694 /* Convert the value from ascii to integer */
1695 ret = kstrtou8(value, 10, &lfrMode);
1696 if (ret < 0)
1697 {
1698 /* If the input value is greater than max value of datatype, then also
1699 kstrtou8 fails */
1700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1701 "%s: kstrtou8 failed range [%d - %d]", __func__,
1702 CFG_LFR_FEATURE_ENABLED_MIN,
1703 CFG_LFR_FEATURE_ENABLED_MAX);
1704 ret = -EINVAL;
1705 goto exit;
1706 }
1707
1708 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1709 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1710 {
1711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1712 "lfr mode value %d is out of range"
1713 " (Min: %d Max: %d)", lfrMode,
1714 CFG_LFR_FEATURE_ENABLED_MIN,
1715 CFG_LFR_FEATURE_ENABLED_MAX);
1716 ret = -EINVAL;
1717 goto exit;
1718 }
1719
1720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1721 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1722
1723 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1724 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1725 }
1726#endif
1727#ifdef WLAN_FEATURE_VOWIFI_11R
1728 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1729 {
1730 tANI_U8 *value = command;
1731 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1732
1733 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1734 value = value + 18;
1735 /* Convert the value from ascii to integer */
1736 ret = kstrtou8(value, 10, &ft);
1737 if (ret < 0)
1738 {
1739 /* If the input value is greater than max value of datatype, then also
1740 kstrtou8 fails */
1741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1742 "%s: kstrtou8 failed range [%d - %d]", __func__,
1743 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1744 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1745 ret = -EINVAL;
1746 goto exit;
1747 }
1748
1749 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1750 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1751 {
1752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1753 "ft mode value %d is out of range"
1754 " (Min: %d Max: %d)", ft,
1755 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1756 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1757 ret = -EINVAL;
1758 goto exit;
1759 }
1760
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1762 "%s: Received Command to change ft mode = %d", __func__, ft);
1763
1764 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1765 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1766 }
1767#endif
1768#ifdef FEATURE_WLAN_CCX
1769 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1770 {
1771 tANI_U8 *value = command;
1772 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1773
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001774 /* Check if the features OKC/CCX/11R are supported simultaneously,
1775 then this operation is not permitted (return FAILURE) */
1776 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1777 hdd_is_okc_mode_enabled(pHddCtx) &&
1778 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1779 {
1780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1781 "%s: OKC/CCX/11R are supported simultaneously"
1782 " hence this operation is not permitted!", __func__);
1783 ret = -EPERM;
1784 goto exit;
1785 }
1786
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001787 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1788 value = value + 11;
1789 /* Convert the value from ascii to integer */
1790 ret = kstrtou8(value, 10, &ccxMode);
1791 if (ret < 0)
1792 {
1793 /* If the input value is greater than max value of datatype, then also
1794 kstrtou8 fails */
1795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1796 "%s: kstrtou8 failed range [%d - %d]", __func__,
1797 CFG_CCX_FEATURE_ENABLED_MIN,
1798 CFG_CCX_FEATURE_ENABLED_MAX);
1799 ret = -EINVAL;
1800 goto exit;
1801 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001802 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1803 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1804 {
1805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1806 "Ccx mode value %d is out of range"
1807 " (Min: %d Max: %d)", ccxMode,
1808 CFG_CCX_FEATURE_ENABLED_MIN,
1809 CFG_CCX_FEATURE_ENABLED_MAX);
1810 ret = -EINVAL;
1811 goto exit;
1812 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1814 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1815
1816 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1817 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1818 }
1819#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001820 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1821 {
1822 tANI_U8 *value = command;
1823 tANI_BOOLEAN roamScanControl = 0;
1824
1825 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1826 value = value + 19;
1827 /* Convert the value from ascii to integer */
1828 ret = kstrtou8(value, 10, &roamScanControl);
1829 if (ret < 0)
1830 {
1831 /* If the input value is greater than max value of datatype, then also
1832 kstrtou8 fails */
1833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1834 "%s: kstrtou8 failed ", __func__);
1835 ret = -EINVAL;
1836 goto exit;
1837 }
1838
1839 if (0 != roamScanControl)
1840 {
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1842 "roam scan control invalid value = %d",
1843 roamScanControl);
1844 ret = -EINVAL;
1845 goto exit;
1846 }
1847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1848 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1849
1850 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1851 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001852#ifdef FEATURE_WLAN_OKC
1853 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1854 {
1855 tANI_U8 *value = command;
1856 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1857
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001858 /* Check if the features OKC/CCX/11R are supported simultaneously,
1859 then this operation is not permitted (return FAILURE) */
1860 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1861 hdd_is_okc_mode_enabled(pHddCtx) &&
1862 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1863 {
1864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1865 "%s: OKC/CCX/11R are supported simultaneously"
1866 " hence this operation is not permitted!", __func__);
1867 ret = -EPERM;
1868 goto exit;
1869 }
1870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001871 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1872 value = value + 11;
1873 /* Convert the value from ascii to integer */
1874 ret = kstrtou8(value, 10, &okcMode);
1875 if (ret < 0)
1876 {
1877 /* If the input value is greater than max value of datatype, then also
1878 kstrtou8 fails */
1879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1880 "%s: kstrtou8 failed range [%d - %d]", __func__,
1881 CFG_OKC_FEATURE_ENABLED_MIN,
1882 CFG_OKC_FEATURE_ENABLED_MAX);
1883 ret = -EINVAL;
1884 goto exit;
1885 }
1886
1887 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1888 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1889 {
1890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1891 "Okc mode value %d is out of range"
1892 " (Min: %d Max: %d)", okcMode,
1893 CFG_OKC_FEATURE_ENABLED_MIN,
1894 CFG_OKC_FEATURE_ENABLED_MAX);
1895 ret = -EINVAL;
1896 goto exit;
1897 }
1898
1899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1900 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1901
1902 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1903 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001904 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1905 {
1906 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1907 char extra[32];
1908 tANI_U8 len = 0;
1909
1910 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1911 if (copy_to_user(priv_data.buf, &extra, len + 1))
1912 {
1913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1914 "%s: failed to copy data to user buffer", __func__);
1915 ret = -EFAULT;
1916 goto exit;
1917 }
1918 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001919#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301920#ifdef WLAN_FEATURE_PACKET_FILTERING
1921 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1922 {
1923 tANI_U8 filterType = 0;
1924 tANI_U8 *value = command;
1925
1926 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1927 value = value + 22;
1928
1929 /* Convert the value from ascii to integer */
1930 ret = kstrtou8(value, 10, &filterType);
1931 if (ret < 0)
1932 {
1933 /* If the input value is greater than max value of datatype,
1934 * then also kstrtou8 fails
1935 */
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "%s: kstrtou8 failed range ", __func__);
1938 ret = -EINVAL;
1939 goto exit;
1940 }
1941
1942 if (filterType != 0 && filterType != 1)
1943 {
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1945 "%s: Accepted Values are 0 and 1 ", __func__);
1946 ret = -EINVAL;
1947 goto exit;
1948 }
1949 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
1950 pAdapter->sessionId);
1951 }
1952#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05301953 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
1954 {
1955 char *dhcpPhase;
1956 dhcpPhase = command + 12;
1957 if ('1' == *dhcpPhase)
1958 {
1959 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
1960 pAdapter->macAddressCurrent.bytes);
1961 }
1962 else if ('2' == *dhcpPhase)
1963 {
1964 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
1965 pAdapter->macAddressCurrent.bytes);
1966 }
1967 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07001968 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
1969 {
1970 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
1971 }
1972 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
1973 {
1974 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
1975 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05301976 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
1977 {
1978 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1979 char extra[32];
1980 tANI_U8 len = 0;
1981
1982 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
1983 (int)pCfg->nActiveMaxChnTime);
1984 if (copy_to_user(priv_data.buf, &extra, len + 1))
1985 {
1986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1987 "%s: failed to copy data to user buffer", __func__);
1988 ret = -EFAULT;
1989 goto exit;
1990 }
1991 ret = len;
1992 }
1993 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
1994 {
1995 tANI_U8 *value = command;
1996 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1997 int val = 0, temp;
1998
1999 value = value + 13;
2000 temp = kstrtou32(value, 10, &val);
2001 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2002 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2003 {
2004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2005 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2006 ret = -EFAULT;
2007 goto exit;
2008 }
2009 pCfg->nActiveMaxChnTime = val;
2010 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002011 else {
2012 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2013 __func__, command);
2014 }
2015
Jeff Johnson295189b2012-06-20 16:38:30 -07002016 }
2017exit:
2018 if (command)
2019 {
2020 kfree(command);
2021 }
2022 return ret;
2023}
2024
Srinivas Girigowdade697412013-02-14 16:31:48 -08002025#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2026void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2027{
2028 eCsrBand band = -1;
2029 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2030 switch (band)
2031 {
2032 case eCSR_BAND_ALL:
2033 *pBand = WLAN_HDD_UI_BAND_AUTO;
2034 break;
2035
2036 case eCSR_BAND_24:
2037 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2038 break;
2039
2040 case eCSR_BAND_5G:
2041 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2042 break;
2043
2044 default:
2045 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2046 *pBand = -1;
2047 break;
2048 }
2049}
2050
2051/**---------------------------------------------------------------------------
2052
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002053 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2054
2055 This function parses the send action frame data passed in the format
2056 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2057
Srinivas Girigowda56076852013-08-20 14:00:50 -07002058 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002059 \param - pTargetApBssid Pointer to target Ap bssid
2060 \param - pChannel Pointer to the Target AP channel
2061 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2062 \param - pBuf Pointer to data
2063 \param - pBufLen Pointer to data length
2064
2065 \return - 0 for success non-zero for failure
2066
2067 --------------------------------------------------------------------------*/
2068VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2069 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2070{
2071 tANI_U8 *inPtr = pValue;
2072 tANI_U8 *dataEnd;
2073 int tempInt;
2074 int j = 0;
2075 int i = 0;
2076 int v = 0;
2077 tANI_U8 tempBuf[32];
2078 tANI_U8 tempByte = 0;
2079
2080 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2081 /*no argument after the command*/
2082 if (NULL == inPtr)
2083 {
2084 return -EINVAL;
2085 }
2086
2087 /*no space after the command*/
2088 else if (SPACE_ASCII_VALUE != *inPtr)
2089 {
2090 return -EINVAL;
2091 }
2092
2093 /*removing empty spaces*/
2094 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2095
2096 /*no argument followed by spaces*/
2097 if ('\0' == *inPtr)
2098 {
2099 return -EINVAL;
2100 }
2101
2102 /*getting the first argument ie the target AP bssid */
2103 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2104 {
2105 return -EINVAL;
2106 }
2107 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2108 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2109 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2110
2111 /* point to the next argument */
2112 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2113 /*no argument after the command*/
2114 if (NULL == inPtr) return -EINVAL;
2115
2116 /*removing empty spaces*/
2117 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2118
2119 /*no argument followed by spaces*/
2120 if ('\0' == *inPtr)
2121 {
2122 return -EINVAL;
2123 }
2124
2125 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002126 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002127 v = kstrtos32(tempBuf, 10, &tempInt);
2128 if ( v < 0) return -EINVAL;
2129
2130 *pChannel = tempInt;
2131
2132 /* point to the next argument */
2133 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2134 /*no argument after the command*/
2135 if (NULL == inPtr) return -EINVAL;
2136 /*removing empty spaces*/
2137 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2138
2139 /*no argument followed by spaces*/
2140 if ('\0' == *inPtr)
2141 {
2142 return -EINVAL;
2143 }
2144
2145 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002146 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002147 v = kstrtos32(tempBuf, 10, &tempInt);
2148 if ( v < 0) return -EINVAL;
2149
2150 *pDwellTime = tempInt;
2151
2152 /* point to the next argument */
2153 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2154 /*no argument after the command*/
2155 if (NULL == inPtr) return -EINVAL;
2156 /*removing empty spaces*/
2157 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2158
2159 /*no argument followed by spaces*/
2160 if ('\0' == *inPtr)
2161 {
2162 return -EINVAL;
2163 }
2164
2165 /* find the length of data */
2166 dataEnd = inPtr;
2167 while(('\0' != *dataEnd) )
2168 {
2169 dataEnd++;
2170 ++(*pBufLen);
2171 }
2172 if ( *pBufLen <= 0) return -EINVAL;
2173
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002174 /* Allocate the number of bytes based on the number of input characters
2175 whether it is even or odd.
2176 if the number of input characters are even, then we need N/2 byte.
2177 if the number of input characters are odd, then we need do (N+1)/2 to
2178 compensate rounding off.
2179 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2180 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2181 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002182 if (NULL == *pBuf)
2183 {
2184 hddLog(VOS_TRACE_LEVEL_FATAL,
2185 "%s: vos_mem_alloc failed ", __func__);
2186 return -EINVAL;
2187 }
2188
2189 /* the buffer received from the upper layer is character buffer,
2190 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2191 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2192 and f0 in 3rd location */
2193 for (i = 0, j = 0; j < *pBufLen; j += 2)
2194 {
2195 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2196 (*pBuf)[i++] = tempByte;
2197 }
2198 *pBufLen = i;
2199 return VOS_STATUS_SUCCESS;
2200}
2201
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002202/**---------------------------------------------------------------------------
2203
Srinivas Girigowdade697412013-02-14 16:31:48 -08002204 \brief hdd_parse_channellist() - HDD Parse channel list
2205
2206 This function parses the channel list passed in the format
2207 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002208 if the Number of channels (N) does not match with the actual number of channels passed
2209 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2210 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2211 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2212 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002213
2214 \param - pValue Pointer to input channel list
2215 \param - ChannelList Pointer to local output array to record channel list
2216 \param - pNumChannels Pointer to number of roam scan channels
2217
2218 \return - 0 for success non-zero for failure
2219
2220 --------------------------------------------------------------------------*/
2221VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2222{
2223 tANI_U8 *inPtr = pValue;
2224 int tempInt;
2225 int j = 0;
2226 int v = 0;
2227 char buf[32];
2228
2229 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2230 /*no argument after the command*/
2231 if (NULL == inPtr)
2232 {
2233 return -EINVAL;
2234 }
2235
2236 /*no space after the command*/
2237 else if (SPACE_ASCII_VALUE != *inPtr)
2238 {
2239 return -EINVAL;
2240 }
2241
2242 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002243 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002244
2245 /*no argument followed by spaces*/
2246 if ('\0' == *inPtr)
2247 {
2248 return -EINVAL;
2249 }
2250
2251 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002252 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002253 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002254 if ((v < 0) ||
2255 (tempInt <= 0) ||
2256 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2257 {
2258 return -EINVAL;
2259 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002260
2261 *pNumChannels = tempInt;
2262
2263 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2264 "Number of channels are: %d", *pNumChannels);
2265
2266 for (j = 0; j < (*pNumChannels); j++)
2267 {
2268 /*inPtr pointing to the beginning of first space after number of channels*/
2269 inPtr = strpbrk( inPtr, " " );
2270 /*no channel list after the number of channels argument*/
2271 if (NULL == inPtr)
2272 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002273 if (0 != j)
2274 {
2275 *pNumChannels = j;
2276 return VOS_STATUS_SUCCESS;
2277 }
2278 else
2279 {
2280 return -EINVAL;
2281 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002282 }
2283
2284 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002285 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002286
2287 /*no channel list after the number of channels argument and spaces*/
2288 if ( '\0' == *inPtr )
2289 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002290 if (0 != j)
2291 {
2292 *pNumChannels = j;
2293 return VOS_STATUS_SUCCESS;
2294 }
2295 else
2296 {
2297 return -EINVAL;
2298 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002299 }
2300
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002301 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002302 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002303 if ((v < 0) ||
2304 (tempInt <= 0) ||
2305 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2306 {
2307 return -EINVAL;
2308 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002309 pChannelList[j] = tempInt;
2310
2311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2312 "Channel %d added to preferred channel list",
2313 pChannelList[j] );
2314 }
2315
Srinivas Girigowdade697412013-02-14 16:31:48 -08002316 return VOS_STATUS_SUCCESS;
2317}
2318
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002319
2320/**---------------------------------------------------------------------------
2321
2322 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2323
2324 This function parses the reasoc command data passed in the format
2325 REASSOC<space><bssid><space><channel>
2326
Srinivas Girigowda56076852013-08-20 14:00:50 -07002327 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002328 \param - pTargetApBssid Pointer to target Ap bssid
2329 \param - pChannel Pointer to the Target AP channel
2330
2331 \return - 0 for success non-zero for failure
2332
2333 --------------------------------------------------------------------------*/
2334VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2335{
2336 tANI_U8 *inPtr = pValue;
2337 int tempInt;
2338 int v = 0;
2339 tANI_U8 tempBuf[32];
2340
2341 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2342 /*no argument after the command*/
2343 if (NULL == inPtr)
2344 {
2345 return -EINVAL;
2346 }
2347
2348 /*no space after the command*/
2349 else if (SPACE_ASCII_VALUE != *inPtr)
2350 {
2351 return -EINVAL;
2352 }
2353
2354 /*removing empty spaces*/
2355 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2356
2357 /*no argument followed by spaces*/
2358 if ('\0' == *inPtr)
2359 {
2360 return -EINVAL;
2361 }
2362
2363 /*getting the first argument ie the target AP bssid */
2364 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2365 {
2366 return -EINVAL;
2367 }
2368 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2369 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2370 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2371
2372 /* point to the next argument */
2373 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2374 /*no argument after the command*/
2375 if (NULL == inPtr) return -EINVAL;
2376
2377 /*removing empty spaces*/
2378 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2379
2380 /*no argument followed by spaces*/
2381 if ('\0' == *inPtr)
2382 {
2383 return -EINVAL;
2384 }
2385
2386 /*getting the next argument ie the channel number */
2387 sscanf(inPtr, "%s ", tempBuf);
2388 v = kstrtos32(tempBuf, 10, &tempInt);
2389 if ( v < 0) return -EINVAL;
2390
2391 *pChannel = tempInt;
2392 return VOS_STATUS_SUCCESS;
2393}
2394
2395#endif
2396
Jeff Johnson295189b2012-06-20 16:38:30 -07002397/**---------------------------------------------------------------------------
2398
2399 \brief hdd_open() - HDD Open function
2400
2401 This is called in response to ifconfig up
2402
2403 \param - dev Pointer to net_device structure
2404
2405 \return - 0 for success non-zero for failure
2406
2407 --------------------------------------------------------------------------*/
2408int hdd_open (struct net_device *dev)
2409{
2410 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2411 hdd_context_t *pHddCtx;
2412 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2413 VOS_STATUS status;
2414 v_BOOL_t in_standby = TRUE;
2415
2416 if (NULL == pAdapter)
2417 {
2418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002419 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002420 return -ENODEV;
2421 }
2422
2423 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2424 if (NULL == pHddCtx)
2425 {
2426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002427 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002428 return -ENODEV;
2429 }
2430
2431 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2432 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2433 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002434 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2435 {
2436 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302437 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002438 in_standby = FALSE;
2439 break;
2440 }
2441 else
2442 {
2443 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2444 pAdapterNode = pNext;
2445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002446 }
2447
2448 if (TRUE == in_standby)
2449 {
2450 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2451 {
2452 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2453 "wlan out of power save", __func__);
2454 return -EINVAL;
2455 }
2456 }
2457
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002458 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002459 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2460 {
2461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002462 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002463 /* Enable TX queues only when we are connected */
2464 netif_tx_start_all_queues(dev);
2465 }
2466
2467 return 0;
2468}
2469
2470int hdd_mon_open (struct net_device *dev)
2471{
2472 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2473
2474 if(pAdapter == NULL) {
2475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002476 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002477 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002478 }
2479
2480 netif_start_queue(dev);
2481
2482 return 0;
2483}
2484/**---------------------------------------------------------------------------
2485
2486 \brief hdd_stop() - HDD stop function
2487
2488 This is called in response to ifconfig down
2489
2490 \param - dev Pointer to net_device structure
2491
2492 \return - 0 for success non-zero for failure
2493
2494 --------------------------------------------------------------------------*/
2495
2496int hdd_stop (struct net_device *dev)
2497{
2498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2499 hdd_context_t *pHddCtx;
2500 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2501 VOS_STATUS status;
2502 v_BOOL_t enter_standby = TRUE;
2503
2504 ENTER();
2505
2506 if (NULL == pAdapter)
2507 {
2508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002509 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002510 return -ENODEV;
2511 }
2512
2513 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2514 if (NULL == pHddCtx)
2515 {
2516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002517 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002518 return -ENODEV;
2519 }
2520
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002521 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002522 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2523 netif_tx_disable(pAdapter->dev);
2524 netif_carrier_off(pAdapter->dev);
2525
2526
2527 /* SoftAP ifaces should never go in power save mode
2528 making sure same here. */
2529 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2530 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002532 )
2533 {
2534 /* SoftAP mode, so return from here */
2535 EXIT();
2536 return 0;
2537 }
2538
2539 /* Find if any iface is up then
2540 if any iface is up then can't put device to sleep/ power save mode. */
2541 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2542 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2543 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002544 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2545 {
2546 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302547 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002548 enter_standby = FALSE;
2549 break;
2550 }
2551 else
2552 {
2553 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2554 pAdapterNode = pNext;
2555 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002556 }
2557
2558 if (TRUE == enter_standby)
2559 {
2560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2561 "entering standby", __func__);
2562 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2563 {
2564 /*log and return success*/
2565 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2566 "wlan in power save", __func__);
2567 }
2568 }
2569
2570 EXIT();
2571 return 0;
2572}
2573
2574/**---------------------------------------------------------------------------
2575
2576 \brief hdd_uninit() - HDD uninit function
2577
2578 This is called during the netdev unregister to uninitialize all data
2579associated with the device
2580
2581 \param - dev Pointer to net_device structure
2582
2583 \return - void
2584
2585 --------------------------------------------------------------------------*/
2586static void hdd_uninit (struct net_device *dev)
2587{
2588 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2589
2590 ENTER();
2591
2592 do
2593 {
2594 if (NULL == pAdapter)
2595 {
2596 hddLog(VOS_TRACE_LEVEL_FATAL,
2597 "%s: NULL pAdapter", __func__);
2598 break;
2599 }
2600
2601 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2602 {
2603 hddLog(VOS_TRACE_LEVEL_FATAL,
2604 "%s: Invalid magic", __func__);
2605 break;
2606 }
2607
2608 if (NULL == pAdapter->pHddCtx)
2609 {
2610 hddLog(VOS_TRACE_LEVEL_FATAL,
2611 "%s: NULL pHddCtx", __func__);
2612 break;
2613 }
2614
2615 if (dev != pAdapter->dev)
2616 {
2617 hddLog(VOS_TRACE_LEVEL_FATAL,
2618 "%s: Invalid device reference", __func__);
2619 /* we haven't validated all cases so let this go for now */
2620 }
2621
2622 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2623
2624 /* after uninit our adapter structure will no longer be valid */
2625 pAdapter->dev = NULL;
2626 pAdapter->magic = 0;
2627 } while (0);
2628
2629 EXIT();
2630}
2631
2632/**---------------------------------------------------------------------------
2633
2634 \brief hdd_release_firmware() -
2635
2636 This function calls the release firmware API to free the firmware buffer.
2637
2638 \param - pFileName Pointer to the File Name.
2639 pCtx - Pointer to the adapter .
2640
2641
2642 \return - 0 for success, non zero for failure
2643
2644 --------------------------------------------------------------------------*/
2645
2646VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2647{
2648 VOS_STATUS status = VOS_STATUS_SUCCESS;
2649 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2650 ENTER();
2651
2652
2653 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2654
2655 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2656
2657 if(pHddCtx->fw) {
2658 release_firmware(pHddCtx->fw);
2659 pHddCtx->fw = NULL;
2660 }
2661 else
2662 status = VOS_STATUS_E_FAILURE;
2663 }
2664 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2665 if(pHddCtx->nv) {
2666 release_firmware(pHddCtx->nv);
2667 pHddCtx->nv = NULL;
2668 }
2669 else
2670 status = VOS_STATUS_E_FAILURE;
2671
2672 }
2673
2674 EXIT();
2675 return status;
2676}
2677
2678/**---------------------------------------------------------------------------
2679
2680 \brief hdd_request_firmware() -
2681
2682 This function reads the firmware file using the request firmware
2683 API and returns the the firmware data and the firmware file size.
2684
2685 \param - pfileName - Pointer to the file name.
2686 - pCtx - Pointer to the adapter .
2687 - ppfw_data - Pointer to the pointer of the firmware data.
2688 - pSize - Pointer to the file size.
2689
2690 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2691
2692 --------------------------------------------------------------------------*/
2693
2694
2695VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2696{
2697 int status;
2698 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2699 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2700 ENTER();
2701
2702 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2703
2704 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2705
2706 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2707 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2708 __func__, pfileName);
2709 retval = VOS_STATUS_E_FAILURE;
2710 }
2711
2712 else {
2713 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2714 *pSize = pHddCtx->fw->size;
2715 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2716 __func__, *pSize);
2717 }
2718 }
2719 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2720
2721 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2722
2723 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2724 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2725 __func__, pfileName);
2726 retval = VOS_STATUS_E_FAILURE;
2727 }
2728
2729 else {
2730 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2731 *pSize = pHddCtx->nv->size;
2732 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2733 __func__, *pSize);
2734 }
2735 }
2736
2737 EXIT();
2738 return retval;
2739}
2740/**---------------------------------------------------------------------------
2741 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2742
2743 This is the function invoked by SME to inform the result of a full power
2744 request issued by HDD
2745
2746 \param - callbackcontext - Pointer to cookie
2747 status - result of request
2748
2749 \return - None
2750
2751--------------------------------------------------------------------------*/
2752void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2753{
2754 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2755
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002756 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002757 if(&pHddCtx->full_pwr_comp_var)
2758 {
2759 complete(&pHddCtx->full_pwr_comp_var);
2760 }
2761}
2762
2763/**---------------------------------------------------------------------------
2764
2765 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2766
2767 This is the function invoked by SME to inform the result of BMPS
2768 request issued by HDD
2769
2770 \param - callbackcontext - Pointer to cookie
2771 status - result of request
2772
2773 \return - None
2774
2775--------------------------------------------------------------------------*/
2776void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2777{
2778
2779 struct completion *completion_var = (struct completion*) callbackContext;
2780
2781 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2782 if(completion_var != NULL)
2783 {
2784 complete(completion_var);
2785 }
2786}
2787
2788/**---------------------------------------------------------------------------
2789
2790 \brief hdd_get_cfg_file_size() -
2791
2792 This function reads the configuration file using the request firmware
2793 API and returns the configuration file size.
2794
2795 \param - pCtx - Pointer to the adapter .
2796 - pFileName - Pointer to the file name.
2797 - pBufSize - Pointer to the buffer size.
2798
2799 \return - 0 for success, non zero for failure
2800
2801 --------------------------------------------------------------------------*/
2802
2803VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2804{
2805 int status;
2806 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2807
2808 ENTER();
2809
2810 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2811
2812 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2813 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2814 status = VOS_STATUS_E_FAILURE;
2815 }
2816 else {
2817 *pBufSize = pHddCtx->fw->size;
2818 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2819 release_firmware(pHddCtx->fw);
2820 pHddCtx->fw = NULL;
2821 }
2822
2823 EXIT();
2824 return VOS_STATUS_SUCCESS;
2825}
2826
2827/**---------------------------------------------------------------------------
2828
2829 \brief hdd_read_cfg_file() -
2830
2831 This function reads the configuration file using the request firmware
2832 API and returns the cfg data and the buffer size of the configuration file.
2833
2834 \param - pCtx - Pointer to the adapter .
2835 - pFileName - Pointer to the file name.
2836 - pBuffer - Pointer to the data buffer.
2837 - pBufSize - Pointer to the buffer size.
2838
2839 \return - 0 for success, non zero for failure
2840
2841 --------------------------------------------------------------------------*/
2842
2843VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2844 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2845{
2846 int status;
2847 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2848
2849 ENTER();
2850
2851 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2852
2853 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2854 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2855 return VOS_STATUS_E_FAILURE;
2856 }
2857 else {
2858 if(*pBufSize != pHddCtx->fw->size) {
2859 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2860 "file size", __func__);
2861 release_firmware(pHddCtx->fw);
2862 pHddCtx->fw = NULL;
2863 return VOS_STATUS_E_FAILURE;
2864 }
2865 else {
2866 if(pBuffer) {
2867 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2868 }
2869 release_firmware(pHddCtx->fw);
2870 pHddCtx->fw = NULL;
2871 }
2872 }
2873
2874 EXIT();
2875
2876 return VOS_STATUS_SUCCESS;
2877}
2878
2879/**---------------------------------------------------------------------------
2880
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 \brief hdd_set_mac_address() -
2882
2883 This function sets the user specified mac address using
2884 the command ifconfig wlanX hw ether <mac adress>.
2885
2886 \param - dev - Pointer to the net device.
2887 - addr - Pointer to the sockaddr.
2888 \return - 0 for success, non zero for failure
2889
2890 --------------------------------------------------------------------------*/
2891
2892static int hdd_set_mac_address(struct net_device *dev, void *addr)
2893{
2894 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2895 struct sockaddr *psta_mac_addr = addr;
2896 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2897
2898 ENTER();
2899
2900 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2901
2902#ifdef HDD_SESSIONIZE
2903 // set the MAC address though the STA ID CFG.
2904 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2905 (v_U8_t *)&pAdapter->macAddressCurrent,
2906 sizeof( pAdapter->macAddressCurrent ),
2907 hdd_set_mac_addr_cb, VOS_FALSE );
2908#endif
2909
2910 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2911
2912 EXIT();
2913 return halStatus;
2914}
2915
2916tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2917{
2918 int i;
2919 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2920 {
2921 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2922 break;
2923 }
2924
2925 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2926 return NULL;
2927
2928 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2929 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2930}
2931
2932void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2933{
2934 int i;
2935 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2936 {
2937 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2938 {
2939 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2940 break;
2941 }
2942 }
2943 return;
2944}
2945
2946#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2947 static struct net_device_ops wlan_drv_ops = {
2948 .ndo_open = hdd_open,
2949 .ndo_stop = hdd_stop,
2950 .ndo_uninit = hdd_uninit,
2951 .ndo_start_xmit = hdd_hard_start_xmit,
2952 .ndo_tx_timeout = hdd_tx_timeout,
2953 .ndo_get_stats = hdd_stats,
2954 .ndo_do_ioctl = hdd_ioctl,
2955 .ndo_set_mac_address = hdd_set_mac_address,
2956 .ndo_select_queue = hdd_select_queue,
2957#ifdef WLAN_FEATURE_PACKET_FILTERING
2958#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2959 .ndo_set_rx_mode = hdd_set_multicast_list,
2960#else
2961 .ndo_set_multicast_list = hdd_set_multicast_list,
2962#endif //LINUX_VERSION_CODE
2963#endif
2964 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002965 static struct net_device_ops wlan_mon_drv_ops = {
2966 .ndo_open = hdd_mon_open,
2967 .ndo_stop = hdd_stop,
2968 .ndo_uninit = hdd_uninit,
2969 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2970 .ndo_tx_timeout = hdd_tx_timeout,
2971 .ndo_get_stats = hdd_stats,
2972 .ndo_do_ioctl = hdd_ioctl,
2973 .ndo_set_mac_address = hdd_set_mac_address,
2974 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002975
2976#endif
2977
2978void hdd_set_station_ops( struct net_device *pWlanDev )
2979{
2980#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2981 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2982 pWlanDev->netdev_ops = &wlan_drv_ops;
2983#else
2984 pWlanDev->open = hdd_open;
2985 pWlanDev->stop = hdd_stop;
2986 pWlanDev->uninit = hdd_uninit;
2987 pWlanDev->hard_start_xmit = NULL;
2988 pWlanDev->tx_timeout = hdd_tx_timeout;
2989 pWlanDev->get_stats = hdd_stats;
2990 pWlanDev->do_ioctl = hdd_ioctl;
2991 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2992 pWlanDev->set_mac_address = hdd_set_mac_address;
2993#endif
2994}
2995
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002996static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002997{
2998 struct net_device *pWlanDev = NULL;
2999 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003000 /*
3001 * cfg80211 initialization and registration....
3002 */
3003 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3004
Jeff Johnson295189b2012-06-20 16:38:30 -07003005 if(pWlanDev != NULL)
3006 {
3007
3008 //Save the pointer to the net_device in the HDD adapter
3009 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3010
Jeff Johnson295189b2012-06-20 16:38:30 -07003011 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3012
3013 pAdapter->dev = pWlanDev;
3014 pAdapter->pHddCtx = pHddCtx;
3015 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3016
3017 init_completion(&pAdapter->session_open_comp_var);
3018 init_completion(&pAdapter->session_close_comp_var);
3019 init_completion(&pAdapter->disconnect_comp_var);
3020 init_completion(&pAdapter->linkup_event_var);
3021 init_completion(&pAdapter->cancel_rem_on_chan_var);
3022 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003023#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3024 init_completion(&pAdapter->offchannel_tx_event);
3025#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003026 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003027#ifdef FEATURE_WLAN_TDLS
3028 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003029 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003030 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303031 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003032#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003033 init_completion(&pHddCtx->mc_sus_event_var);
3034 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303035 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003036 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003037
Jeff Johnson295189b2012-06-20 16:38:30 -07003038 pAdapter->isLinkUpSvcNeeded = FALSE;
3039 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3040 //Init the net_device structure
3041 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3042
3043 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3044 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3045 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3046 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3047
3048 hdd_set_station_ops( pAdapter->dev );
3049
3050 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003051 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3052 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3053 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 /* set pWlanDev's parent to underlying device */
3055 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3056 }
3057
3058 return pAdapter;
3059}
3060
3061VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3062{
3063 struct net_device *pWlanDev = pAdapter->dev;
3064 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3065 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3066 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3067
3068 if( rtnl_lock_held )
3069 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003070 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003071 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3072 {
3073 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3074 return VOS_STATUS_E_FAILURE;
3075 }
3076 }
3077 if (register_netdevice(pWlanDev))
3078 {
3079 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3080 return VOS_STATUS_E_FAILURE;
3081 }
3082 }
3083 else
3084 {
3085 if(register_netdev(pWlanDev))
3086 {
3087 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3088 return VOS_STATUS_E_FAILURE;
3089 }
3090 }
3091 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3092
3093 return VOS_STATUS_SUCCESS;
3094}
3095
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003096static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003097{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003098 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003099
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003100 if (NULL == pAdapter)
3101 {
3102 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3103 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003104 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003105
3106 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3107 {
3108 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3109 return eHAL_STATUS_NOT_INITIALIZED;
3110 }
3111
3112 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3113
3114 /* need to make sure all of our scheduled work has completed.
3115 * This callback is called from MC thread context, so it is safe to
3116 * to call below flush workqueue API from here.
3117 */
3118 flush_scheduled_work();
3119
3120 /* We can be blocked while waiting for scheduled work to be
3121 * flushed, and the adapter structure can potentially be freed, in
3122 * which case the magic will have been reset. So make sure the
3123 * magic is still good, and hence the adapter structure is still
3124 * valid, before signaling completion */
3125 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3126 {
3127 complete(&pAdapter->session_close_comp_var);
3128 }
3129
Jeff Johnson295189b2012-06-20 16:38:30 -07003130 return eHAL_STATUS_SUCCESS;
3131}
3132
3133VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3134{
3135 struct net_device *pWlanDev = pAdapter->dev;
3136 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3137 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3138 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3139 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3140 int rc = 0;
3141
3142 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003143 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003144 //Open a SME session for future operation
3145 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003146 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003147 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3148 {
3149 hddLog(VOS_TRACE_LEVEL_FATAL,
3150 "sme_OpenSession() failed with status code %08d [x%08lx]",
3151 halStatus, halStatus );
3152 status = VOS_STATUS_E_FAILURE;
3153 goto error_sme_open;
3154 }
3155
3156 //Block on a completion variable. Can't wait forever though.
3157 rc = wait_for_completion_interruptible_timeout(
3158 &pAdapter->session_open_comp_var,
3159 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3160 if (!rc)
3161 {
3162 hddLog(VOS_TRACE_LEVEL_FATAL,
3163 "Session is not opened within timeout period code %08d", rc );
3164 status = VOS_STATUS_E_FAILURE;
3165 goto error_sme_open;
3166 }
3167
3168 // Register wireless extensions
3169 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3170 {
3171 hddLog(VOS_TRACE_LEVEL_FATAL,
3172 "hdd_register_wext() failed with status code %08d [x%08lx]",
3173 halStatus, halStatus );
3174 status = VOS_STATUS_E_FAILURE;
3175 goto error_register_wext;
3176 }
3177 //Safe to register the hard_start_xmit function again
3178#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3179 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3180#else
3181 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3182#endif
3183
3184 //Set the Connection State to Not Connected
3185 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3186
3187 //Set the default operation channel
3188 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3189
3190 /* Make the default Auth Type as OPEN*/
3191 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3192
3193 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3194 {
3195 hddLog(VOS_TRACE_LEVEL_FATAL,
3196 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3197 status, status );
3198 goto error_init_txrx;
3199 }
3200
3201 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3202
3203 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3204 {
3205 hddLog(VOS_TRACE_LEVEL_FATAL,
3206 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3207 status, status );
3208 goto error_wmm_init;
3209 }
3210
3211 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3212
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003213#ifdef FEATURE_WLAN_TDLS
3214 if(0 != wlan_hdd_tdls_init(pAdapter))
3215 {
3216 status = VOS_STATUS_E_FAILURE;
3217 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3218 goto error_tdls_init;
3219 }
3220 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3221#endif
3222
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 return VOS_STATUS_SUCCESS;
3224
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003225#ifdef FEATURE_WLAN_TDLS
3226error_tdls_init:
3227 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3228 hdd_wmm_adapter_close(pAdapter);
3229#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003230error_wmm_init:
3231 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3232 hdd_deinit_tx_rx(pAdapter);
3233error_init_txrx:
3234 hdd_UnregisterWext(pWlanDev);
3235error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003236 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003237 {
3238 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003239 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003240 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003241 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003242 {
3243 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003244 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003246 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003247 }
3248}
3249error_sme_open:
3250 return status;
3251}
3252
Jeff Johnson295189b2012-06-20 16:38:30 -07003253void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3254{
3255 hdd_cfg80211_state_t *cfgState;
3256
3257 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3258
3259 if( NULL != cfgState->buf )
3260 {
3261 int rc;
3262 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3263 rc = wait_for_completion_interruptible_timeout(
3264 &pAdapter->tx_action_cnf_event,
3265 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3266 if(!rc)
3267 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003268 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003269 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3270 }
3271 }
3272 return;
3273}
Jeff Johnson295189b2012-06-20 16:38:30 -07003274
3275void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3276{
3277 ENTER();
3278 switch ( pAdapter->device_mode )
3279 {
3280 case WLAN_HDD_INFRA_STATION:
3281 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003282 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003283 {
3284 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3285 {
3286 hdd_deinit_tx_rx( pAdapter );
3287 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3288 }
3289
3290 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3291 {
3292 hdd_wmm_adapter_close( pAdapter );
3293 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3294 }
3295
Jeff Johnson295189b2012-06-20 16:38:30 -07003296 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003297#ifdef FEATURE_WLAN_TDLS
3298 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3299 {
3300 wlan_hdd_tdls_exit(pAdapter);
3301 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3302 }
3303#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003304
3305 break;
3306 }
3307
3308 case WLAN_HDD_SOFTAP:
3309 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003311 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003312
3313 hdd_unregister_hostapd(pAdapter);
3314 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003316 break;
3317 }
3318
3319 case WLAN_HDD_MONITOR:
3320 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003321 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003322 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 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003327 if(NULL != pAdapterforTx)
3328 {
3329 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3330 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003331 break;
3332 }
3333
3334
3335 default:
3336 break;
3337 }
3338
3339 EXIT();
3340}
3341
3342void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3343{
3344 struct net_device *pWlanDev = pAdapter->dev;
3345
3346 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3347 if( rtnl_held )
3348 {
3349 unregister_netdevice(pWlanDev);
3350 }
3351 else
3352 {
3353 unregister_netdev(pWlanDev);
3354 }
3355 // note that the pAdapter is no longer valid at this point
3356 // since the memory has been reclaimed
3357 }
3358
3359}
3360
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003361void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3362{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303363 VOS_STATUS status;
3364 hdd_adapter_t *pAdapter = NULL;
3365 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003366
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303367 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003368
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303369 /*loop through all adapters.*/
3370 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003371 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303372 pAdapter = pAdapterNode->pAdapter;
3373 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3374 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003375
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303376 { // we skip this registration for modes other than STA and P2P client modes.
3377 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3378 pAdapterNode = pNext;
3379 continue;
3380 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003381
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303382 //Apply Dynamic DTIM For P2P
3383 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3384 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3385 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3386 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3387 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3388 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3389 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3390 (eConnectionState_Associated ==
3391 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3392 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3393 {
3394 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003395
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303396 powerRequest.uIgnoreDTIM = 1;
3397 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3398
3399 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3400 {
3401 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3402 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3403 }
3404 else
3405 {
3406 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3407 }
3408
3409 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3410 * specified during Enter/Exit BMPS when LCD off*/
3411 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3412 NULL, eANI_BOOLEAN_FALSE);
3413 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3414 NULL, eANI_BOOLEAN_FALSE);
3415
3416 /* switch to the DTIM specified in cfg.ini */
3417 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3418 "Switch to DTIM %d", powerRequest.uListenInterval);
3419 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3420 break;
3421
3422 }
3423
3424 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3425 pAdapterNode = pNext;
3426 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003427}
3428
3429void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3430{
3431 /*Switch back to DTIM 1*/
3432 tSirSetPowerParamsReq powerRequest = { 0 };
3433
3434 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3435 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003436 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003437
3438 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3439 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3440 NULL, eANI_BOOLEAN_FALSE);
3441 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3442 NULL, eANI_BOOLEAN_FALSE);
3443
3444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3445 "Switch to DTIM%d",powerRequest.uListenInterval);
3446 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3447
3448}
3449
Jeff Johnson295189b2012-06-20 16:38:30 -07003450VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3451{
3452 VOS_STATUS status = VOS_STATUS_SUCCESS;
3453
3454 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3455 {
3456 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3457 }
3458
3459 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3460 {
3461 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3462 }
3463
3464 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3465 {
3466 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3467 }
3468
3469 return status;
3470}
3471
3472VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3473{
3474 hdd_adapter_t *pAdapter = NULL;
3475 eHalStatus halStatus;
3476 VOS_STATUS status = VOS_STATUS_E_INVAL;
3477 v_BOOL_t disableBmps = FALSE;
3478 v_BOOL_t disableImps = FALSE;
3479
3480 switch(session_type)
3481 {
3482 case WLAN_HDD_INFRA_STATION:
3483 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003484 case WLAN_HDD_P2P_CLIENT:
3485 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003486 //Exit BMPS -> Is Sta/P2P Client is already connected
3487 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3488 if((NULL != pAdapter)&&
3489 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3490 {
3491 disableBmps = TRUE;
3492 }
3493
3494 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3495 if((NULL != pAdapter)&&
3496 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3497 {
3498 disableBmps = TRUE;
3499 }
3500
3501 //Exit both Bmps and Imps incase of Go/SAP Mode
3502 if((WLAN_HDD_SOFTAP == session_type) ||
3503 (WLAN_HDD_P2P_GO == session_type))
3504 {
3505 disableBmps = TRUE;
3506 disableImps = TRUE;
3507 }
3508
3509 if(TRUE == disableImps)
3510 {
3511 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3512 {
3513 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3514 }
3515 }
3516
3517 if(TRUE == disableBmps)
3518 {
3519 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3520 {
3521 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3522
3523 if(eHAL_STATUS_SUCCESS != halStatus)
3524 {
3525 status = VOS_STATUS_E_FAILURE;
3526 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3527 VOS_ASSERT(0);
3528 return status;
3529 }
3530 }
3531
3532 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3533 {
3534 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3535
3536 if(eHAL_STATUS_SUCCESS != halStatus)
3537 {
3538 status = VOS_STATUS_E_FAILURE;
3539 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3540 VOS_ASSERT(0);
3541 return status;
3542 }
3543 }
3544 }
3545
3546 if((TRUE == disableBmps) ||
3547 (TRUE == disableImps))
3548 {
3549 /* Now, get the chip into Full Power now */
3550 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3551 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3552 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3553
3554 if(halStatus != eHAL_STATUS_SUCCESS)
3555 {
3556 if(halStatus == eHAL_STATUS_PMC_PENDING)
3557 {
3558 //Block on a completion variable. Can't wait forever though
3559 wait_for_completion_interruptible_timeout(
3560 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3561 }
3562 else
3563 {
3564 status = VOS_STATUS_E_FAILURE;
3565 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3566 VOS_ASSERT(0);
3567 return status;
3568 }
3569 }
3570
3571 status = VOS_STATUS_SUCCESS;
3572 }
3573
3574 break;
3575 }
3576 return status;
3577}
3578
3579hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003580 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003581 tANI_U8 rtnl_held )
3582{
3583 hdd_adapter_t *pAdapter = NULL;
3584 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3585 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3586 VOS_STATUS exitbmpsStatus;
3587
3588 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3589
3590 //Disable BMPS incase of Concurrency
3591 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3592
3593 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3594 {
3595 //Fail to Exit BMPS
3596 VOS_ASSERT(0);
3597 return NULL;
3598 }
3599
3600 switch(session_type)
3601 {
3602 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003603 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003604 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 {
3606 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3607
3608 if( NULL == pAdapter )
3609 return NULL;
3610
Jeff Johnsone7245742012-09-05 17:12:55 -07003611 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3612 NL80211_IFTYPE_P2P_CLIENT:
3613 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003614
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 pAdapter->device_mode = session_type;
3616
3617 status = hdd_init_station_mode( pAdapter );
3618 if( VOS_STATUS_SUCCESS != status )
3619 goto err_free_netdev;
3620
3621 status = hdd_register_interface( pAdapter, rtnl_held );
3622 if( VOS_STATUS_SUCCESS != status )
3623 {
3624 hdd_deinit_adapter(pHddCtx, pAdapter);
3625 goto err_free_netdev;
3626 }
3627 //Stop the Interface TX queue.
3628 netif_tx_disable(pAdapter->dev);
3629 //netif_tx_disable(pWlanDev);
3630 netif_carrier_off(pAdapter->dev);
3631
3632 break;
3633 }
3634
Jeff Johnson295189b2012-06-20 16:38:30 -07003635 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003636 case WLAN_HDD_SOFTAP:
3637 {
3638 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3639 if( NULL == pAdapter )
3640 return NULL;
3641
Jeff Johnson295189b2012-06-20 16:38:30 -07003642 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3643 NL80211_IFTYPE_AP:
3644 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003645 pAdapter->device_mode = session_type;
3646
3647 status = hdd_init_ap_mode(pAdapter);
3648 if( VOS_STATUS_SUCCESS != status )
3649 goto err_free_netdev;
3650
3651 status = hdd_register_hostapd( pAdapter, rtnl_held );
3652 if( VOS_STATUS_SUCCESS != status )
3653 {
3654 hdd_deinit_adapter(pHddCtx, pAdapter);
3655 goto err_free_netdev;
3656 }
3657
3658 netif_tx_disable(pAdapter->dev);
3659 netif_carrier_off(pAdapter->dev);
3660
3661 hdd_set_conparam( 1 );
3662 break;
3663 }
3664 case WLAN_HDD_MONITOR:
3665 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003666 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3667 if( NULL == pAdapter )
3668 return NULL;
3669
3670 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3671 pAdapter->device_mode = session_type;
3672 status = hdd_register_interface( pAdapter, rtnl_held );
3673#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3674 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3675#else
3676 pAdapter->dev->open = hdd_mon_open;
3677 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3678#endif
3679 hdd_init_tx_rx( pAdapter );
3680 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3681 //Set adapter to be used for data tx. It will use either GO or softap.
3682 pAdapter->sessionCtx.monitor.pAdapterForTx =
3683 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003684 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3685 {
3686 pAdapter->sessionCtx.monitor.pAdapterForTx =
3687 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3688 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 /* This workqueue will be used to transmit management packet over
3690 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003691 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3692 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3693 return NULL;
3694 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003695
Jeff Johnson295189b2012-06-20 16:38:30 -07003696 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3697 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003698 }
3699 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003700 case WLAN_HDD_FTM:
3701 {
3702 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3703
3704 if( NULL == pAdapter )
3705 return NULL;
3706 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3707 * message while loading driver in FTM mode. */
3708 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3709 pAdapter->device_mode = session_type;
3710 status = hdd_register_interface( pAdapter, rtnl_held );
3711 }
3712 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 default:
3714 {
3715 VOS_ASSERT(0);
3716 return NULL;
3717 }
3718 }
3719
3720
3721 if( VOS_STATUS_SUCCESS == status )
3722 {
3723 //Add it to the hdd's session list.
3724 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3725 if( NULL == pHddAdapterNode )
3726 {
3727 status = VOS_STATUS_E_NOMEM;
3728 }
3729 else
3730 {
3731 pHddAdapterNode->pAdapter = pAdapter;
3732 status = hdd_add_adapter_back ( pHddCtx,
3733 pHddAdapterNode );
3734 }
3735 }
3736
3737 if( VOS_STATUS_SUCCESS != status )
3738 {
3739 if( NULL != pAdapter )
3740 {
3741 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3742 pAdapter = NULL;
3743 }
3744 if( NULL != pHddAdapterNode )
3745 {
3746 vos_mem_free( pHddAdapterNode );
3747 }
3748
3749 goto resume_bmps;
3750 }
3751
3752 if(VOS_STATUS_SUCCESS == status)
3753 {
3754 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3755
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003756 //Initialize the WoWL service
3757 if(!hdd_init_wowl(pAdapter))
3758 {
3759 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3760 goto err_free_netdev;
3761 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003762 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 return pAdapter;
3764
3765err_free_netdev:
3766 free_netdev(pAdapter->dev);
3767 wlan_hdd_release_intf_addr( pHddCtx,
3768 pAdapter->macAddressCurrent.bytes );
3769
3770resume_bmps:
3771 //If bmps disabled enable it
3772 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3773 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303774 if (pHddCtx->hdd_wlan_suspended)
3775 {
3776 hdd_set_pwrparams(pHddCtx);
3777 }
3778 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 }
3780 return NULL;
3781}
3782
3783VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3784 tANI_U8 rtnl_held )
3785{
3786 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3787 VOS_STATUS status;
3788
3789 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3790 if( VOS_STATUS_SUCCESS != status )
3791 return status;
3792
3793 while ( pCurrent->pAdapter != pAdapter )
3794 {
3795 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3796 if( VOS_STATUS_SUCCESS != status )
3797 break;
3798
3799 pCurrent = pNext;
3800 }
3801 pAdapterNode = pCurrent;
3802 if( VOS_STATUS_SUCCESS == status )
3803 {
3804 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3805 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3806 hdd_remove_adapter( pHddCtx, pAdapterNode );
3807 vos_mem_free( pAdapterNode );
3808
Jeff Johnson295189b2012-06-20 16:38:30 -07003809
3810 /* If there is a single session of STA/P2P client, re-enable BMPS */
3811 if ((!vos_concurrent_sessions_running()) &&
3812 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3813 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3814 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303815 if (pHddCtx->hdd_wlan_suspended)
3816 {
3817 hdd_set_pwrparams(pHddCtx);
3818 }
3819 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 }
3821
3822 return VOS_STATUS_SUCCESS;
3823 }
3824
3825 return VOS_STATUS_E_FAILURE;
3826}
3827
3828VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3829{
3830 hdd_adapter_list_node_t *pHddAdapterNode;
3831 VOS_STATUS status;
3832
3833 ENTER();
3834
3835 do
3836 {
3837 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3838 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3839 {
3840 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3841 vos_mem_free( pHddAdapterNode );
3842 }
3843 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3844
3845 EXIT();
3846
3847 return VOS_STATUS_SUCCESS;
3848}
3849
3850void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3851{
3852 v_U8_t addIE[1] = {0};
3853
3854 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3855 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3856 eANI_BOOLEAN_FALSE) )
3857 {
3858 hddLog(LOGE,
3859 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3860 }
3861
3862 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3863 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3864 eANI_BOOLEAN_FALSE) )
3865 {
3866 hddLog(LOGE,
3867 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3868 }
3869
3870 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3871 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3872 eANI_BOOLEAN_FALSE) )
3873 {
3874 hddLog(LOGE,
3875 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3876 }
3877}
3878
3879VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3880{
3881 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3882 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3883 union iwreq_data wrqu;
3884
3885 ENTER();
3886
3887 switch(pAdapter->device_mode)
3888 {
3889 case WLAN_HDD_INFRA_STATION:
3890 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003891 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3893 {
3894 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3895 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3896 pAdapter->sessionId,
3897 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3898 else
3899 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3900 pAdapter->sessionId,
3901 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3902 //success implies disconnect command got queued up successfully
3903 if(halStatus == eHAL_STATUS_SUCCESS)
3904 {
3905 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3906 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3907 }
3908 memset(&wrqu, '\0', sizeof(wrqu));
3909 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3910 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3911 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3912 }
3913 else
3914 {
3915 hdd_abort_mac_scan(pHddCtx);
3916 }
3917
3918 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3919 {
3920 INIT_COMPLETION(pAdapter->session_close_comp_var);
3921 if (eHAL_STATUS_SUCCESS ==
3922 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3923 hdd_smeCloseSessionCallback, pAdapter))
3924 {
3925 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003926 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003927 &pAdapter->session_close_comp_var,
3928 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3929 }
3930 }
3931
3932 break;
3933
3934 case WLAN_HDD_SOFTAP:
3935 case WLAN_HDD_P2P_GO:
3936 //Any softap specific cleanup here...
3937 mutex_lock(&pHddCtx->sap_lock);
3938 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3939 {
3940 VOS_STATUS status;
3941 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3942
3943 //Stop Bss.
3944 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3945 if (VOS_IS_STATUS_SUCCESS(status))
3946 {
3947 hdd_hostapd_state_t *pHostapdState =
3948 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3949
3950 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3951
3952 if (!VOS_IS_STATUS_SUCCESS(status))
3953 {
3954 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003955 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003956 }
3957 }
3958 else
3959 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003960 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 }
3962 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3963
3964 if (eHAL_STATUS_FAILURE ==
3965 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3966 0, NULL, eANI_BOOLEAN_FALSE))
3967 {
3968 hddLog(LOGE,
3969 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003970 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003971 }
3972
3973 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3974 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3975 eANI_BOOLEAN_FALSE) )
3976 {
3977 hddLog(LOGE,
3978 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3979 }
3980
3981 // Reset WNI_CFG_PROBE_RSP Flags
3982 wlan_hdd_reset_prob_rspies(pAdapter);
3983 kfree(pAdapter->sessionCtx.ap.beacon);
3984 pAdapter->sessionCtx.ap.beacon = NULL;
3985 }
3986 mutex_unlock(&pHddCtx->sap_lock);
3987 break;
3988 case WLAN_HDD_MONITOR:
3989 break;
3990 default:
3991 break;
3992 }
3993
3994 EXIT();
3995 return VOS_STATUS_SUCCESS;
3996}
3997
3998VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3999{
4000 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4001 VOS_STATUS status;
4002 hdd_adapter_t *pAdapter;
4003
4004 ENTER();
4005
4006 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4007
4008 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4009 {
4010 pAdapter = pAdapterNode->pAdapter;
4011 netif_tx_disable(pAdapter->dev);
4012 netif_carrier_off(pAdapter->dev);
4013
4014 hdd_stop_adapter( pHddCtx, pAdapter );
4015
4016 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4017 pAdapterNode = pNext;
4018 }
4019
4020 EXIT();
4021
4022 return VOS_STATUS_SUCCESS;
4023}
4024
4025VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4026{
4027 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4028 VOS_STATUS status;
4029 hdd_adapter_t *pAdapter;
4030
4031 ENTER();
4032
4033 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4034
4035 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4036 {
4037 pAdapter = pAdapterNode->pAdapter;
4038 netif_tx_disable(pAdapter->dev);
4039 netif_carrier_off(pAdapter->dev);
4040
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004041 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4042
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 hdd_deinit_tx_rx(pAdapter);
4044 hdd_wmm_adapter_close(pAdapter);
4045
4046 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4047 pAdapterNode = pNext;
4048 }
4049
4050 EXIT();
4051
4052 return VOS_STATUS_SUCCESS;
4053}
4054
4055VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4056{
4057 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4058 VOS_STATUS status;
4059 hdd_adapter_t *pAdapter;
4060 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304061 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004062
4063 ENTER();
4064
4065 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4066
4067 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4068 {
4069 pAdapter = pAdapterNode->pAdapter;
4070
4071 switch(pAdapter->device_mode)
4072 {
4073 case WLAN_HDD_INFRA_STATION:
4074 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004075 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304076
4077 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4078
Jeff Johnson295189b2012-06-20 16:38:30 -07004079 hdd_init_station_mode(pAdapter);
4080 /* Open the gates for HDD to receive Wext commands */
4081 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004082 pHddCtx->scan_info.mScanPending = FALSE;
4083 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004084
4085 //Trigger the initial scan
4086 hdd_wlan_initial_scan(pAdapter);
4087
4088 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304089 if (eConnectionState_Associated == connState ||
4090 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 {
4092 union iwreq_data wrqu;
4093 memset(&wrqu, '\0', sizeof(wrqu));
4094 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4095 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4096 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004097 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004098
Jeff Johnson295189b2012-06-20 16:38:30 -07004099 /* indicate disconnected event to nl80211 */
4100 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4101 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004102 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304103 else if (eConnectionState_Connecting == connState)
4104 {
4105 /*
4106 * Indicate connect failure to supplicant if we were in the
4107 * process of connecting
4108 */
4109 cfg80211_connect_result(pAdapter->dev, NULL,
4110 NULL, 0, NULL, 0,
4111 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4112 GFP_KERNEL);
4113 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004114 break;
4115
4116 case WLAN_HDD_SOFTAP:
4117 /* softAP can handle SSR */
4118 break;
4119
4120 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004121 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4122 __func__);
4123 /* event supplicant to restart */
4124 cfg80211_del_sta(pAdapter->dev,
4125 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004126 break;
4127
4128 case WLAN_HDD_MONITOR:
4129 /* monitor interface start */
4130 break;
4131 default:
4132 break;
4133 }
4134
4135 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4136 pAdapterNode = pNext;
4137 }
4138
4139 EXIT();
4140
4141 return VOS_STATUS_SUCCESS;
4142}
4143
4144VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4145{
4146 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4147 hdd_adapter_t *pAdapter;
4148 VOS_STATUS status;
4149 v_U32_t roamId;
4150
4151 ENTER();
4152
4153 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4154
4155 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4156 {
4157 pAdapter = pAdapterNode->pAdapter;
4158
4159 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4160 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4161 {
4162 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4163 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4164
4165 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4166 init_completion(&pAdapter->disconnect_comp_var);
4167 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4168 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4169
4170 wait_for_completion_interruptible_timeout(
4171 &pAdapter->disconnect_comp_var,
4172 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4173
4174 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4175 pHddCtx->isAmpAllowed = VOS_FALSE;
4176 sme_RoamConnect(pHddCtx->hHal,
4177 pAdapter->sessionId, &(pWextState->roamProfile),
4178 &roamId);
4179 }
4180
4181 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4182 pAdapterNode = pNext;
4183 }
4184
4185 EXIT();
4186
4187 return VOS_STATUS_SUCCESS;
4188}
4189
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004190void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4191{
4192 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4193 VOS_STATUS status;
4194 hdd_adapter_t *pAdapter;
4195 hdd_station_ctx_t *pHddStaCtx;
4196 hdd_ap_ctx_t *pHddApCtx;
4197 hdd_hostapd_state_t * pHostapdState;
4198 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4199 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4200 const char *p2pMode = "DEV";
4201 const char *ccMode = "Standalone";
4202 int n;
4203
4204 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4205 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4206 {
4207 pAdapter = pAdapterNode->pAdapter;
4208 switch (pAdapter->device_mode) {
4209 case WLAN_HDD_INFRA_STATION:
4210 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4211 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4212 staChannel = pHddStaCtx->conn_info.operationChannel;
4213 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4214 }
4215 break;
4216 case WLAN_HDD_P2P_CLIENT:
4217 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4218 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4219 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4220 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4221 p2pMode = "CLI";
4222 }
4223 break;
4224 case WLAN_HDD_P2P_GO:
4225 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4226 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4227 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4228 p2pChannel = pHddApCtx->operatingChannel;
4229 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4230 }
4231 p2pMode = "GO";
4232 break;
4233 case WLAN_HDD_SOFTAP:
4234 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4235 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4236 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4237 apChannel = pHddApCtx->operatingChannel;
4238 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4239 }
4240 break;
4241 default:
4242 break;
4243 }
4244 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4245 pAdapterNode = pNext;
4246 }
4247 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4248 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4249 }
4250 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4251 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4252 if (p2pChannel > 0) {
4253 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4254 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4255 }
4256 if (apChannel > 0) {
4257 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4258 apChannel, MAC_ADDR_ARRAY(apBssid));
4259 }
4260
4261 if (p2pChannel > 0 && apChannel > 0) {
4262 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4263 }
4264}
4265
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004266bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004267{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004268 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004269}
4270
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004271/* Once SSR is disabled then it cannot be set. */
4272void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004273{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004274 if (HDD_SSR_DISABLED == isSsrRequired)
4275 return;
4276
Jeff Johnson295189b2012-06-20 16:38:30 -07004277 isSsrRequired = value;
4278}
4279
4280VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4281 hdd_adapter_list_node_t** ppAdapterNode)
4282{
4283 VOS_STATUS status;
4284 spin_lock(&pHddCtx->hddAdapters.lock);
4285 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4286 (hdd_list_node_t**) ppAdapterNode );
4287 spin_unlock(&pHddCtx->hddAdapters.lock);
4288 return status;
4289}
4290
4291VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4292 hdd_adapter_list_node_t* pAdapterNode,
4293 hdd_adapter_list_node_t** pNextAdapterNode)
4294{
4295 VOS_STATUS status;
4296 spin_lock(&pHddCtx->hddAdapters.lock);
4297 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4298 (hdd_list_node_t*) pAdapterNode,
4299 (hdd_list_node_t**)pNextAdapterNode );
4300
4301 spin_unlock(&pHddCtx->hddAdapters.lock);
4302 return status;
4303}
4304
4305VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4306 hdd_adapter_list_node_t* pAdapterNode)
4307{
4308 VOS_STATUS status;
4309 spin_lock(&pHddCtx->hddAdapters.lock);
4310 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4311 &pAdapterNode->node );
4312 spin_unlock(&pHddCtx->hddAdapters.lock);
4313 return status;
4314}
4315
4316VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4317 hdd_adapter_list_node_t** ppAdapterNode)
4318{
4319 VOS_STATUS status;
4320 spin_lock(&pHddCtx->hddAdapters.lock);
4321 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4322 (hdd_list_node_t**) ppAdapterNode );
4323 spin_unlock(&pHddCtx->hddAdapters.lock);
4324 return status;
4325}
4326
4327VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4328 hdd_adapter_list_node_t* pAdapterNode)
4329{
4330 VOS_STATUS status;
4331 spin_lock(&pHddCtx->hddAdapters.lock);
4332 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4333 (hdd_list_node_t*) pAdapterNode );
4334 spin_unlock(&pHddCtx->hddAdapters.lock);
4335 return status;
4336}
4337
4338VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4339 hdd_adapter_list_node_t* pAdapterNode)
4340{
4341 VOS_STATUS status;
4342 spin_lock(&pHddCtx->hddAdapters.lock);
4343 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4344 (hdd_list_node_t*) pAdapterNode );
4345 spin_unlock(&pHddCtx->hddAdapters.lock);
4346 return status;
4347}
4348
4349hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4350 tSirMacAddr macAddr )
4351{
4352 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4353 hdd_adapter_t *pAdapter;
4354 VOS_STATUS status;
4355
4356 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4357
4358 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4359 {
4360 pAdapter = pAdapterNode->pAdapter;
4361
4362 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4363 macAddr, sizeof(tSirMacAddr) ) )
4364 {
4365 return pAdapter;
4366 }
4367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4368 pAdapterNode = pNext;
4369 }
4370
4371 return NULL;
4372
4373}
4374
4375hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4376{
4377 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4378 hdd_adapter_t *pAdapter;
4379 VOS_STATUS status;
4380
4381 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4382
4383 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4384 {
4385 pAdapter = pAdapterNode->pAdapter;
4386
4387 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4388 IFNAMSIZ ) )
4389 {
4390 return pAdapter;
4391 }
4392 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4393 pAdapterNode = pNext;
4394 }
4395
4396 return NULL;
4397
4398}
4399
4400hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4401{
4402 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4403 hdd_adapter_t *pAdapter;
4404 VOS_STATUS status;
4405
4406 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4407
4408 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4409 {
4410 pAdapter = pAdapterNode->pAdapter;
4411
4412 if( pAdapter && (mode == pAdapter->device_mode) )
4413 {
4414 return pAdapter;
4415 }
4416 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4417 pAdapterNode = pNext;
4418 }
4419
4420 return NULL;
4421
4422}
4423
4424//Remove this function later
4425hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4426{
4427 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4428 hdd_adapter_t *pAdapter;
4429 VOS_STATUS status;
4430
4431 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4432
4433 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4434 {
4435 pAdapter = pAdapterNode->pAdapter;
4436
4437 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4438 {
4439 return pAdapter;
4440 }
4441
4442 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4443 pAdapterNode = pNext;
4444 }
4445
4446 return NULL;
4447
4448}
4449
Jeff Johnson295189b2012-06-20 16:38:30 -07004450/**---------------------------------------------------------------------------
4451
4452 \brief hdd_set_monitor_tx_adapter() -
4453
4454 This API initializes the adapter to be used while transmitting on monitor
4455 adapter.
4456
4457 \param - pHddCtx - Pointer to the HDD context.
4458 pAdapter - Adapter that will used for TX. This can be NULL.
4459 \return - None.
4460 --------------------------------------------------------------------------*/
4461void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4462{
4463 hdd_adapter_t *pMonAdapter;
4464
4465 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4466
4467 if( NULL != pMonAdapter )
4468 {
4469 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4470 }
4471}
Jeff Johnson295189b2012-06-20 16:38:30 -07004472/**---------------------------------------------------------------------------
4473
4474 \brief hdd_select_queue() -
4475
4476 This API returns the operating channel of the requested device mode
4477
4478 \param - pHddCtx - Pointer to the HDD context.
4479 - mode - Device mode for which operating channel is required
4480 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4481 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4482 \return - channel number. "0" id the requested device is not found OR it is not connected.
4483 --------------------------------------------------------------------------*/
4484v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4485{
4486 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4487 VOS_STATUS status;
4488 hdd_adapter_t *pAdapter;
4489 v_U8_t operatingChannel = 0;
4490
4491 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4492
4493 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4494 {
4495 pAdapter = pAdapterNode->pAdapter;
4496
4497 if( mode == pAdapter->device_mode )
4498 {
4499 switch(pAdapter->device_mode)
4500 {
4501 case WLAN_HDD_INFRA_STATION:
4502 case WLAN_HDD_P2P_CLIENT:
4503 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4504 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4505 break;
4506 case WLAN_HDD_SOFTAP:
4507 case WLAN_HDD_P2P_GO:
4508 /*softap connection info */
4509 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4510 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4511 break;
4512 default:
4513 break;
4514 }
4515
4516 break; //Found the device of interest. break the loop
4517 }
4518
4519 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4520 pAdapterNode = pNext;
4521 }
4522 return operatingChannel;
4523}
4524
4525#ifdef WLAN_FEATURE_PACKET_FILTERING
4526/**---------------------------------------------------------------------------
4527
4528 \brief hdd_set_multicast_list() -
4529
4530 This used to set the multicast address list.
4531
4532 \param - dev - Pointer to the WLAN device.
4533 - skb - Pointer to OS packet (sk_buff).
4534 \return - success/fail
4535
4536 --------------------------------------------------------------------------*/
4537static void hdd_set_multicast_list(struct net_device *dev)
4538{
4539 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 int mc_count;
4541 int i = 0;
4542 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304543
4544 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004545 {
4546 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304547 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 return;
4549 }
4550
4551 if (dev->flags & IFF_ALLMULTI)
4552 {
4553 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004554 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304555 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004556 }
4557 else
4558 {
4559 mc_count = netdev_mc_count(dev);
4560 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004561 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4563 {
4564 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004565 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304566 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004567 return;
4568 }
4569
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304570 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004571
4572 netdev_for_each_mc_addr(ha, dev) {
4573 if (i == mc_count)
4574 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304575 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4576 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4577 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004578 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304579 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 i++;
4581 }
4582 }
4583 return;
4584}
4585#endif
4586
4587/**---------------------------------------------------------------------------
4588
4589 \brief hdd_select_queue() -
4590
4591 This function is registered with the Linux OS for network
4592 core to decide which queue to use first.
4593
4594 \param - dev - Pointer to the WLAN device.
4595 - skb - Pointer to OS packet (sk_buff).
4596 \return - ac, Queue Index/access category corresponding to UP in IP header
4597
4598 --------------------------------------------------------------------------*/
4599v_U16_t hdd_select_queue(struct net_device *dev,
4600 struct sk_buff *skb)
4601{
4602 return hdd_wmm_select_queue(dev, skb);
4603}
4604
4605
4606/**---------------------------------------------------------------------------
4607
4608 \brief hdd_wlan_initial_scan() -
4609
4610 This function triggers the initial scan
4611
4612 \param - pAdapter - Pointer to the HDD adapter.
4613
4614 --------------------------------------------------------------------------*/
4615void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4616{
4617 tCsrScanRequest scanReq;
4618 tCsrChannelInfo channelInfo;
4619 eHalStatus halStatus;
4620 unsigned long scanId;
4621 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4622
4623 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4624 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4625 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4626
4627 if(sme_Is11dSupported(pHddCtx->hHal))
4628 {
4629 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4630 if ( HAL_STATUS_SUCCESS( halStatus ) )
4631 {
4632 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4633 if( !scanReq.ChannelInfo.ChannelList )
4634 {
4635 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4636 vos_mem_free(channelInfo.ChannelList);
4637 return;
4638 }
4639 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4640 channelInfo.numOfChannels);
4641 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4642 vos_mem_free(channelInfo.ChannelList);
4643 }
4644
4645 scanReq.scanType = eSIR_PASSIVE_SCAN;
4646 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4647 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4648 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4649 }
4650 else
4651 {
4652 scanReq.scanType = eSIR_ACTIVE_SCAN;
4653 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4654 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4655 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4656 }
4657
4658 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4659 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4660 {
4661 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4662 __func__, halStatus );
4663 }
4664
4665 if(sme_Is11dSupported(pHddCtx->hHal))
4666 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4667}
4668
4669struct fullPowerContext
4670{
4671 struct completion completion;
4672 unsigned int magic;
4673};
4674#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4675
4676/**---------------------------------------------------------------------------
4677
4678 \brief hdd_full_power_callback() - HDD full power callback function
4679
4680 This is the function invoked by SME to inform the result of a full power
4681 request issued by HDD
4682
4683 \param - callbackcontext - Pointer to cookie
4684 \param - status - result of request
4685
4686 \return - None
4687
4688 --------------------------------------------------------------------------*/
4689static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4690{
4691 struct fullPowerContext *pContext = callbackContext;
4692
4693 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304694 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004695
4696 if (NULL == callbackContext)
4697 {
4698 hddLog(VOS_TRACE_LEVEL_ERROR,
4699 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004700 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004701 return;
4702 }
4703
4704 /* there is a race condition that exists between this callback function
4705 and the caller since the caller could time out either before or
4706 while this code is executing. we'll assume the timeout hasn't
4707 occurred, but we'll verify that right before we save our work */
4708
4709 if (POWER_CONTEXT_MAGIC != pContext->magic)
4710 {
4711 /* the caller presumably timed out so there is nothing we can do */
4712 hddLog(VOS_TRACE_LEVEL_WARN,
4713 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004714 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004715 return;
4716 }
4717
4718 /* the race is on. caller could have timed out immediately after
4719 we verified the magic, but if so, caller will wait a short time
4720 for us to notify the caller, so the context will stay valid */
4721 complete(&pContext->completion);
4722}
4723
4724/**---------------------------------------------------------------------------
4725
4726 \brief hdd_wlan_exit() - HDD WLAN exit function
4727
4728 This is the driver exit point (invoked during rmmod)
4729
4730 \param - pHddCtx - Pointer to the HDD Context
4731
4732 \return - None
4733
4734 --------------------------------------------------------------------------*/
4735void hdd_wlan_exit(hdd_context_t *pHddCtx)
4736{
4737 eHalStatus halStatus;
4738 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4739 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304740 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004741 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004742 struct fullPowerContext powerContext;
4743 long lrc;
4744
4745 ENTER();
4746
Jeff Johnson88ba7742013-02-27 14:36:02 -08004747 if (VOS_FTM_MODE != hdd_get_conparam())
4748 {
4749 // Unloading, restart logic is no more required.
4750 wlan_hdd_restart_deinit(pHddCtx);
4751 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004752
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004754 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 {
4757 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4758 WLAN_HDD_INFRA_STATION);
4759 if (pAdapter == NULL)
4760 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4761
4762 if (pAdapter != NULL)
4763 {
4764 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4765 hdd_UnregisterWext(pAdapter->dev);
4766 }
4767 }
4768 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004769
Jeff Johnson295189b2012-06-20 16:38:30 -07004770 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004771 {
4772 wlan_hdd_ftm_close(pHddCtx);
4773 goto free_hdd_ctx;
4774 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 //Stop the Interface TX queue.
4776 //netif_tx_disable(pWlanDev);
4777 //netif_carrier_off(pWlanDev);
4778
Jeff Johnson295189b2012-06-20 16:38:30 -07004779 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4780 {
4781 pAdapter = hdd_get_adapter(pHddCtx,
4782 WLAN_HDD_SOFTAP);
4783 }
4784 else
4785 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004786 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004787 {
4788 pAdapter = hdd_get_adapter(pHddCtx,
4789 WLAN_HDD_INFRA_STATION);
4790 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004791 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004792 /* DeRegister with platform driver as client for Suspend/Resume */
4793 vosStatus = hddDeregisterPmOps(pHddCtx);
4794 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4795 {
4796 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4797 VOS_ASSERT(0);
4798 }
4799
4800 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4801 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4802 {
4803 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4804 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004805
4806 // Cancel any outstanding scan requests. We are about to close all
4807 // of our adapters, but an adapter structure is what SME passes back
4808 // to our callback function. Hence if there are any outstanding scan
4809 // requests then there is a race condition between when the adapter
4810 // is closed and when the callback is invoked. We try to resolve that
4811 // race condition here by canceling any outstanding scans before we
4812 // close the adapters.
4813 // Note that the scans may be cancelled in an asynchronous manner, so
4814 // ideally there needs to be some kind of synchronization. Rather than
4815 // introduce a new synchronization here, we will utilize the fact that
4816 // we are about to Request Full Power, and since that is synchronized,
4817 // the expectation is that by the time Request Full Power has completed,
4818 // all scans will be cancelled.
4819 hdd_abort_mac_scan( pHddCtx );
4820
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304821 //Stop the timer if already running
4822 if (VOS_TIMER_STATE_RUNNING ==
4823 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4824 {
4825 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4826 }
4827
4828 // Destroy hdd_p2p_go_conn_is_in_progress timer
4829 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4830 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4831 {
4832 hddLog(VOS_TRACE_LEVEL_ERROR,
4833 "%s: Cannot deallocate p2p connection timer", __func__);
4834 }
4835
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 //Disable IMPS/BMPS as we do not want the device to enter any power
4837 //save mode during shutdown
4838 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4839 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4840 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4841
4842 //Ensure that device is in full power as we will touch H/W during vos_Stop
4843 init_completion(&powerContext.completion);
4844 powerContext.magic = POWER_CONTEXT_MAGIC;
4845
4846 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4847 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4848
4849 if (eHAL_STATUS_SUCCESS != halStatus)
4850 {
4851 if (eHAL_STATUS_PMC_PENDING == halStatus)
4852 {
4853 /* request was sent -- wait for the response */
4854 lrc = wait_for_completion_interruptible_timeout(
4855 &powerContext.completion,
4856 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4857 /* either we have a response or we timed out
4858 either way, first invalidate our magic */
4859 powerContext.magic = 0;
4860 if (lrc <= 0)
4861 {
4862 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004863 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004864 /* there is a race condition such that the callback
4865 function could be executing at the same time we are. of
4866 primary concern is if the callback function had already
4867 verified the "magic" but hasn't yet set the completion
4868 variable. Since the completion variable is on our
4869 stack, we'll delay just a bit to make sure the data is
4870 still valid if that is the case */
4871 msleep(50);
4872 }
4873 }
4874 else
4875 {
4876 hddLog(VOS_TRACE_LEVEL_ERROR,
4877 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004878 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004879 VOS_ASSERT(0);
4880 /* continue -- need to clean up as much as possible */
4881 }
4882 }
4883
Yue Ma0d4891e2013-08-06 17:01:45 -07004884 hdd_debugfs_exit(pHddCtx);
4885
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 // Unregister the Net Device Notifier
4887 unregister_netdevice_notifier(&hdd_netdev_notifier);
4888
Jeff Johnson295189b2012-06-20 16:38:30 -07004889 hdd_stop_all_adapters( pHddCtx );
4890
Jeff Johnson295189b2012-06-20 16:38:30 -07004891#ifdef WLAN_BTAMP_FEATURE
4892 vosStatus = WLANBAP_Stop(pVosContext);
4893 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4894 {
4895 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4896 "%s: Failed to stop BAP",__func__);
4897 }
4898#endif //WLAN_BTAMP_FEATURE
4899
4900 //Stop all the modules
4901 vosStatus = vos_stop( pVosContext );
4902 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4903 {
4904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4905 "%s: Failed to stop VOSS",__func__);
4906 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4907 }
4908
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 //Assert Deep sleep signal now to put Libra HW in lowest power state
4910 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4911 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4912
4913 //Vote off any PMIC voltage supplies
4914 vos_chipPowerDown(NULL, NULL, NULL);
4915
4916 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4917
Leo Chang59cdc7e2013-07-10 10:08:21 -07004918
Jeff Johnson295189b2012-06-20 16:38:30 -07004919 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004920 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004921
4922 //Close the scheduler before calling vos_close to make sure no thread is
4923 // scheduled after the each module close is called i.e after all the data
4924 // structures are freed.
4925 vosStatus = vos_sched_close( pVosContext );
4926 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4927 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4928 "%s: Failed to close VOSS Scheduler",__func__);
4929 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4930 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004931#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004932#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4933 /* Destroy the wake lock */
4934 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4935#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004936 /* Destroy the wake lock */
4937 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004938#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004939
4940 //Close VOSS
4941 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4942 vos_close(pVosContext);
4943
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 //Close Watchdog
4945 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4946 vos_watchdog_close(pVosContext);
4947
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05304948 //Clean up HDD Nlink Service
4949 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07004950#ifdef WLAN_KD_READY_NOTIFIER
4951 nl_srv_exit(pHddCtx->ptt_pid);
4952#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05304953 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07004954#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05304955
Jeff Johnson295189b2012-06-20 16:38:30 -07004956 /* Cancel the vote for XO Core ON.
4957 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4958 * exited at this point
4959 */
4960 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4961 " when WLAN is turned OFF\n");
4962 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4963 {
4964 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4965 " Not returning failure."
4966 " Power consumed will be high\n");
4967 }
4968
4969 hdd_close_all_adapters( pHddCtx );
4970
4971
4972 //Free up dynamically allocated members inside HDD Adapter
4973 kfree(pHddCtx->cfg_ini);
4974 pHddCtx->cfg_ini= NULL;
4975
4976 /* free the power on lock from platform driver */
4977 if (free_riva_power_on_lock("wlan"))
4978 {
4979 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4980 __func__);
4981 }
4982
Jeff Johnson88ba7742013-02-27 14:36:02 -08004983free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004984 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004986 if (hdd_is_ssr_required())
4987 {
4988 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004989 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004990 msleep(5000);
4991 }
4992 hdd_set_ssr_required (VOS_FALSE);
4993}
4994
4995
4996/**---------------------------------------------------------------------------
4997
4998 \brief hdd_update_config_from_nv() - Function to update the contents of
4999 the running configuration with parameters taken from NV storage
5000
5001 \param - pHddCtx - Pointer to the HDD global context
5002
5003 \return - VOS_STATUS_SUCCESS if successful
5004
5005 --------------------------------------------------------------------------*/
5006static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5007{
Jeff Johnson295189b2012-06-20 16:38:30 -07005008 v_BOOL_t itemIsValid = VOS_FALSE;
5009 VOS_STATUS status;
5010 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5011 v_U8_t macLoop;
5012
5013 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5014 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5015 if(status != VOS_STATUS_SUCCESS)
5016 {
5017 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5018 return VOS_STATUS_E_FAILURE;
5019 }
5020
5021 if (itemIsValid == VOS_TRUE)
5022 {
5023 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5024 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5025 VOS_MAX_CONCURRENCY_PERSONA);
5026 if(status != VOS_STATUS_SUCCESS)
5027 {
5028 /* Get MAC from NV fail, not update CFG info
5029 * INI MAC value will be used for MAC setting */
5030 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5031 return VOS_STATUS_E_FAILURE;
5032 }
5033
5034 /* If first MAC is not valid, treat all others are not valid
5035 * Then all MACs will be got from ini file */
5036 if(vos_is_macaddr_zero(&macFromNV[0]))
5037 {
5038 /* MAC address in NV file is not configured yet */
5039 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5040 return VOS_STATUS_E_INVAL;
5041 }
5042
5043 /* Get MAC address from NV, update CFG info */
5044 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5045 {
5046 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5047 {
5048 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5049 /* This MAC is not valid, skip it
5050 * This MAC will be got from ini file */
5051 }
5052 else
5053 {
5054 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5055 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5056 VOS_MAC_ADDR_SIZE);
5057 }
5058 }
5059 }
5060 else
5061 {
5062 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5063 return VOS_STATUS_E_FAILURE;
5064 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005065
Jeff Johnson295189b2012-06-20 16:38:30 -07005066
5067 return VOS_STATUS_SUCCESS;
5068}
5069
5070/**---------------------------------------------------------------------------
5071
5072 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5073
5074 \param - pAdapter - Pointer to the HDD
5075
5076 \return - None
5077
5078 --------------------------------------------------------------------------*/
5079VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5080{
5081 eHalStatus halStatus;
5082 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305083 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005084
Jeff Johnson295189b2012-06-20 16:38:30 -07005085
5086 // Send ready indication to the HDD. This will kick off the MAC
5087 // into a 'running' state and should kick off an initial scan.
5088 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5089 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5090 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305091 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 "code %08d [x%08x]",__func__, halStatus, halStatus );
5093 return VOS_STATUS_E_FAILURE;
5094 }
5095
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305096 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5098 // And RIVA will crash
5099 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5100 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305101 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5102 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5103
5104
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 return VOS_STATUS_SUCCESS;
5106}
5107
Jeff Johnson295189b2012-06-20 16:38:30 -07005108/* wake lock APIs for HDD */
5109void hdd_prevent_suspend(void)
5110{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005111#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005112 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005113#else
5114 wcnss_prevent_suspend();
5115#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005116}
5117
5118void hdd_allow_suspend(void)
5119{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005120#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005122#else
5123 wcnss_allow_suspend();
5124#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005125}
5126
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005127void hdd_allow_suspend_timeout(v_U32_t timeout)
5128{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005129#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005130 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005131#else
5132 /* Do nothing as there is no API in wcnss for timeout*/
5133#endif
5134}
5135
Jeff Johnson295189b2012-06-20 16:38:30 -07005136/**---------------------------------------------------------------------------
5137
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005138 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5139 information between Host and Riva
5140
5141 This function gets reported version of FW
5142 It also finds the version of Riva headers used to compile the host
5143 It compares the above two and prints a warning if they are different
5144 It gets the SW and HW version string
5145 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5146 indicating the features they support through a bitmap
5147
5148 \param - pHddCtx - Pointer to HDD context
5149
5150 \return - void
5151
5152 --------------------------------------------------------------------------*/
5153
5154void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5155{
5156
5157 tSirVersionType versionCompiled;
5158 tSirVersionType versionReported;
5159 tSirVersionString versionString;
5160 tANI_U8 fwFeatCapsMsgSupported = 0;
5161 VOS_STATUS vstatus;
5162
5163 /* retrieve and display WCNSS version information */
5164 do {
5165
5166 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5167 &versionCompiled);
5168 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5169 {
5170 hddLog(VOS_TRACE_LEVEL_FATAL,
5171 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005172 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005173 break;
5174 }
5175
5176 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5177 &versionReported);
5178 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5179 {
5180 hddLog(VOS_TRACE_LEVEL_FATAL,
5181 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005182 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005183 break;
5184 }
5185
5186 if ((versionCompiled.major != versionReported.major) ||
5187 (versionCompiled.minor != versionReported.minor) ||
5188 (versionCompiled.version != versionReported.version) ||
5189 (versionCompiled.revision != versionReported.revision))
5190 {
5191 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5192 "Host expected %u.%u.%u.%u\n",
5193 WLAN_MODULE_NAME,
5194 (int)versionReported.major,
5195 (int)versionReported.minor,
5196 (int)versionReported.version,
5197 (int)versionReported.revision,
5198 (int)versionCompiled.major,
5199 (int)versionCompiled.minor,
5200 (int)versionCompiled.version,
5201 (int)versionCompiled.revision);
5202 }
5203 else
5204 {
5205 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5206 WLAN_MODULE_NAME,
5207 (int)versionReported.major,
5208 (int)versionReported.minor,
5209 (int)versionReported.version,
5210 (int)versionReported.revision);
5211 }
5212
5213 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5214 versionString,
5215 sizeof(versionString));
5216 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5217 {
5218 hddLog(VOS_TRACE_LEVEL_FATAL,
5219 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005220 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005221 break;
5222 }
5223
5224 pr_info("%s: WCNSS software version %s\n",
5225 WLAN_MODULE_NAME, versionString);
5226
5227 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5228 versionString,
5229 sizeof(versionString));
5230 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5231 {
5232 hddLog(VOS_TRACE_LEVEL_FATAL,
5233 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005234 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005235 break;
5236 }
5237
5238 pr_info("%s: WCNSS hardware version %s\n",
5239 WLAN_MODULE_NAME, versionString);
5240
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005241 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5242 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005243 send the message only if it the riva is 1.1
5244 minor numbers for different riva branches:
5245 0 -> (1.0)Mainline Build
5246 1 -> (1.1)Mainline Build
5247 2->(1.04) Stability Build
5248 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005249 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005250 ((versionReported.minor>=1) && (versionReported.version>=1)))
5251 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5252 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005253
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005254 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005255 {
5256#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5257 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5258 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5259#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005260 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5261 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5262 {
5263 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5264 }
5265
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005266 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005267 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005268
5269 } while (0);
5270
5271}
5272
5273/**---------------------------------------------------------------------------
5274
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305275 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5276
5277 \param - pHddCtx - Pointer to the hdd context
5278
5279 \return - true if hardware supports 5GHz
5280
5281 --------------------------------------------------------------------------*/
5282static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5283{
5284 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5285 * then hardware support 5Ghz.
5286 */
5287 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5288 {
5289 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5290 return true;
5291 }
5292 else
5293 {
5294 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5295 __func__);
5296 return false;
5297 }
5298}
5299
5300
5301/**---------------------------------------------------------------------------
5302
Jeff Johnson295189b2012-06-20 16:38:30 -07005303 \brief hdd_wlan_startup() - HDD init function
5304
5305 This is the driver startup code executed once a WLAN device has been detected
5306
5307 \param - dev - Pointer to the underlying device
5308
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005309 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005310
5311 --------------------------------------------------------------------------*/
5312
5313int hdd_wlan_startup(struct device *dev )
5314{
5315 VOS_STATUS status;
5316 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005317 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 hdd_context_t *pHddCtx = NULL;
5319 v_CONTEXT_t pVosContext= NULL;
5320#ifdef WLAN_BTAMP_FEATURE
5321 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5322 WLANBAP_ConfigType btAmpConfig;
5323 hdd_config_t *pConfig;
5324#endif
5325 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005326 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005327
5328 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005329 /*
5330 * cfg80211: wiphy allocation
5331 */
5332 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5333
5334 if(wiphy == NULL)
5335 {
5336 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005337 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 }
5339
5340 pHddCtx = wiphy_priv(wiphy);
5341
Jeff Johnson295189b2012-06-20 16:38:30 -07005342 //Initialize the adapter context to zeros.
5343 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5344
Jeff Johnson295189b2012-06-20 16:38:30 -07005345 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 hdd_prevent_suspend();
5347 pHddCtx->isLoadUnloadInProgress = TRUE;
5348
5349 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5350
5351 /*Get vos context here bcoz vos_open requires it*/
5352 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5353
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005354 if(pVosContext == NULL)
5355 {
5356 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5357 goto err_free_hdd_context;
5358 }
5359
Jeff Johnson295189b2012-06-20 16:38:30 -07005360 //Save the Global VOSS context in adapter context for future.
5361 pHddCtx->pvosContext = pVosContext;
5362
5363 //Save the adapter context in global context for future.
5364 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5365
Jeff Johnson295189b2012-06-20 16:38:30 -07005366 pHddCtx->parent_dev = dev;
5367
5368 init_completion(&pHddCtx->full_pwr_comp_var);
5369 init_completion(&pHddCtx->standby_comp_var);
5370 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005371 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005372 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +05305373 init_completion(&pHddCtx->driver_crda_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005374
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305375 spin_lock_init(&pHddCtx->schedScan_lock);
5376
Jeff Johnson295189b2012-06-20 16:38:30 -07005377 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5378
5379 // Load all config first as TL config is needed during vos_open
5380 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5381 if(pHddCtx->cfg_ini == NULL)
5382 {
5383 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5384 goto err_free_hdd_context;
5385 }
5386
5387 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5388
5389 // Read and parse the qcom_cfg.ini file
5390 status = hdd_parse_config_ini( pHddCtx );
5391 if ( VOS_STATUS_SUCCESS != status )
5392 {
5393 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5394 __func__, WLAN_INI_FILE);
5395 goto err_config;
5396 }
5397
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305398 /* INI has been read, initialise the configuredMcastBcastFilter with
5399 * INI value as this will serve as the default value
5400 */
5401 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5402 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5403 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305404
5405 if (false == hdd_is_5g_supported(pHddCtx))
5406 {
5407 //5Ghz is not supported.
5408 if (1 != pHddCtx->cfg_ini->nBandCapability)
5409 {
5410 hddLog(VOS_TRACE_LEVEL_INFO,
5411 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5412 pHddCtx->cfg_ini->nBandCapability = 1;
5413 }
5414 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305415
5416 /* If SNR Monitoring is enabled, FW has to parse all beacons
5417 * for calcaluting and storing the average SNR, so set Nth beacon
5418 * filter to 1 to enable FW to parse all the beaocons
5419 */
5420 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5421 {
5422 /* The log level is deliberately set to WARN as overriding
5423 * nthBeaconFilter to 1 will increase power cosumption and this
5424 * might just prove helpful to detect the power issue.
5425 */
5426 hddLog(VOS_TRACE_LEVEL_WARN,
5427 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5428 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5429 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005430 /*
5431 * cfg80211: Initialization and registration ...
5432 */
5433 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5434 {
5435 hddLog(VOS_TRACE_LEVEL_FATAL,
5436 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5437 goto err_wiphy_reg;
5438 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005439
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005440 // Update VOS trace levels based upon the cfg.ini
5441 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5442 pHddCtx->cfg_ini->vosTraceEnableBAP);
5443 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5444 pHddCtx->cfg_ini->vosTraceEnableTL);
5445 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5446 pHddCtx->cfg_ini->vosTraceEnableWDI);
5447 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5448 pHddCtx->cfg_ini->vosTraceEnableHDD);
5449 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5450 pHddCtx->cfg_ini->vosTraceEnableSME);
5451 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5452 pHddCtx->cfg_ini->vosTraceEnablePE);
5453 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5454 pHddCtx->cfg_ini->vosTraceEnableWDA);
5455 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5456 pHddCtx->cfg_ini->vosTraceEnableSYS);
5457 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5458 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005459 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5460 pHddCtx->cfg_ini->vosTraceEnableSAP);
5461 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5462 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005463
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 // Update WDI trace levels based upon the cfg.ini
5465 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5466 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5467 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5468 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5469 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5470 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5471 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5472 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005473
Jeff Johnson88ba7742013-02-27 14:36:02 -08005474 if (VOS_FTM_MODE == hdd_get_conparam())
5475 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5477 {
5478 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5479 goto err_free_hdd_context;
5480 }
5481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5482 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005484
Jeff Johnson88ba7742013-02-27 14:36:02 -08005485 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5487 {
5488 status = vos_watchdog_open(pVosContext,
5489 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5490
5491 if(!VOS_IS_STATUS_SUCCESS( status ))
5492 {
5493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005494 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 }
5496 }
5497
5498 pHddCtx->isLogpInProgress = FALSE;
5499 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5500
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5502 if(!VOS_IS_STATUS_SUCCESS(status))
5503 {
5504 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005505 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 }
5507
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 status = vos_open( &pVosContext, 0);
5509 if ( !VOS_IS_STATUS_SUCCESS( status ))
5510 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005511 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5512 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 }
5514
Jeff Johnson295189b2012-06-20 16:38:30 -07005515 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5516
5517 if ( NULL == pHddCtx->hHal )
5518 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005519 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 goto err_vosclose;
5521 }
5522
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005523 status = vos_preStart( pHddCtx->pvosContext );
5524 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5525 {
5526 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5527 goto err_vosclose;
5528 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005529
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005530 /* Note that the vos_preStart() sequence triggers the cfg download.
5531 The cfg download must occur before we update the SME config
5532 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005533 status = hdd_set_sme_config( pHddCtx );
5534
5535 if ( VOS_STATUS_SUCCESS != status )
5536 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005537 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5538 goto err_vosclose;
5539 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005540
5541 //Initialize the WMM module
5542 status = hdd_wmm_init(pHddCtx);
5543 if (!VOS_IS_STATUS_SUCCESS(status))
5544 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005545 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005546 goto err_vosclose;
5547 }
5548
Jeff Johnson295189b2012-06-20 16:38:30 -07005549 /* In the integrated architecture we update the configuration from
5550 the INI file and from NV before vOSS has been started so that
5551 the final contents are available to send down to the cCPU */
5552
5553 // Apply the cfg.ini to cfg.dat
5554 if (FALSE == hdd_update_config_dat(pHddCtx))
5555 {
5556 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5557 goto err_vosclose;
5558 }
5559
5560 // Apply the NV to cfg.dat
5561 /* Prima Update MAC address only at here */
5562 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5563 {
5564#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5565 /* There was not a valid set of MAC Addresses in NV. See if the
5566 default addresses were modified by the cfg.ini settings. If so,
5567 we'll use them, but if not, we'll autogenerate a set of MAC
5568 addresses based upon the device serial number */
5569
5570 static const v_MACADDR_t default_address =
5571 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5572 unsigned int serialno;
5573 int i;
5574
5575 serialno = wcnss_get_serial_number();
5576 if ((0 != serialno) &&
5577 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5578 sizeof(default_address))))
5579 {
5580 /* cfg.ini has the default address, invoke autogen logic */
5581
5582 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5583 bytes of the serial number that can be used to generate
5584 the other 3 bytes of the MAC address. Mask off all but
5585 the lower 3 bytes (this will also make sure we don't
5586 overflow in the next step) */
5587 serialno &= 0x00FFFFFF;
5588
5589 /* we need a unique address for each session */
5590 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5591
5592 /* autogen all addresses */
5593 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5594 {
5595 /* start with the entire default address */
5596 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5597 /* then replace the lower 3 bytes */
5598 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5599 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5600 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5601
5602 serialno++;
5603 }
5604
5605 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5606 MAC_ADDRESS_STR,
5607 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5608 }
5609 else
5610#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5611 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005612 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 "%s: Invalid MAC address in NV, using MAC from ini file "
5614 MAC_ADDRESS_STR, __func__,
5615 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5616 }
5617 }
5618 {
5619 eHalStatus halStatus;
5620 // Set the MAC Address
5621 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5622 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5623 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5624 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5625
5626 if (!HAL_STATUS_SUCCESS( halStatus ))
5627 {
5628 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5629 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005630 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005631 }
5632 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005633
5634 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5635 Note: Firmware image will be read and downloaded inside vos_start API */
5636 status = vos_start( pHddCtx->pvosContext );
5637 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5638 {
5639 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5640 goto err_vosclose;
5641 }
5642
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005643 /* Exchange capability info between Host and FW and also get versioning info from FW */
5644 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005645
5646 status = hdd_post_voss_start_config( pHddCtx );
5647 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5648 {
5649 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5650 __func__);
5651 goto err_vosstop;
5652 }
5653
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5655 {
5656 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5657 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5658 }
5659 else
5660 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5662 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5663 if (pAdapter != NULL)
5664 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305665 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005666 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305667 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5668 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5669 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005670
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305671 /* Generate the P2P Device Address. This consists of the device's
5672 * primary MAC address with the locally administered bit set.
5673 */
5674 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005675 }
5676 else
5677 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305678 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5679 if (p2p_dev_addr != NULL)
5680 {
5681 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5682 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5683 }
5684 else
5685 {
5686 hddLog(VOS_TRACE_LEVEL_FATAL,
5687 "%s: Failed to allocate mac_address for p2p_device",
5688 __func__);
5689 goto err_close_adapter;
5690 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005691 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005692
5693 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5694 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5695 if ( NULL == pP2pAdapter )
5696 {
5697 hddLog(VOS_TRACE_LEVEL_FATAL,
5698 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005699 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005700 goto err_close_adapter;
5701 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005704
5705 if( pAdapter == NULL )
5706 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005707 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5708 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005709 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005710
Jeff Johnson295189b2012-06-20 16:38:30 -07005711#ifdef WLAN_BTAMP_FEATURE
5712 vStatus = WLANBAP_Open(pVosContext);
5713 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5714 {
5715 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5716 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005717 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005718 }
5719
5720 vStatus = BSL_Init(pVosContext);
5721 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5722 {
5723 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5724 "%s: Failed to Init BSL",__func__);
5725 goto err_bap_close;
5726 }
5727 vStatus = WLANBAP_Start(pVosContext);
5728 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5729 {
5730 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5731 "%s: Failed to start TL",__func__);
5732 goto err_bap_close;
5733 }
5734
5735 pConfig = pHddCtx->cfg_ini;
5736 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5737 status = WLANBAP_SetConfig(&btAmpConfig);
5738
5739#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005740
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005741#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5742 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5743 {
5744 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5745 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5746 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5747 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5748 }
5749#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005750#ifdef FEATURE_WLAN_SCAN_PNO
5751 /*SME must send channel update configuration to RIVA*/
5752 sme_UpdateChannelConfig(pHddCtx->hHal);
5753#endif
5754
Jeff Johnson295189b2012-06-20 16:38:30 -07005755 /* Register with platform driver as client for Suspend/Resume */
5756 status = hddRegisterPmOps(pHddCtx);
5757 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5758 {
5759 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5760#ifdef WLAN_BTAMP_FEATURE
5761 goto err_bap_stop;
5762#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005763 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005764#endif //WLAN_BTAMP_FEATURE
5765 }
5766
Yue Ma0d4891e2013-08-06 17:01:45 -07005767 /* Open debugfs interface */
5768 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5769 {
5770 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5771 "%s: hdd_debugfs_init failed!", __func__);
5772 goto err_close_debugfs;
5773 }
5774
Jeff Johnson295189b2012-06-20 16:38:30 -07005775 /* Register TM level change handler function to the platform */
5776 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5777 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5778 {
5779 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5780 goto err_unregister_pmops;
5781 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005782
5783 /* register for riva power on lock to platform driver */
5784 if (req_riva_power_on_lock("wlan"))
5785 {
5786 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5787 __func__);
5788 goto err_unregister_pmops;
5789 }
5790
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 // register net device notifier for device change notification
5792 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5793
5794 if(ret < 0)
5795 {
5796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5797 goto err_free_power_on_lock;
5798 }
5799
5800 //Initialize the nlink service
5801 if(nl_srv_init() != 0)
5802 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305803 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 goto err_reg_netdev;
5805 }
5806
5807 //Initialize the BTC service
5808 if(btc_activate_service(pHddCtx) != 0)
5809 {
5810 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5811 goto err_nl_srv;
5812 }
5813
5814#ifdef PTT_SOCK_SVC_ENABLE
5815 //Initialize the PTT service
5816 if(ptt_sock_activate_svc(pHddCtx) != 0)
5817 {
5818 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5819 goto err_nl_srv;
5820 }
5821#endif
5822
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005825 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005826 /* Action frame registered in one adapter which will
5827 * applicable to all interfaces
5828 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005829 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005831
5832 mutex_init(&pHddCtx->sap_lock);
5833
5834 pHddCtx->isLoadUnloadInProgress = FALSE;
5835
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005836#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005837#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5838 /* Initialize the wake lcok */
5839 wake_lock_init(&pHddCtx->rx_wake_lock,
5840 WAKE_LOCK_SUSPEND,
5841 "qcom_rx_wakelock");
5842#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005843 /* Initialize the wake lcok */
5844 wake_lock_init(&pHddCtx->sap_wake_lock,
5845 WAKE_LOCK_SUSPEND,
5846 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005847#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005848
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005849 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5850 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005851
5852 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5853 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305854
Jeff Johnsone7245742012-09-05 17:12:55 -07005855 // Initialize the restart logic
5856 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305857
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305858 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5859 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5860 {
5861 hddLog(VOS_TRACE_LEVEL_ERROR,
5862 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5863 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005864 goto success;
5865
5866err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005867#ifdef WLAN_KD_READY_NOTIFIER
5868 nl_srv_exit(pHddCtx->ptt_pid);
5869#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005871#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005872err_reg_netdev:
5873 unregister_netdevice_notifier(&hdd_netdev_notifier);
5874
5875err_free_power_on_lock:
5876 free_riva_power_on_lock("wlan");
5877
5878err_unregister_pmops:
5879 hddDevTmUnregisterNotifyCallback(pHddCtx);
5880 hddDeregisterPmOps(pHddCtx);
5881
Yue Ma0d4891e2013-08-06 17:01:45 -07005882err_close_debugfs:
5883 hdd_debugfs_exit(pHddCtx);
5884
Jeff Johnson295189b2012-06-20 16:38:30 -07005885#ifdef WLAN_BTAMP_FEATURE
5886err_bap_stop:
5887 WLANBAP_Stop(pVosContext);
5888#endif
5889
5890#ifdef WLAN_BTAMP_FEATURE
5891err_bap_close:
5892 WLANBAP_Close(pVosContext);
5893#endif
5894
Jeff Johnson295189b2012-06-20 16:38:30 -07005895err_close_adapter:
5896 hdd_close_all_adapters( pHddCtx );
5897
5898err_vosstop:
5899 vos_stop(pVosContext);
5900
5901err_vosclose:
5902 status = vos_sched_close( pVosContext );
5903 if (!VOS_IS_STATUS_SUCCESS(status)) {
5904 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5905 "%s: Failed to close VOSS Scheduler", __func__);
5906 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5907 }
5908 vos_close(pVosContext );
5909
Jeff Johnson295189b2012-06-20 16:38:30 -07005910err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005911 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005912
5913err_wdclose:
5914 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5915 vos_watchdog_close(pVosContext);
5916
Jeff Johnson295189b2012-06-20 16:38:30 -07005917err_wiphy_reg:
5918 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005919
5920err_config:
5921 kfree(pHddCtx->cfg_ini);
5922 pHddCtx->cfg_ini= NULL;
5923
5924err_free_hdd_context:
5925 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 wiphy_free(wiphy) ;
5927 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 VOS_BUG(1);
5929
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005930 if (hdd_is_ssr_required())
5931 {
5932 /* WDI timeout had happened during load, so SSR is needed here */
5933 subsystem_restart("wcnss");
5934 msleep(5000);
5935 }
5936 hdd_set_ssr_required (VOS_FALSE);
5937
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005938 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005939
5940success:
5941 EXIT();
5942 return 0;
5943}
5944
5945/**---------------------------------------------------------------------------
5946
Jeff Johnson32d95a32012-09-10 13:15:23 -07005947 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005948
Jeff Johnson32d95a32012-09-10 13:15:23 -07005949 This is the driver entry point - called in different timeline depending
5950 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005951
5952 \param - None
5953
5954 \return - 0 for success, non zero for failure
5955
5956 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005957static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005958{
5959 VOS_STATUS status;
5960 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 struct device *dev = NULL;
5962 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005963#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5964 int max_retries = 0;
5965#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005966
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305967#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5968 vos_wconn_trace_init();
5969#endif
5970
Jeff Johnson295189b2012-06-20 16:38:30 -07005971 ENTER();
5972
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005973#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005975#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005976
5977 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5978 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5979
5980 //Power Up Libra WLAN card first if not already powered up
5981 status = vos_chipPowerUp(NULL,NULL,NULL);
5982 if (!VOS_IS_STATUS_SUCCESS(status))
5983 {
5984 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5985 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05305986#ifdef WLAN_OPEN_SOURCE
5987 wake_lock_destroy(&wlan_wake_lock);
5988#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005989 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005990 }
5991
Jeff Johnson295189b2012-06-20 16:38:30 -07005992#ifdef ANI_BUS_TYPE_PCI
5993
5994 dev = wcnss_wlan_get_device();
5995
5996#endif // ANI_BUS_TYPE_PCI
5997
5998#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005999
6000#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6001 /* wait until WCNSS driver downloads NV */
6002 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6003 msleep(1000);
6004 }
6005 if (max_retries >= 5) {
6006 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306007#ifdef WLAN_OPEN_SOURCE
6008 wake_lock_destroy(&wlan_wake_lock);
6009#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006010 return -ENODEV;
6011 }
6012#endif
6013
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 dev = wcnss_wlan_get_device();
6015#endif // ANI_BUS_TYPE_PLATFORM
6016
6017
6018 do {
6019 if (NULL == dev) {
6020 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6021 ret_status = -1;
6022 break;
6023 }
6024
6025#ifdef MEMORY_DEBUG
6026 vos_mem_init();
6027#endif
6028
6029#ifdef TIMER_MANAGER
6030 vos_timer_manager_init();
6031#endif
6032
6033 /* Preopen VOSS so that it is ready to start at least SAL */
6034 status = vos_preOpen(&pVosContext);
6035
6036 if (!VOS_IS_STATUS_SUCCESS(status))
6037 {
6038 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6039 ret_status = -1;
6040 break;
6041 }
6042
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006043#ifndef MODULE
6044 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6045 */
6046 hdd_set_conparam((v_UINT_t)con_mode);
6047#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006048
6049 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006050 if (hdd_wlan_startup(dev))
6051 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006052 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006053 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 vos_preClose( &pVosContext );
6055 ret_status = -1;
6056 break;
6057 }
6058
6059 /* Cancel the vote for XO Core ON
6060 * This is done here for safety purposes in case we re-initialize without turning
6061 * it OFF in any error scenario.
6062 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006063 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006064 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006065 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6067 {
6068 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6069 " Power consumed will be high\n");
6070 }
6071 } while (0);
6072
6073 if (0 != ret_status)
6074 {
6075 //Assert Deep sleep signal now to put Libra HW in lowest power state
6076 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6077 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6078
6079 //Vote off any PMIC voltage supplies
6080 vos_chipPowerDown(NULL, NULL, NULL);
6081#ifdef TIMER_MANAGER
6082 vos_timer_exit();
6083#endif
6084#ifdef MEMORY_DEBUG
6085 vos_mem_exit();
6086#endif
6087
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006088#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006090#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6092 }
6093 else
6094 {
6095 //Send WLAN UP indication to Nlink Service
6096 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6097
6098 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 }
6100
6101 EXIT();
6102
6103 return ret_status;
6104}
6105
Jeff Johnson32d95a32012-09-10 13:15:23 -07006106/**---------------------------------------------------------------------------
6107
6108 \brief hdd_module_init() - Init Function
6109
6110 This is the driver entry point (invoked when module is loaded using insmod)
6111
6112 \param - None
6113
6114 \return - 0 for success, non zero for failure
6115
6116 --------------------------------------------------------------------------*/
6117#ifdef MODULE
6118static int __init hdd_module_init ( void)
6119{
6120 return hdd_driver_init();
6121}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006122#else /* #ifdef MODULE */
6123static int __init hdd_module_init ( void)
6124{
6125 /* Driver initialization is delayed to fwpath_changed_handler */
6126 return 0;
6127}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006128#endif /* #ifdef MODULE */
6129
Jeff Johnson295189b2012-06-20 16:38:30 -07006130
6131/**---------------------------------------------------------------------------
6132
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006133 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006134
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006135 This is the driver exit point (invoked when module is unloaded using rmmod
6136 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006137
6138 \param - None
6139
6140 \return - None
6141
6142 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006143static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006144{
6145 hdd_context_t *pHddCtx = NULL;
6146 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006147 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006148
6149 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6150
6151 //Get the global vos context
6152 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6153
6154 if(!pVosContext)
6155 {
6156 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6157 goto done;
6158 }
6159
6160 //Get the HDD context.
6161 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6162
6163 if(!pHddCtx)
6164 {
6165 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6166 }
6167 else
6168 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006169 while(isWDresetInProgress()) {
6170 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6171 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006172 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006173
6174 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6176 "%s:SSR never completed, fatal error", __func__);
6177 VOS_BUG(0);
6178 }
6179 }
6180
Jeff Johnson295189b2012-06-20 16:38:30 -07006181
6182 pHddCtx->isLoadUnloadInProgress = TRUE;
6183 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6184
6185 //Do all the cleanup before deregistering the driver
6186 hdd_wlan_exit(pHddCtx);
6187 }
6188
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 vos_preClose( &pVosContext );
6190
6191#ifdef TIMER_MANAGER
6192 vos_timer_exit();
6193#endif
6194#ifdef MEMORY_DEBUG
6195 vos_mem_exit();
6196#endif
6197
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306198#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6199 vos_wconn_trace_exit();
6200#endif
6201
Jeff Johnson295189b2012-06-20 16:38:30 -07006202done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006203#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006204 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006205#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006206 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6207}
6208
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006209/**---------------------------------------------------------------------------
6210
6211 \brief hdd_module_exit() - Exit function
6212
6213 This is the driver exit point (invoked when module is unloaded using rmmod)
6214
6215 \param - None
6216
6217 \return - None
6218
6219 --------------------------------------------------------------------------*/
6220static void __exit hdd_module_exit(void)
6221{
6222 hdd_driver_exit();
6223}
6224
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006225#ifdef MODULE
6226static int fwpath_changed_handler(const char *kmessage,
6227 struct kernel_param *kp)
6228{
Jeff Johnson76052702013-04-16 13:55:05 -07006229 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006230}
6231
6232static int con_mode_handler(const char *kmessage,
6233 struct kernel_param *kp)
6234{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006235 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006236}
6237#else /* #ifdef MODULE */
6238/**---------------------------------------------------------------------------
6239
Jeff Johnson76052702013-04-16 13:55:05 -07006240 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006241
Jeff Johnson76052702013-04-16 13:55:05 -07006242 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006243 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006244 - invoked when module parameter fwpath is modified from userspace to signal
6245 initializing the WLAN driver or when con_mode is modified from userspace
6246 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006247
6248 \return - 0 for success, non zero for failure
6249
6250 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006251static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006252{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006253 int ret_status;
6254
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006255 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006256 ret_status = hdd_driver_init();
6257 wlan_hdd_inited = ret_status ? 0 : 1;
6258 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006259 }
6260
6261 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006262
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006263 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006264
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006265 ret_status = hdd_driver_init();
6266 wlan_hdd_inited = ret_status ? 0 : 1;
6267 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006268}
6269
Jeff Johnson295189b2012-06-20 16:38:30 -07006270/**---------------------------------------------------------------------------
6271
Jeff Johnson76052702013-04-16 13:55:05 -07006272 \brief fwpath_changed_handler() - Handler Function
6273
6274 Handle changes to the fwpath parameter
6275
6276 \return - 0 for success, non zero for failure
6277
6278 --------------------------------------------------------------------------*/
6279static int fwpath_changed_handler(const char *kmessage,
6280 struct kernel_param *kp)
6281{
6282 int ret;
6283
6284 ret = param_set_copystring(kmessage, kp);
6285 if (0 == ret)
6286 ret = kickstart_driver();
6287 return ret;
6288}
6289
6290/**---------------------------------------------------------------------------
6291
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006292 \brief con_mode_handler() -
6293
6294 Handler function for module param con_mode when it is changed by userspace
6295 Dynamically linked - do nothing
6296 Statically linked - exit and init driver, as in rmmod and insmod
6297
Jeff Johnson76052702013-04-16 13:55:05 -07006298 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006299
Jeff Johnson76052702013-04-16 13:55:05 -07006300 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006301
6302 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006303static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006304{
Jeff Johnson76052702013-04-16 13:55:05 -07006305 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006306
Jeff Johnson76052702013-04-16 13:55:05 -07006307 ret = param_set_int(kmessage, kp);
6308 if (0 == ret)
6309 ret = kickstart_driver();
6310 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006311}
6312#endif /* #ifdef MODULE */
6313
6314/**---------------------------------------------------------------------------
6315
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 \brief hdd_get_conparam() -
6317
6318 This is the driver exit point (invoked when module is unloaded using rmmod)
6319
6320 \param - None
6321
6322 \return - tVOS_CON_MODE
6323
6324 --------------------------------------------------------------------------*/
6325tVOS_CON_MODE hdd_get_conparam ( void )
6326{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006327#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006329#else
6330 return (tVOS_CON_MODE)curr_con_mode;
6331#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006332}
6333void hdd_set_conparam ( v_UINT_t newParam )
6334{
6335 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006336#ifndef MODULE
6337 curr_con_mode = con_mode;
6338#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006339}
6340/**---------------------------------------------------------------------------
6341
6342 \brief hdd_softap_sta_deauth() - function
6343
6344 This to take counter measure to handle deauth req from HDD
6345
6346 \param - pAdapter - Pointer to the HDD
6347
6348 \param - enable - boolean value
6349
6350 \return - None
6351
6352 --------------------------------------------------------------------------*/
6353
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006354VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006355{
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006357 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006358
6359 ENTER();
6360
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006361 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6362 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006363
6364 //Ignore request to deauth bcmc station
6365 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006366 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006367
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006368 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006369
6370 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006371 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006372}
6373
6374/**---------------------------------------------------------------------------
6375
6376 \brief hdd_softap_sta_disassoc() - function
6377
6378 This to take counter measure to handle deauth req from HDD
6379
6380 \param - pAdapter - Pointer to the HDD
6381
6382 \param - enable - boolean value
6383
6384 \return - None
6385
6386 --------------------------------------------------------------------------*/
6387
6388void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6389{
6390 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6391
6392 ENTER();
6393
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306394 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006395
6396 //Ignore request to disassoc bcmc station
6397 if( pDestMacAddress[0] & 0x1 )
6398 return;
6399
6400 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6401}
6402
6403void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6404{
6405 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6406
6407 ENTER();
6408
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306409 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006410
6411 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6412}
6413
Jeff Johnson295189b2012-06-20 16:38:30 -07006414/**---------------------------------------------------------------------------
6415 *
6416 * \brief hdd_get__concurrency_mode() -
6417 *
6418 *
6419 * \param - None
6420 *
6421 * \return - CONCURRENCY MODE
6422 *
6423 * --------------------------------------------------------------------------*/
6424tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6425{
6426 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6427 hdd_context_t *pHddCtx;
6428
6429 if (NULL != pVosContext)
6430 {
6431 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6432 if (NULL != pHddCtx)
6433 {
6434 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6435 }
6436 }
6437
6438 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006439 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006440 return VOS_STA;
6441}
6442
6443/* Decide whether to allow/not the apps power collapse.
6444 * Allow apps power collapse if we are in connected state.
6445 * if not, allow only if we are in IMPS */
6446v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6447{
6448 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006449 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006450 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6452 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6453 hdd_adapter_t *pAdapter = NULL;
6454 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006455 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006456
Jeff Johnson295189b2012-06-20 16:38:30 -07006457 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6458 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459
Yathish9f22e662012-12-10 14:21:35 -08006460 concurrent_state = hdd_get_concurrency_mode();
6461
6462#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6463 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6464 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6465 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6466 return TRUE;
6467#endif
6468
Jeff Johnson295189b2012-06-20 16:38:30 -07006469 /*loop through all adapters. TBD fix for Concurrency */
6470 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6471 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6472 {
6473 pAdapter = pAdapterNode->pAdapter;
6474 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6475 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6476 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006477 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006479 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006480 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6481 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006482 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006483 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006484 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6485 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 return FALSE;
6487 }
6488 }
6489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6490 pAdapterNode = pNext;
6491 }
6492 return TRUE;
6493}
6494
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006495/* Decides whether to send suspend notification to Riva
6496 * if any adapter is in BMPS; then it is required */
6497v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6498{
6499 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6500 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6501
6502 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6503 {
6504 return TRUE;
6505 }
6506 return FALSE;
6507}
6508
Jeff Johnson295189b2012-06-20 16:38:30 -07006509void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6510{
6511 switch(mode)
6512 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006513 case VOS_STA_MODE:
6514 case VOS_P2P_CLIENT_MODE:
6515 case VOS_P2P_GO_MODE:
6516 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006517 pHddCtx->concurrency_mode |= (1 << mode);
6518 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006519 break;
6520 default:
6521 break;
6522
6523 }
6524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6525 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6526}
6527
6528
6529void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6530{
6531 switch(mode)
6532 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006533 case VOS_STA_MODE:
6534 case VOS_P2P_CLIENT_MODE:
6535 case VOS_P2P_GO_MODE:
6536 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006537 pHddCtx->no_of_sessions[mode]--;
6538 if (!(pHddCtx->no_of_sessions[mode]))
6539 pHddCtx->concurrency_mode &= (~(1 << mode));
6540 break;
6541 default:
6542 break;
6543 }
6544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6545 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6546}
6547
Jeff Johnsone7245742012-09-05 17:12:55 -07006548/**---------------------------------------------------------------------------
6549 *
6550 * \brief wlan_hdd_restart_init
6551 *
6552 * This function initalizes restart timer/flag. An internal function.
6553 *
6554 * \param - pHddCtx
6555 *
6556 * \return - None
6557 *
6558 * --------------------------------------------------------------------------*/
6559
6560static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6561{
6562 /* Initialize */
6563 pHddCtx->hdd_restart_retries = 0;
6564 atomic_set(&pHddCtx->isRestartInProgress, 0);
6565 vos_timer_init(&pHddCtx->hdd_restart_timer,
6566 VOS_TIMER_TYPE_SW,
6567 wlan_hdd_restart_timer_cb,
6568 pHddCtx);
6569}
6570/**---------------------------------------------------------------------------
6571 *
6572 * \brief wlan_hdd_restart_deinit
6573 *
6574 * This function cleans up the resources used. An internal function.
6575 *
6576 * \param - pHddCtx
6577 *
6578 * \return - None
6579 *
6580 * --------------------------------------------------------------------------*/
6581
6582static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6583{
6584
6585 VOS_STATUS vos_status;
6586 /* Block any further calls */
6587 atomic_set(&pHddCtx->isRestartInProgress, 1);
6588 /* Cleanup */
6589 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6590 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006591 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006592 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6593 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006594 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006595
6596}
6597
6598/**---------------------------------------------------------------------------
6599 *
6600 * \brief wlan_hdd_framework_restart
6601 *
6602 * This function uses a cfg80211 API to start a framework initiated WLAN
6603 * driver module unload/load.
6604 *
6605 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6606 *
6607 *
6608 * \param - pHddCtx
6609 *
6610 * \return - VOS_STATUS_SUCCESS: Success
6611 * VOS_STATUS_E_EMPTY: Adapter is Empty
6612 * VOS_STATUS_E_NOMEM: No memory
6613
6614 * --------------------------------------------------------------------------*/
6615
6616static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6617{
6618 VOS_STATUS status = VOS_STATUS_SUCCESS;
6619 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006620 int len = (sizeof (struct ieee80211_mgmt));
6621 struct ieee80211_mgmt *mgmt = NULL;
6622
6623 /* Prepare the DEAUTH managment frame with reason code */
6624 mgmt = kzalloc(len, GFP_KERNEL);
6625 if(mgmt == NULL)
6626 {
6627 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6628 "%s: memory allocation failed (%d bytes)", __func__, len);
6629 return VOS_STATUS_E_NOMEM;
6630 }
6631 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006632
6633 /* Iterate over all adapters/devices */
6634 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6635 do
6636 {
6637 if( (status == VOS_STATUS_SUCCESS) &&
6638 pAdapterNode &&
6639 pAdapterNode->pAdapter)
6640 {
6641 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6642 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6643 pAdapterNode->pAdapter->dev->name,
6644 pAdapterNode->pAdapter->device_mode,
6645 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006646 /*
6647 * CFG80211 event to restart the driver
6648 *
6649 * 'cfg80211_send_unprot_deauth' sends a
6650 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6651 * of SME(Linux Kernel) state machine.
6652 *
6653 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6654 * the driver.
6655 *
6656 */
6657
6658 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006659 }
6660 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6661 pAdapterNode = pNext;
6662 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6663
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006664
6665 /* Free the allocated management frame */
6666 kfree(mgmt);
6667
Jeff Johnsone7245742012-09-05 17:12:55 -07006668 /* Retry until we unload or reach max count */
6669 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6670 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6671
6672 return status;
6673
6674}
6675/**---------------------------------------------------------------------------
6676 *
6677 * \brief wlan_hdd_restart_timer_cb
6678 *
6679 * Restart timer callback. An internal function.
6680 *
6681 * \param - User data:
6682 *
6683 * \return - None
6684 *
6685 * --------------------------------------------------------------------------*/
6686
6687void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6688{
6689 hdd_context_t *pHddCtx = usrDataForCallback;
6690 wlan_hdd_framework_restart(pHddCtx);
6691 return;
6692
6693}
6694
6695
6696/**---------------------------------------------------------------------------
6697 *
6698 * \brief wlan_hdd_restart_driver
6699 *
6700 * This function sends an event to supplicant to restart the WLAN driver.
6701 *
6702 * This function is called from vos_wlanRestart.
6703 *
6704 * \param - pHddCtx
6705 *
6706 * \return - VOS_STATUS_SUCCESS: Success
6707 * VOS_STATUS_E_EMPTY: Adapter is Empty
6708 * VOS_STATUS_E_ALREADY: Request already in progress
6709
6710 * --------------------------------------------------------------------------*/
6711VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6712{
6713 VOS_STATUS status = VOS_STATUS_SUCCESS;
6714
6715 /* A tight check to make sure reentrancy */
6716 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6717 {
6718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6719 "%s: WLAN restart is already in progress", __func__);
6720
6721 return VOS_STATUS_E_ALREADY;
6722 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006723 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006724#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006725 wcnss_reset_intr();
6726#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006727
Jeff Johnsone7245742012-09-05 17:12:55 -07006728 return status;
6729}
6730
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006731/*
6732 * API to find if there is any STA or P2P-Client is connected
6733 */
6734VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6735{
6736 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6737}
Jeff Johnsone7245742012-09-05 17:12:55 -07006738
Jeff Johnson295189b2012-06-20 16:38:30 -07006739//Register the module init/exit functions
6740module_init(hdd_module_init);
6741module_exit(hdd_module_exit);
6742
6743MODULE_LICENSE("Dual BSD/GPL");
6744MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6745MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6746
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006747module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6748 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006749
Jeff Johnson76052702013-04-16 13:55:05 -07006750module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006751 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);