blob: 9f565d4df04ad95a500c906b11d179cc10d050a8 [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
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(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 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
646 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
647 {
648 tANI_U8 *value = command;
649 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
650 tANI_U8 revision = 0;
651 eHalStatus status = eHAL_STATUS_SUCCESS;
652 v_REGDOMAIN_t regId;
653
654 status = hdd_parse_countryrev(value, countryCode, &revision);
655 if (eHAL_STATUS_SUCCESS != status)
656 {
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: Failed to parse country revision information", __func__);
659 ret = -EINVAL;
660 goto exit;
661 }
662
663 /* Validate country code */
664 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
665 if (eHAL_STATUS_SUCCESS != status)
666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
668 "%s: Invalid country code %s", __func__, countryCode);
669 ret = -EINVAL;
670 goto exit;
671 }
672
673 /* Validate revision */
674 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: Invalid revision %d", __func__, revision);
678 ret = -EINVAL;
679 goto exit;
680 }
681
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700682 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530683 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800684 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530685 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 if (0 != ret)
687 {
688 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
689 "%s: SME Change Country code fail ret=%d", __func__, ret);
690 ret = -EINVAL;
691 goto exit;
692 }
693
694 if (0 == strncmp(countryCode, "KR", 2))
695 {
696 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
697 revision);
698 if (eHAL_STATUS_SUCCESS != status)
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: Failed to build valid channel list", __func__);
702 ret = -EINVAL;
703 goto exit;
704 }
705 }
706 }
707#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700708 /*
709 command should be a string having format
710 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
711 */
Amar Singhal0974e402013-02-12 14:27:46 -0800712 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700713 {
Amar Singhal0974e402013-02-12 14:27:46 -0800714 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700717 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700718
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800719 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700720 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800721 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
722 {
723 int suspend = 0;
724 tANI_U8 *ptr = (tANI_U8*)command + 15;
725
726 suspend = *ptr - '0';
727 hdd_set_wlan_suspend_mode(suspend);
728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800729#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
730 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 *value = command;
733 int rssi = 0;
734 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
735 eHalStatus status = eHAL_STATUS_SUCCESS;
736
737 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
738 value = value + 15;
739
740 sscanf(value, "%d", &rssi);
741 lookUpThreshold = abs(rssi);
742 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
743 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
744 {
745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
746 "Neighbor lookup threshold value %d is out of range"
747 " (Min: %d Max: %d)", lookUpThreshold,
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
755 "%s: Received Command to Set Roam trigger"
756 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
757
758 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
759 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
760 if (eHAL_STATUS_SUCCESS != status)
761 {
762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
763 "%s: Failed to set roam trigger, try again", __func__);
764 ret = -EPERM;
765 goto exit;
766 }
767
768 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
769 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
770 }
771 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
772 {
773 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
774 int rssi = (-1) * lookUpThreshold;
775 char extra[32];
776 tANI_U8 len = 0;
777
778 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
779 if (copy_to_user(priv_data.buf, &extra, len + 1))
780 {
781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
782 "%s: failed to copy data to user buffer", __func__);
783 ret = -EFAULT;
784 goto exit;
785 }
786 }
787 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
788 {
789 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700790 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800791 /* input refresh period is in terms of seconds */
792 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
793 value = value + 18;
794 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700795 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800796 if (ret < 0)
797 {
798 /* If the input value is greater than max value of datatype, then also
799 kstrtou16 fails */
800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
801 "%s: kstrtou16 failed ",
802 "Input value may be out of range[%d - %d]",
803 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700804 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
805 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800806 ret = -EINVAL;
807 goto exit;
808 }
809
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700810 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
811 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
812 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800813 {
814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 "Neighbor empty scan results refresh period value %d is out of range"
816 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700817 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
818 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800819 ret = -EINVAL;
820 goto exit;
821 }
822
823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
824 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700825 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800826
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700827 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
828 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800829 }
830 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
831 {
832 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
833 char extra[32];
834 tANI_U8 len = 0;
835
836 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
837 /* Returned value is in units of seconds */
838 if (copy_to_user(priv_data.buf, &extra, len + 1))
839 {
840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
841 "%s: failed to copy data to user buffer", __func__);
842 ret = -EFAULT;
843 goto exit;
844 }
845 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
847 {
848 tANI_U8 *value = command;
849 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
850 /* input refresh period is in terms of seconds */
851 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
852 value = value + 25;
853 /* Convert the value from ascii to integer */
854 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
855 if (ret < 0)
856 {
857 /* If the input value is greater than max value of datatype, then also
858 kstrtou16 fails */
859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
860 "%s: kstrtou16 failed ",
861 "Input value may be out of range[%d - %d]",
862 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700863 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
864 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 ret = -EINVAL;
866 goto exit;
867 }
868
869 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700870 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
871 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700872 {
873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
874 "Neighbor scan results refresh period value %d is out of range"
875 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
876 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
877 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
878 ret = -EINVAL;
879 goto exit;
880 }
881
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
883 "%s: Received Command to Set roam scan refresh period"
884 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
885
886 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
887 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
888 }
889 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
890 {
891 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
892 char extra[32];
893 tANI_U8 len = 0;
894
895 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
896 /* Returned value is in units of seconds */
897 if (copy_to_user(priv_data.buf, &extra, len + 1))
898 {
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
900 "%s: failed to copy data to user buffer", __func__);
901 ret = -EFAULT;
902 goto exit;
903 }
904 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700905#ifdef FEATURE_WLAN_LFR
906 /* SETROAMMODE */
907 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
908 {
909 tANI_U8 *value = command;
910 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
911
912 /* Move pointer to ahead of SETROAMMODE<delimiter> */
913 value = value + SIZE_OF_SETROAMMODE + 1;
914
915 /* Convert the value from ascii to integer */
916 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
917 if (ret < 0)
918 {
919 /* If the input value is greater than max value of datatype, then also
920 kstrtou8 fails */
921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
922 "%s: kstrtou8 failed range [%d - %d]", __func__,
923 CFG_LFR_FEATURE_ENABLED_MIN,
924 CFG_LFR_FEATURE_ENABLED_MAX);
925 ret = -EINVAL;
926 goto exit;
927 }
928 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
929 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
930 {
931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
932 "Roam Mode value %d is out of range"
933 " (Min: %d Max: %d)", roamMode,
934 CFG_LFR_FEATURE_ENABLED_MIN,
935 CFG_LFR_FEATURE_ENABLED_MAX);
936 ret = -EINVAL;
937 goto exit;
938 }
939
940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
941 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
942 /*
943 * Note that
944 * SETROAMMODE 0 is to enable LFR while
945 * SETROAMMODE 1 is to disable LFR, but
946 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
947 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
948 */
949 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
950 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
951 else
952 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
953
954 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
955 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
956 }
957 /* GETROAMMODE */
958 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
959 {
960 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
961 char extra[32];
962 tANI_U8 len = 0;
963
964 /*
965 * roamMode value shall be inverted because the sementics is different.
966 */
967 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
968 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
969 else
970 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
971
972 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
973 if (copy_to_user(priv_data.buf, &extra, len + 1))
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: failed to copy data to user buffer", __func__);
977 ret = -EFAULT;
978 goto exit;
979 }
980 }
981#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800982#endif
983#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
984 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 *value = command;
987 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
988
989 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
990 value = value + 13;
991 /* Convert the value from ascii to integer */
992 ret = kstrtou8(value, 10, &roamRssiDiff);
993 if (ret < 0)
994 {
995 /* If the input value is greater than max value of datatype, then also
996 kstrtou8 fails */
997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
998 "%s: kstrtou8 failed range [%d - %d]", __func__,
999 CFG_ROAM_RSSI_DIFF_MIN,
1000 CFG_ROAM_RSSI_DIFF_MAX);
1001 ret = -EINVAL;
1002 goto exit;
1003 }
1004
1005 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1006 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1007 {
1008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1009 "Roam rssi diff value %d is out of range"
1010 " (Min: %d Max: %d)", roamRssiDiff,
1011 CFG_ROAM_RSSI_DIFF_MIN,
1012 CFG_ROAM_RSSI_DIFF_MAX);
1013 ret = -EINVAL;
1014 goto exit;
1015 }
1016
1017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1018 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1019
1020 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1021 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1022 }
1023 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1024 {
1025 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1026 char extra[32];
1027 tANI_U8 len = 0;
1028
1029 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1030 if (copy_to_user(priv_data.buf, &extra, len + 1))
1031 {
1032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: failed to copy data to user buffer", __func__);
1034 ret = -EFAULT;
1035 goto exit;
1036 }
1037 }
1038#endif
1039#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1040 else if (strncmp(command, "GETBAND", 7) == 0)
1041 {
1042 int band = -1;
1043 char extra[32];
1044 tANI_U8 len = 0;
1045 hdd_getBand_helper(pHddCtx, &band);
1046
1047 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1048 if (copy_to_user(priv_data.buf, &extra, len + 1))
1049 {
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: failed to copy data to user buffer", __func__);
1052 ret = -EFAULT;
1053 goto exit;
1054 }
1055 }
1056 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1057 {
1058 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1059 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1060 tANI_U8 revision = 0;
1061 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1062 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1063 char extra[32] = {0};
1064 tANI_U8 len = 0;
1065
1066 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1067 {
1068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1069 "%s: failed to get country code", __func__);
1070 ret = -EFAULT;
1071 goto exit;
1072 }
1073 pBuf[uBufLen] = '\0';
1074 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1075
1076 if (0 == strncmp(pBuf, "KR", 2))
1077 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1078 else
1079 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1080
1081 if (copy_to_user(priv_data.buf, &extra, len + 1))
1082 {
1083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: failed to copy data to user buffer", __func__);
1085 ret = -EFAULT;
1086 goto exit;
1087 }
1088 }
1089 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1090 {
1091 tANI_U8 *value = command;
1092 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1093 tANI_U8 numChannels = 0;
1094 eHalStatus status = eHAL_STATUS_SUCCESS;
1095
1096 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1097 if (eHAL_STATUS_SUCCESS != status)
1098 {
1099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Failed to parse channel list information", __func__);
1101 ret = -EINVAL;
1102 goto exit;
1103 }
1104
1105 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1106 {
1107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1108 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1109 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1110 ret = -EINVAL;
1111 goto exit;
1112 }
1113 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1114 numChannels);
1115 if (eHAL_STATUS_SUCCESS != status)
1116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1118 "%s: Failed to update channel list information", __func__);
1119 ret = -EINVAL;
1120 goto exit;
1121 }
1122 }
1123 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1124 {
1125 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1126 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001127 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001128 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001129 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001130
1131 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1132 ChannelList, &numChannels ))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1135 "%s: failed to get roam scan channel list", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 /* output channel list is of the format
1140 [Number of roam scan channels][Channel1][Channel2]... */
1141 /* copy the number of channels in the 0th index */
1142 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1143 for (j = 0; (j < numChannels); j++)
1144 {
1145 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1146 }
1147
1148 if (copy_to_user(priv_data.buf, &extra, len + 1))
1149 {
1150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1151 "%s: failed to copy data to user buffer", __func__);
1152 ret = -EFAULT;
1153 goto exit;
1154 }
1155 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001156 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1157 {
1158 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1159 char extra[32];
1160 tANI_U8 len = 0;
1161
1162 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1163 if (copy_to_user(priv_data.buf, &extra, len + 1))
1164 {
1165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1166 "%s: failed to copy data to user buffer", __func__);
1167 ret = -EFAULT;
1168 goto exit;
1169 }
1170 }
1171 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1172 {
1173 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1174 char extra[32];
1175 tANI_U8 len = 0;
1176
1177 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1178 if (copy_to_user(priv_data.buf, &extra, len + 1))
1179 {
1180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1181 "%s: failed to copy data to user buffer", __func__);
1182 ret = -EFAULT;
1183 goto exit;
1184 }
1185 }
1186 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1187 {
1188 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1189 char extra[32];
1190 tANI_U8 len = 0;
1191
1192 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1193 if (copy_to_user(priv_data.buf, &extra, len + 1))
1194 {
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: failed to copy data to user buffer", __func__);
1197 ret = -EFAULT;
1198 goto exit;
1199 }
1200 }
1201 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1202 {
1203 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1204 char extra[32];
1205 tANI_U8 len = 0;
1206
1207 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1208 if (copy_to_user(priv_data.buf, &extra, len + 1))
1209 {
1210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1211 "%s: failed to copy data to user buffer", __func__);
1212 ret = -EFAULT;
1213 goto exit;
1214 }
1215 }
1216 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1217 {
1218 tANI_U8 *value = command;
1219 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1220
1221 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1222 value = value + 26;
1223 /* Convert the value from ascii to integer */
1224 ret = kstrtou8(value, 10, &minTime);
1225 if (ret < 0)
1226 {
1227 /* If the input value is greater than max value of datatype, then also
1228 kstrtou8 fails */
1229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1230 "%s: kstrtou8 failed range [%d - %d]", __func__,
1231 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1232 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1233 ret = -EINVAL;
1234 goto exit;
1235 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001236 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1237 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1238 {
1239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1240 "scan min channel time value %d is out of range"
1241 " (Min: %d Max: %d)", minTime,
1242 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1243 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1244 ret = -EINVAL;
1245 goto exit;
1246 }
1247
1248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1249 "%s: Received Command to change channel min time = %d", __func__, minTime);
1250
1251 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1252 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1253 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001254 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1255 {
1256 tANI_U8 *value = command;
1257 tANI_U8 channel = 0;
1258 tANI_U8 dwellTime = 0;
1259 tANI_U8 bufLen = 0;
1260 tANI_U8 *buf = NULL;
1261 tSirMacAddr targetApBssid;
1262 eHalStatus status = eHAL_STATUS_SUCCESS;
1263 struct ieee80211_channel chan;
1264 tANI_U8 finalLen = 0;
1265 tANI_U8 *finalBuf = NULL;
1266 tANI_U8 temp = 0;
1267 u64 cookie;
1268 hdd_station_ctx_t *pHddStaCtx = NULL;
1269 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1270
1271 /* if not associated, no need to send action frame */
1272 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1273 {
1274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1275 ret = -EINVAL;
1276 goto exit;
1277 }
1278
1279 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1280 &dwellTime, &buf, &bufLen);
1281 if (eHAL_STATUS_SUCCESS != status)
1282 {
1283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1284 "%s: Failed to parse send action frame data", __func__);
1285 ret = -EINVAL;
1286 goto exit;
1287 }
1288
1289 /* if the target bssid is different from currently associated AP,
1290 then no need to send action frame */
1291 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1292 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1293 {
1294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1295 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001296 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 goto exit;
1298 }
1299
1300 /* if the channel number is different from operating channel then
1301 no need to send action frame */
1302 if (channel != pHddStaCtx->conn_info.operationChannel)
1303 {
1304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1305 "%s: channel(%d) is different from operating channel(%d)",
1306 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1307 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001308 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001309 goto exit;
1310 }
1311 chan.center_freq = sme_ChnToFreq(channel);
1312
1313 finalLen = bufLen + 24;
1314 finalBuf = vos_mem_malloc(finalLen);
1315 if (NULL == finalBuf)
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1318 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001319 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001320 goto exit;
1321 }
1322 vos_mem_zero(finalBuf, finalLen);
1323
1324 /* Fill subtype */
1325 temp = SIR_MAC_MGMT_ACTION << 4;
1326 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1327
1328 /* Fill type */
1329 temp = SIR_MAC_MGMT_FRAME;
1330 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1331
1332 /* Fill destination address (bssid of the AP) */
1333 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1334
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001335 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001336 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1337
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001338 /* Fill BSSID (AP mac address) */
1339 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340
1341 /* Fill received buffer from 24th address */
1342 vos_mem_copy(finalBuf + 24, buf, bufLen);
1343
Jeff Johnson11c33152013-04-16 17:52:40 -07001344 /* done with the parsed buffer */
1345 vos_mem_free(buf);
1346
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001347 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1348 1, dwellTime, finalBuf, finalLen, 1,
1349 1, &cookie );
1350 vos_mem_free(finalBuf);
1351 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001352 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1353 {
1354 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1355 char extra[32];
1356 tANI_U8 len = 0;
1357
1358 /* value is interms of msec */
1359 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1360 if (copy_to_user(priv_data.buf, &extra, len + 1))
1361 {
1362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1363 "%s: failed to copy data to user buffer", __func__);
1364 ret = -EFAULT;
1365 goto exit;
1366 }
1367 }
1368 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1369 {
1370 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001371 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001372 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001373
1374 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1375 value = value + 19;
1376 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001377 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001378 if (ret < 0)
1379 {
1380 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001381 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001383 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001384 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1385 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1386 ret = -EINVAL;
1387 goto exit;
1388 }
1389
1390 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1391 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1392 {
1393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1394 "lfr mode value %d is out of range"
1395 " (Min: %d Max: %d)", maxTime,
1396 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1397 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1398 ret = -EINVAL;
1399 goto exit;
1400 }
1401
1402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1403 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1404
1405 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001406
1407 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1408 * where RFS is the RF Switching time. It is twice RFS to consider the
1409 * time to go off channel and return to the home channel. */
1410 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1411 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1412 {
1413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1414 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1415 " Hence enforcing home away time to disable (0)",
1416 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1417 homeAwayTime = 0;
1418 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1419 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1420 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001421 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1422 }
1423 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1424 {
1425 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1426 char extra[32];
1427 tANI_U8 len = 0;
1428
1429 /* value is interms of msec */
1430 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1431 if (copy_to_user(priv_data.buf, &extra, len + 1))
1432 {
1433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1434 "%s: failed to copy data to user buffer", __func__);
1435 ret = -EFAULT;
1436 goto exit;
1437 }
1438 }
1439 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1440 {
1441 tANI_U8 *value = command;
1442 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1443
1444 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1445 value = value + 16;
1446 /* Convert the value from ascii to integer */
1447 ret = kstrtou16(value, 10, &val);
1448 if (ret < 0)
1449 {
1450 /* If the input value is greater than max value of datatype, then also
1451 kstrtou16 fails */
1452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1453 "%s: kstrtou16 failed range [%d - %d]", __func__,
1454 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1455 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1456 ret = -EINVAL;
1457 goto exit;
1458 }
1459
1460 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1461 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1462 {
1463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1464 "scan home time value %d is out of range"
1465 " (Min: %d Max: %d)", val,
1466 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1467 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1468 ret = -EINVAL;
1469 goto exit;
1470 }
1471
1472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1473 "%s: Received Command to change scan home time = %d", __func__, val);
1474
1475 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1476 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1477 }
1478 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1479 {
1480 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1481 char extra[32];
1482 tANI_U8 len = 0;
1483
1484 /* value is interms of msec */
1485 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1486 if (copy_to_user(priv_data.buf, &extra, len + 1))
1487 {
1488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1489 "%s: failed to copy data to user buffer", __func__);
1490 ret = -EFAULT;
1491 goto exit;
1492 }
1493 }
1494 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1495 {
1496 tANI_U8 *value = command;
1497 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1498
1499 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1500 value = value + 17;
1501 /* Convert the value from ascii to integer */
1502 ret = kstrtou8(value, 10, &val);
1503 if (ret < 0)
1504 {
1505 /* If the input value is greater than max value of datatype, then also
1506 kstrtou8 fails */
1507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1508 "%s: kstrtou8 failed range [%d - %d]", __func__,
1509 CFG_ROAM_INTRA_BAND_MIN,
1510 CFG_ROAM_INTRA_BAND_MAX);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514
1515 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1516 (val > CFG_ROAM_INTRA_BAND_MAX))
1517 {
1518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1519 "intra band mode value %d is out of range"
1520 " (Min: %d Max: %d)", val,
1521 CFG_ROAM_INTRA_BAND_MIN,
1522 CFG_ROAM_INTRA_BAND_MAX);
1523 ret = -EINVAL;
1524 goto exit;
1525 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1527 "%s: Received Command to change intra band = %d", __func__, val);
1528
1529 pHddCtx->cfg_ini->nRoamIntraBand = val;
1530 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1531 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001532 else if (strncmp(command, "SETWESMODE", 10) == 0)
1533 {
1534 tANI_U8 *value = command;
1535 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1536
1537 /* Move pointer to ahead of SETWESMODE<delimiter> */
1538 value = value + 11;
1539 /* Convert the value from ascii to integer */
1540 ret = kstrtou8(value, 10, &wesMode);
1541 if (ret < 0)
1542 {
1543 /* If the input value is greater than max value of datatype, then also
1544 kstrtou8 fails */
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "%s: kstrtou8 failed range [%d - %d]", __func__,
1547 CFG_ENABLE_WES_MODE_NAME_MIN,
1548 CFG_ENABLE_WES_MODE_NAME_MAX);
1549 ret = -EINVAL;
1550 goto exit;
1551 }
1552
1553 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1554 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1555 {
1556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "WES Mode value %d is out of range"
1558 " (Min: %d Max: %d)", wesMode,
1559 CFG_ENABLE_WES_MODE_NAME_MIN,
1560 CFG_ENABLE_WES_MODE_NAME_MAX);
1561 ret = -EINVAL;
1562 goto exit;
1563 }
1564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1565 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1566
1567 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1568 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1569 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001570 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1571 {
1572 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1573 char extra[32];
1574 tANI_U8 len = 0;
1575
1576 /* value is interms of msec */
1577 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1578 if (copy_to_user(priv_data.buf, &extra, len + 1))
1579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: failed to copy data to user buffer", __func__);
1582 ret = -EFAULT;
1583 goto exit;
1584 }
1585 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001586 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1587 {
1588 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1589 char extra[32];
1590 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001591
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001592 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1593 if (copy_to_user(priv_data.buf, &extra, len + 1))
1594 {
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1596 "%s: failed to copy data to user buffer", __func__);
1597 ret = -EFAULT;
1598 goto exit;
1599 }
1600 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001601 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1602 {
1603 tANI_U8 *value = command;
1604 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1605
1606 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1607 value = value + 15;
1608 /* Convert the value from ascii to integer */
1609 ret = kstrtou8(value, 10, &nProbes);
1610 if (ret < 0)
1611 {
1612 /* If the input value is greater than max value of datatype, then also
1613 kstrtou8 fails */
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1615 "%s: kstrtou8 failed range [%d - %d]", __func__,
1616 CFG_ROAM_SCAN_N_PROBES_MIN,
1617 CFG_ROAM_SCAN_N_PROBES_MAX);
1618 ret = -EINVAL;
1619 goto exit;
1620 }
1621
1622 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1623 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1626 "NProbes value %d is out of range"
1627 " (Min: %d Max: %d)", nProbes,
1628 CFG_ROAM_SCAN_N_PROBES_MIN,
1629 CFG_ROAM_SCAN_N_PROBES_MAX);
1630 ret = -EINVAL;
1631 goto exit;
1632 }
1633
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1635 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1636
1637 pHddCtx->cfg_ini->nProbes = nProbes;
1638 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1639 }
1640 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1641 {
1642 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1643 char extra[32];
1644 tANI_U8 len = 0;
1645
1646 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1647 if (copy_to_user(priv_data.buf, &extra, len + 1))
1648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "%s: failed to copy data to user buffer", __func__);
1651 ret = -EFAULT;
1652 goto exit;
1653 }
1654 }
1655 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1656 {
1657 tANI_U8 *value = command;
1658 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001659 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001660
1661 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1662 /* input value is in units of msec */
1663 value = value + 20;
1664 /* Convert the value from ascii to integer */
1665 ret = kstrtou16(value, 10, &homeAwayTime);
1666 if (ret < 0)
1667 {
1668 /* If the input value is greater than max value of datatype, then also
1669 kstrtou8 fails */
1670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1671 "%s: kstrtou8 failed range [%d - %d]", __func__,
1672 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1673 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001678 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1679 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1680 {
1681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1682 "homeAwayTime value %d is out of range"
1683 " (Min: %d Max: %d)", homeAwayTime,
1684 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1686 ret = -EINVAL;
1687 goto exit;
1688 }
1689
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1691 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1692
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001693 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1694 * where RFS is the RF Switching time. It is twice RFS to consider the
1695 * time to go off channel and return to the home channel. */
1696 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1697 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1698 {
1699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1700 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1701 " Hence enforcing home away time to disable (0)",
1702 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1703 homeAwayTime = 0;
1704 }
1705
1706 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1707 {
1708 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1709 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1710 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001711 }
1712 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1713 {
1714 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1715 char extra[32];
1716 tANI_U8 len = 0;
1717
1718 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1719 if (copy_to_user(priv_data.buf, &extra, len + 1))
1720 {
1721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1722 "%s: failed to copy data to user buffer", __func__);
1723 ret = -EFAULT;
1724 goto exit;
1725 }
1726 }
1727 else if (strncmp(command, "REASSOC", 7) == 0)
1728 {
1729 tANI_U8 *value = command;
1730 tANI_U8 channel = 0;
1731 tSirMacAddr targetApBssid;
1732 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001733#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1734 tCsrHandoffRequest handoffInfo;
1735#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001736 hdd_station_ctx_t *pHddStaCtx = NULL;
1737 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1738 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1739
1740 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1741
1742 /* Reassoc command is allowed only if WES mode is enabled */
1743 if (!wesMode)
1744 {
1745 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1746 ret = -EINVAL;
1747 goto exit;
1748 }
1749
1750 /* if not associated, no need to proceed with reassoc */
1751 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1752 {
1753 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1754 ret = -EINVAL;
1755 goto exit;
1756 }
1757
1758 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1759 if (eHAL_STATUS_SUCCESS != status)
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "%s: Failed to parse reassoc command data", __func__);
1763 ret = -EINVAL;
1764 goto exit;
1765 }
1766
1767 /* if the target bssid is same as currently associated AP,
1768 then no need to proceed with reassoc */
1769 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1770 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1771 {
1772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1773 ret = -EINVAL;
1774 goto exit;
1775 }
1776
1777 /* Check channel number is a valid channel number */
1778 if(VOS_STATUS_SUCCESS !=
1779 wlan_hdd_validate_operation_channel(pAdapter, channel))
1780 {
1781 hddLog(VOS_TRACE_LEVEL_ERROR,
1782 "%s: Invalid Channel [%d] \n", __func__, channel);
1783 return -EINVAL;
1784 }
1785
1786 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001787#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1788 handoffInfo.channel = channel;
1789 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1790 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1791#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001792 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001793#endif
1794#ifdef FEATURE_WLAN_LFR
1795 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1796 {
1797 tANI_U8 *value = command;
1798 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1799
1800 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1801 value = value + 12;
1802 /* Convert the value from ascii to integer */
1803 ret = kstrtou8(value, 10, &lfrMode);
1804 if (ret < 0)
1805 {
1806 /* If the input value is greater than max value of datatype, then also
1807 kstrtou8 fails */
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "%s: kstrtou8 failed range [%d - %d]", __func__,
1810 CFG_LFR_FEATURE_ENABLED_MIN,
1811 CFG_LFR_FEATURE_ENABLED_MAX);
1812 ret = -EINVAL;
1813 goto exit;
1814 }
1815
1816 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1817 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "lfr mode value %d is out of range"
1821 " (Min: %d Max: %d)", lfrMode,
1822 CFG_LFR_FEATURE_ENABLED_MIN,
1823 CFG_LFR_FEATURE_ENABLED_MAX);
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1829 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1830
1831 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1832 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1833 }
1834#endif
1835#ifdef WLAN_FEATURE_VOWIFI_11R
1836 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1837 {
1838 tANI_U8 *value = command;
1839 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1840
1841 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1842 value = value + 18;
1843 /* Convert the value from ascii to integer */
1844 ret = kstrtou8(value, 10, &ft);
1845 if (ret < 0)
1846 {
1847 /* If the input value is greater than max value of datatype, then also
1848 kstrtou8 fails */
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: kstrtou8 failed range [%d - %d]", __func__,
1851 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1852 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1853 ret = -EINVAL;
1854 goto exit;
1855 }
1856
1857 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1858 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1859 {
1860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1861 "ft mode value %d is out of range"
1862 " (Min: %d Max: %d)", ft,
1863 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1864 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1865 ret = -EINVAL;
1866 goto exit;
1867 }
1868
1869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1870 "%s: Received Command to change ft mode = %d", __func__, ft);
1871
1872 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1873 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1874 }
1875#endif
1876#ifdef FEATURE_WLAN_CCX
1877 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1878 {
1879 tANI_U8 *value = command;
1880 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1881
1882 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1883 value = value + 11;
1884 /* Convert the value from ascii to integer */
1885 ret = kstrtou8(value, 10, &ccxMode);
1886 if (ret < 0)
1887 {
1888 /* If the input value is greater than max value of datatype, then also
1889 kstrtou8 fails */
1890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1891 "%s: kstrtou8 failed range [%d - %d]", __func__,
1892 CFG_CCX_FEATURE_ENABLED_MIN,
1893 CFG_CCX_FEATURE_ENABLED_MAX);
1894 ret = -EINVAL;
1895 goto exit;
1896 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001897 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1898 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1899 {
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1901 "Ccx mode value %d is out of range"
1902 " (Min: %d Max: %d)", ccxMode,
1903 CFG_CCX_FEATURE_ENABLED_MIN,
1904 CFG_CCX_FEATURE_ENABLED_MAX);
1905 ret = -EINVAL;
1906 goto exit;
1907 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1909 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1910
1911 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1912 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1913 }
1914#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001915 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1916 {
1917 tANI_U8 *value = command;
1918 tANI_BOOLEAN roamScanControl = 0;
1919
1920 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1921 value = value + 19;
1922 /* Convert the value from ascii to integer */
1923 ret = kstrtou8(value, 10, &roamScanControl);
1924 if (ret < 0)
1925 {
1926 /* If the input value is greater than max value of datatype, then also
1927 kstrtou8 fails */
1928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "%s: kstrtou8 failed ", __func__);
1930 ret = -EINVAL;
1931 goto exit;
1932 }
1933
1934 if (0 != roamScanControl)
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "roam scan control invalid value = %d",
1938 roamScanControl);
1939 ret = -EINVAL;
1940 goto exit;
1941 }
1942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1943 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1944
1945 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1946 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001947#ifdef FEATURE_WLAN_OKC
1948 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1949 {
1950 tANI_U8 *value = command;
1951 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1952
1953 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1954 value = value + 11;
1955 /* Convert the value from ascii to integer */
1956 ret = kstrtou8(value, 10, &okcMode);
1957 if (ret < 0)
1958 {
1959 /* If the input value is greater than max value of datatype, then also
1960 kstrtou8 fails */
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1962 "%s: kstrtou8 failed range [%d - %d]", __func__,
1963 CFG_OKC_FEATURE_ENABLED_MIN,
1964 CFG_OKC_FEATURE_ENABLED_MAX);
1965 ret = -EINVAL;
1966 goto exit;
1967 }
1968
1969 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1970 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1971 {
1972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1973 "Okc mode value %d is out of range"
1974 " (Min: %d Max: %d)", okcMode,
1975 CFG_OKC_FEATURE_ENABLED_MIN,
1976 CFG_OKC_FEATURE_ENABLED_MAX);
1977 ret = -EINVAL;
1978 goto exit;
1979 }
1980
1981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1982 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1983
1984 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1985 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001986 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1987 {
1988 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1989 char extra[32];
1990 tANI_U8 len = 0;
1991
1992 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1993 if (copy_to_user(priv_data.buf, &extra, len + 1))
1994 {
1995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1996 "%s: failed to copy data to user buffer", __func__);
1997 ret = -EFAULT;
1998 goto exit;
1999 }
2000 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002001#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002002 else {
2003 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2004 __func__, command);
2005 }
2006
Jeff Johnson295189b2012-06-20 16:38:30 -07002007 }
2008exit:
2009 if (command)
2010 {
2011 kfree(command);
2012 }
2013 return ret;
2014}
2015
Srinivas Girigowdade697412013-02-14 16:31:48 -08002016#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2017void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2018{
2019 eCsrBand band = -1;
2020 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2021 switch (band)
2022 {
2023 case eCSR_BAND_ALL:
2024 *pBand = WLAN_HDD_UI_BAND_AUTO;
2025 break;
2026
2027 case eCSR_BAND_24:
2028 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2029 break;
2030
2031 case eCSR_BAND_5G:
2032 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2033 break;
2034
2035 default:
2036 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2037 *pBand = -1;
2038 break;
2039 }
2040}
2041
2042/**---------------------------------------------------------------------------
2043
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002044 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2045
2046 This function parses the send action frame data passed in the format
2047 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2048
2049 \param - pValue Pointer to input country code revision
2050 \param - pTargetApBssid Pointer to target Ap bssid
2051 \param - pChannel Pointer to the Target AP channel
2052 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2053 \param - pBuf Pointer to data
2054 \param - pBufLen Pointer to data length
2055
2056 \return - 0 for success non-zero for failure
2057
2058 --------------------------------------------------------------------------*/
2059VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2060 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2061{
2062 tANI_U8 *inPtr = pValue;
2063 tANI_U8 *dataEnd;
2064 int tempInt;
2065 int j = 0;
2066 int i = 0;
2067 int v = 0;
2068 tANI_U8 tempBuf[32];
2069 tANI_U8 tempByte = 0;
2070
2071 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2072 /*no argument after the command*/
2073 if (NULL == inPtr)
2074 {
2075 return -EINVAL;
2076 }
2077
2078 /*no space after the command*/
2079 else if (SPACE_ASCII_VALUE != *inPtr)
2080 {
2081 return -EINVAL;
2082 }
2083
2084 /*removing empty spaces*/
2085 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2086
2087 /*no argument followed by spaces*/
2088 if ('\0' == *inPtr)
2089 {
2090 return -EINVAL;
2091 }
2092
2093 /*getting the first argument ie the target AP bssid */
2094 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2095 {
2096 return -EINVAL;
2097 }
2098 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2099 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2100 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2101
2102 /* point to the next argument */
2103 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2104 /*no argument after the command*/
2105 if (NULL == inPtr) return -EINVAL;
2106
2107 /*removing empty spaces*/
2108 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2109
2110 /*no argument followed by spaces*/
2111 if ('\0' == *inPtr)
2112 {
2113 return -EINVAL;
2114 }
2115
2116 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002117 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002118 v = kstrtos32(tempBuf, 10, &tempInt);
2119 if ( v < 0) return -EINVAL;
2120
2121 *pChannel = tempInt;
2122
2123 /* point to the next argument */
2124 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2125 /*no argument after the command*/
2126 if (NULL == inPtr) return -EINVAL;
2127 /*removing empty spaces*/
2128 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2129
2130 /*no argument followed by spaces*/
2131 if ('\0' == *inPtr)
2132 {
2133 return -EINVAL;
2134 }
2135
2136 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002137 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002138 v = kstrtos32(tempBuf, 10, &tempInt);
2139 if ( v < 0) return -EINVAL;
2140
2141 *pDwellTime = tempInt;
2142
2143 /* point to the next argument */
2144 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2145 /*no argument after the command*/
2146 if (NULL == inPtr) return -EINVAL;
2147 /*removing empty spaces*/
2148 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2149
2150 /*no argument followed by spaces*/
2151 if ('\0' == *inPtr)
2152 {
2153 return -EINVAL;
2154 }
2155
2156 /* find the length of data */
2157 dataEnd = inPtr;
2158 while(('\0' != *dataEnd) )
2159 {
2160 dataEnd++;
2161 ++(*pBufLen);
2162 }
2163 if ( *pBufLen <= 0) return -EINVAL;
2164
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002165 /* Allocate the number of bytes based on the number of input characters
2166 whether it is even or odd.
2167 if the number of input characters are even, then we need N/2 byte.
2168 if the number of input characters are odd, then we need do (N+1)/2 to
2169 compensate rounding off.
2170 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2171 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2172 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002173 if (NULL == *pBuf)
2174 {
2175 hddLog(VOS_TRACE_LEVEL_FATAL,
2176 "%s: vos_mem_alloc failed ", __func__);
2177 return -EINVAL;
2178 }
2179
2180 /* the buffer received from the upper layer is character buffer,
2181 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2182 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2183 and f0 in 3rd location */
2184 for (i = 0, j = 0; j < *pBufLen; j += 2)
2185 {
2186 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2187 (*pBuf)[i++] = tempByte;
2188 }
2189 *pBufLen = i;
2190 return VOS_STATUS_SUCCESS;
2191}
2192
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002193/**---------------------------------------------------------------------------
2194
Srinivas Girigowdade697412013-02-14 16:31:48 -08002195 \brief hdd_parse_countryrev() - HDD Parse country code revision
2196
2197 This function parses the country code revision passed in the format
2198 SETCOUNTRYREV<space><Country code><space>revision
2199
2200 \param - pValue Pointer to input country code revision
2201 \param - pCountryCode Pointer to local output array to record country code
2202 \param - pRevision Pointer to store revision integer number
2203
2204 \return - 0 for success non-zero for failure
2205
2206 --------------------------------------------------------------------------*/
2207VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2208{
2209 tANI_U8 *inPtr = pValue;
2210 int tempInt;
2211
2212 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2213 /*no argument after the command*/
2214 if (NULL == inPtr)
2215 {
2216 return -EINVAL;
2217 }
2218
2219 /*no space after the command*/
2220 else if (SPACE_ASCII_VALUE != *inPtr)
2221 {
2222 return -EINVAL;
2223 }
2224
2225 /*removing empty spaces*/
2226 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2227
2228 /*no argument followed by spaces*/
2229 if ('\0' == *inPtr)
2230 {
2231 return -EINVAL;
2232 }
2233
2234 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002235 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002236
2237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2238 "Country code is : %s", pCountryCode);
2239
2240 /*inPtr pointing to the beginning of first space after country code */
2241 inPtr = strpbrk( inPtr, " " );
2242 /*no revision number after the country code argument */
2243 if (NULL == inPtr)
2244 {
2245 return -EINVAL;
2246 }
2247
2248 inPtr++;
2249
2250 /*removing empty space*/
2251 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2252
2253 /*no channel list after the number of channels argument and spaces*/
2254 if (0 == strncmp(pCountryCode, "KR", 2))
2255 {
2256 if ('\0' == *inPtr)
2257 {
2258 return -EINVAL;
2259 }
2260
2261 sscanf(inPtr, "%d", &tempInt);
2262 *pRevision = tempInt;
2263 }
2264 else
2265 {
2266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2267 "Revision input is required only for Country KR");
2268 return -EINVAL;
2269 }
2270 return VOS_STATUS_SUCCESS;
2271}
2272
2273/**---------------------------------------------------------------------------
2274
2275 \brief hdd_parse_channellist() - HDD Parse channel list
2276
2277 This function parses the channel list passed in the format
2278 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002279 if the Number of channels (N) does not match with the actual number of channels passed
2280 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2281 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2282 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2283 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002284
2285 \param - pValue Pointer to input channel list
2286 \param - ChannelList Pointer to local output array to record channel list
2287 \param - pNumChannels Pointer to number of roam scan channels
2288
2289 \return - 0 for success non-zero for failure
2290
2291 --------------------------------------------------------------------------*/
2292VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2293{
2294 tANI_U8 *inPtr = pValue;
2295 int tempInt;
2296 int j = 0;
2297 int v = 0;
2298 char buf[32];
2299
2300 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2301 /*no argument after the command*/
2302 if (NULL == inPtr)
2303 {
2304 return -EINVAL;
2305 }
2306
2307 /*no space after the command*/
2308 else if (SPACE_ASCII_VALUE != *inPtr)
2309 {
2310 return -EINVAL;
2311 }
2312
2313 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002314 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002315
2316 /*no argument followed by spaces*/
2317 if ('\0' == *inPtr)
2318 {
2319 return -EINVAL;
2320 }
2321
2322 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002323 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002324 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002325 if ((v < 0) ||
2326 (tempInt <= 0) ||
2327 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2328 {
2329 return -EINVAL;
2330 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002331
2332 *pNumChannels = tempInt;
2333
2334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2335 "Number of channels are: %d", *pNumChannels);
2336
2337 for (j = 0; j < (*pNumChannels); j++)
2338 {
2339 /*inPtr pointing to the beginning of first space after number of channels*/
2340 inPtr = strpbrk( inPtr, " " );
2341 /*no channel list after the number of channels argument*/
2342 if (NULL == inPtr)
2343 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002344 if (0 != j)
2345 {
2346 *pNumChannels = j;
2347 return VOS_STATUS_SUCCESS;
2348 }
2349 else
2350 {
2351 return -EINVAL;
2352 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002353 }
2354
2355 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002356 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002357
2358 /*no channel list after the number of channels argument and spaces*/
2359 if ( '\0' == *inPtr )
2360 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002361 if (0 != j)
2362 {
2363 *pNumChannels = j;
2364 return VOS_STATUS_SUCCESS;
2365 }
2366 else
2367 {
2368 return -EINVAL;
2369 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 }
2371
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002372 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002373 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002374 if ((v < 0) ||
2375 (tempInt <= 0) ||
2376 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2377 {
2378 return -EINVAL;
2379 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002380 pChannelList[j] = tempInt;
2381
2382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2383 "Channel %d added to preferred channel list",
2384 pChannelList[j] );
2385 }
2386
Srinivas Girigowdade697412013-02-14 16:31:48 -08002387 return VOS_STATUS_SUCCESS;
2388}
2389
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002390
2391/**---------------------------------------------------------------------------
2392
2393 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2394
2395 This function parses the reasoc command data passed in the format
2396 REASSOC<space><bssid><space><channel>
2397
2398 \param - pValue Pointer to input country code revision
2399 \param - pTargetApBssid Pointer to target Ap bssid
2400 \param - pChannel Pointer to the Target AP channel
2401
2402 \return - 0 for success non-zero for failure
2403
2404 --------------------------------------------------------------------------*/
2405VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2406{
2407 tANI_U8 *inPtr = pValue;
2408 int tempInt;
2409 int v = 0;
2410 tANI_U8 tempBuf[32];
2411
2412 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2413 /*no argument after the command*/
2414 if (NULL == inPtr)
2415 {
2416 return -EINVAL;
2417 }
2418
2419 /*no space after the command*/
2420 else if (SPACE_ASCII_VALUE != *inPtr)
2421 {
2422 return -EINVAL;
2423 }
2424
2425 /*removing empty spaces*/
2426 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2427
2428 /*no argument followed by spaces*/
2429 if ('\0' == *inPtr)
2430 {
2431 return -EINVAL;
2432 }
2433
2434 /*getting the first argument ie the target AP bssid */
2435 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2436 {
2437 return -EINVAL;
2438 }
2439 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2440 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2441 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2442
2443 /* point to the next argument */
2444 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2445 /*no argument after the command*/
2446 if (NULL == inPtr) return -EINVAL;
2447
2448 /*removing empty spaces*/
2449 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2450
2451 /*no argument followed by spaces*/
2452 if ('\0' == *inPtr)
2453 {
2454 return -EINVAL;
2455 }
2456
2457 /*getting the next argument ie the channel number */
2458 sscanf(inPtr, "%s ", tempBuf);
2459 v = kstrtos32(tempBuf, 10, &tempInt);
2460 if ( v < 0) return -EINVAL;
2461
2462 *pChannel = tempInt;
2463 return VOS_STATUS_SUCCESS;
2464}
2465
2466#endif
2467
Jeff Johnson295189b2012-06-20 16:38:30 -07002468/**---------------------------------------------------------------------------
2469
2470 \brief hdd_open() - HDD Open function
2471
2472 This is called in response to ifconfig up
2473
2474 \param - dev Pointer to net_device structure
2475
2476 \return - 0 for success non-zero for failure
2477
2478 --------------------------------------------------------------------------*/
2479int hdd_open (struct net_device *dev)
2480{
2481 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2482 hdd_context_t *pHddCtx;
2483 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2484 VOS_STATUS status;
2485 v_BOOL_t in_standby = TRUE;
2486
2487 if (NULL == pAdapter)
2488 {
2489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002490 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 return -ENODEV;
2492 }
2493
2494 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2495 if (NULL == pHddCtx)
2496 {
2497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002498 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002499 return -ENODEV;
2500 }
2501
2502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2503 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2504 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002505 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2506 {
2507 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302508 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002509 in_standby = FALSE;
2510 break;
2511 }
2512 else
2513 {
2514 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2515 pAdapterNode = pNext;
2516 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002517 }
2518
2519 if (TRUE == in_standby)
2520 {
2521 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2522 {
2523 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2524 "wlan out of power save", __func__);
2525 return -EINVAL;
2526 }
2527 }
2528
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002529 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002530 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2531 {
2532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002533 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002534 /* Enable TX queues only when we are connected */
2535 netif_tx_start_all_queues(dev);
2536 }
2537
2538 return 0;
2539}
2540
2541int hdd_mon_open (struct net_device *dev)
2542{
2543 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2544
2545 if(pAdapter == NULL) {
2546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002547 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002548 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 }
2550
2551 netif_start_queue(dev);
2552
2553 return 0;
2554}
2555/**---------------------------------------------------------------------------
2556
2557 \brief hdd_stop() - HDD stop function
2558
2559 This is called in response to ifconfig down
2560
2561 \param - dev Pointer to net_device structure
2562
2563 \return - 0 for success non-zero for failure
2564
2565 --------------------------------------------------------------------------*/
2566
2567int hdd_stop (struct net_device *dev)
2568{
2569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2570 hdd_context_t *pHddCtx;
2571 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2572 VOS_STATUS status;
2573 v_BOOL_t enter_standby = TRUE;
2574
2575 ENTER();
2576
2577 if (NULL == pAdapter)
2578 {
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002580 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002581 return -ENODEV;
2582 }
2583
2584 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2585 if (NULL == pHddCtx)
2586 {
2587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002588 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002589 return -ENODEV;
2590 }
2591
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002592 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002593 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2594 netif_tx_disable(pAdapter->dev);
2595 netif_carrier_off(pAdapter->dev);
2596
2597
2598 /* SoftAP ifaces should never go in power save mode
2599 making sure same here. */
2600 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2601 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 )
2604 {
2605 /* SoftAP mode, so return from here */
2606 EXIT();
2607 return 0;
2608 }
2609
2610 /* Find if any iface is up then
2611 if any iface is up then can't put device to sleep/ power save mode. */
2612 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2613 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2614 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002615 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2616 {
2617 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302618 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002619 enter_standby = FALSE;
2620 break;
2621 }
2622 else
2623 {
2624 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2625 pAdapterNode = pNext;
2626 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 }
2628
2629 if (TRUE == enter_standby)
2630 {
2631 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2632 "entering standby", __func__);
2633 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2634 {
2635 /*log and return success*/
2636 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2637 "wlan in power save", __func__);
2638 }
2639 }
2640
2641 EXIT();
2642 return 0;
2643}
2644
2645/**---------------------------------------------------------------------------
2646
2647 \brief hdd_uninit() - HDD uninit function
2648
2649 This is called during the netdev unregister to uninitialize all data
2650associated with the device
2651
2652 \param - dev Pointer to net_device structure
2653
2654 \return - void
2655
2656 --------------------------------------------------------------------------*/
2657static void hdd_uninit (struct net_device *dev)
2658{
2659 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2660
2661 ENTER();
2662
2663 do
2664 {
2665 if (NULL == pAdapter)
2666 {
2667 hddLog(VOS_TRACE_LEVEL_FATAL,
2668 "%s: NULL pAdapter", __func__);
2669 break;
2670 }
2671
2672 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2673 {
2674 hddLog(VOS_TRACE_LEVEL_FATAL,
2675 "%s: Invalid magic", __func__);
2676 break;
2677 }
2678
2679 if (NULL == pAdapter->pHddCtx)
2680 {
2681 hddLog(VOS_TRACE_LEVEL_FATAL,
2682 "%s: NULL pHddCtx", __func__);
2683 break;
2684 }
2685
2686 if (dev != pAdapter->dev)
2687 {
2688 hddLog(VOS_TRACE_LEVEL_FATAL,
2689 "%s: Invalid device reference", __func__);
2690 /* we haven't validated all cases so let this go for now */
2691 }
2692
2693 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2694
2695 /* after uninit our adapter structure will no longer be valid */
2696 pAdapter->dev = NULL;
2697 pAdapter->magic = 0;
2698 } while (0);
2699
2700 EXIT();
2701}
2702
2703/**---------------------------------------------------------------------------
2704
2705 \brief hdd_release_firmware() -
2706
2707 This function calls the release firmware API to free the firmware buffer.
2708
2709 \param - pFileName Pointer to the File Name.
2710 pCtx - Pointer to the adapter .
2711
2712
2713 \return - 0 for success, non zero for failure
2714
2715 --------------------------------------------------------------------------*/
2716
2717VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2718{
2719 VOS_STATUS status = VOS_STATUS_SUCCESS;
2720 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2721 ENTER();
2722
2723
2724 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2725
2726 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2727
2728 if(pHddCtx->fw) {
2729 release_firmware(pHddCtx->fw);
2730 pHddCtx->fw = NULL;
2731 }
2732 else
2733 status = VOS_STATUS_E_FAILURE;
2734 }
2735 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2736 if(pHddCtx->nv) {
2737 release_firmware(pHddCtx->nv);
2738 pHddCtx->nv = NULL;
2739 }
2740 else
2741 status = VOS_STATUS_E_FAILURE;
2742
2743 }
2744
2745 EXIT();
2746 return status;
2747}
2748
2749/**---------------------------------------------------------------------------
2750
2751 \brief hdd_request_firmware() -
2752
2753 This function reads the firmware file using the request firmware
2754 API and returns the the firmware data and the firmware file size.
2755
2756 \param - pfileName - Pointer to the file name.
2757 - pCtx - Pointer to the adapter .
2758 - ppfw_data - Pointer to the pointer of the firmware data.
2759 - pSize - Pointer to the file size.
2760
2761 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2762
2763 --------------------------------------------------------------------------*/
2764
2765
2766VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2767{
2768 int status;
2769 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2770 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2771 ENTER();
2772
2773 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2774
2775 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2776
2777 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2778 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2779 __func__, pfileName);
2780 retval = VOS_STATUS_E_FAILURE;
2781 }
2782
2783 else {
2784 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2785 *pSize = pHddCtx->fw->size;
2786 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2787 __func__, *pSize);
2788 }
2789 }
2790 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2791
2792 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2793
2794 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2795 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2796 __func__, pfileName);
2797 retval = VOS_STATUS_E_FAILURE;
2798 }
2799
2800 else {
2801 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2802 *pSize = pHddCtx->nv->size;
2803 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2804 __func__, *pSize);
2805 }
2806 }
2807
2808 EXIT();
2809 return retval;
2810}
2811/**---------------------------------------------------------------------------
2812 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2813
2814 This is the function invoked by SME to inform the result of a full power
2815 request issued by HDD
2816
2817 \param - callbackcontext - Pointer to cookie
2818 status - result of request
2819
2820 \return - None
2821
2822--------------------------------------------------------------------------*/
2823void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2824{
2825 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2826
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002827 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 if(&pHddCtx->full_pwr_comp_var)
2829 {
2830 complete(&pHddCtx->full_pwr_comp_var);
2831 }
2832}
2833
2834/**---------------------------------------------------------------------------
2835
2836 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2837
2838 This is the function invoked by SME to inform the result of BMPS
2839 request issued by HDD
2840
2841 \param - callbackcontext - Pointer to cookie
2842 status - result of request
2843
2844 \return - None
2845
2846--------------------------------------------------------------------------*/
2847void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2848{
2849
2850 struct completion *completion_var = (struct completion*) callbackContext;
2851
2852 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2853 if(completion_var != NULL)
2854 {
2855 complete(completion_var);
2856 }
2857}
2858
2859/**---------------------------------------------------------------------------
2860
2861 \brief hdd_get_cfg_file_size() -
2862
2863 This function reads the configuration file using the request firmware
2864 API and returns the configuration file size.
2865
2866 \param - pCtx - Pointer to the adapter .
2867 - pFileName - Pointer to the file name.
2868 - pBufSize - Pointer to the buffer size.
2869
2870 \return - 0 for success, non zero for failure
2871
2872 --------------------------------------------------------------------------*/
2873
2874VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2875{
2876 int status;
2877 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2878
2879 ENTER();
2880
2881 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2882
2883 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2884 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2885 status = VOS_STATUS_E_FAILURE;
2886 }
2887 else {
2888 *pBufSize = pHddCtx->fw->size;
2889 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2890 release_firmware(pHddCtx->fw);
2891 pHddCtx->fw = NULL;
2892 }
2893
2894 EXIT();
2895 return VOS_STATUS_SUCCESS;
2896}
2897
2898/**---------------------------------------------------------------------------
2899
2900 \brief hdd_read_cfg_file() -
2901
2902 This function reads the configuration file using the request firmware
2903 API and returns the cfg data and the buffer size of the configuration file.
2904
2905 \param - pCtx - Pointer to the adapter .
2906 - pFileName - Pointer to the file name.
2907 - pBuffer - Pointer to the data buffer.
2908 - pBufSize - Pointer to the buffer size.
2909
2910 \return - 0 for success, non zero for failure
2911
2912 --------------------------------------------------------------------------*/
2913
2914VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2915 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2916{
2917 int status;
2918 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2919
2920 ENTER();
2921
2922 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2923
2924 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2926 return VOS_STATUS_E_FAILURE;
2927 }
2928 else {
2929 if(*pBufSize != pHddCtx->fw->size) {
2930 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2931 "file size", __func__);
2932 release_firmware(pHddCtx->fw);
2933 pHddCtx->fw = NULL;
2934 return VOS_STATUS_E_FAILURE;
2935 }
2936 else {
2937 if(pBuffer) {
2938 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2939 }
2940 release_firmware(pHddCtx->fw);
2941 pHddCtx->fw = NULL;
2942 }
2943 }
2944
2945 EXIT();
2946
2947 return VOS_STATUS_SUCCESS;
2948}
2949
2950/**---------------------------------------------------------------------------
2951
Jeff Johnson295189b2012-06-20 16:38:30 -07002952 \brief hdd_set_mac_address() -
2953
2954 This function sets the user specified mac address using
2955 the command ifconfig wlanX hw ether <mac adress>.
2956
2957 \param - dev - Pointer to the net device.
2958 - addr - Pointer to the sockaddr.
2959 \return - 0 for success, non zero for failure
2960
2961 --------------------------------------------------------------------------*/
2962
2963static int hdd_set_mac_address(struct net_device *dev, void *addr)
2964{
2965 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2966 struct sockaddr *psta_mac_addr = addr;
2967 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2968
2969 ENTER();
2970
2971 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2972
2973#ifdef HDD_SESSIONIZE
2974 // set the MAC address though the STA ID CFG.
2975 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2976 (v_U8_t *)&pAdapter->macAddressCurrent,
2977 sizeof( pAdapter->macAddressCurrent ),
2978 hdd_set_mac_addr_cb, VOS_FALSE );
2979#endif
2980
2981 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2982
2983 EXIT();
2984 return halStatus;
2985}
2986
2987tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2988{
2989 int i;
2990 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2991 {
2992 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2993 break;
2994 }
2995
2996 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2997 return NULL;
2998
2999 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3000 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3001}
3002
3003void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3004{
3005 int i;
3006 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3007 {
3008 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3009 {
3010 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3011 break;
3012 }
3013 }
3014 return;
3015}
3016
3017#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3018 static struct net_device_ops wlan_drv_ops = {
3019 .ndo_open = hdd_open,
3020 .ndo_stop = hdd_stop,
3021 .ndo_uninit = hdd_uninit,
3022 .ndo_start_xmit = hdd_hard_start_xmit,
3023 .ndo_tx_timeout = hdd_tx_timeout,
3024 .ndo_get_stats = hdd_stats,
3025 .ndo_do_ioctl = hdd_ioctl,
3026 .ndo_set_mac_address = hdd_set_mac_address,
3027 .ndo_select_queue = hdd_select_queue,
3028#ifdef WLAN_FEATURE_PACKET_FILTERING
3029#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3030 .ndo_set_rx_mode = hdd_set_multicast_list,
3031#else
3032 .ndo_set_multicast_list = hdd_set_multicast_list,
3033#endif //LINUX_VERSION_CODE
3034#endif
3035 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003036 static struct net_device_ops wlan_mon_drv_ops = {
3037 .ndo_open = hdd_mon_open,
3038 .ndo_stop = hdd_stop,
3039 .ndo_uninit = hdd_uninit,
3040 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3041 .ndo_tx_timeout = hdd_tx_timeout,
3042 .ndo_get_stats = hdd_stats,
3043 .ndo_do_ioctl = hdd_ioctl,
3044 .ndo_set_mac_address = hdd_set_mac_address,
3045 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003046
3047#endif
3048
3049void hdd_set_station_ops( struct net_device *pWlanDev )
3050{
3051#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3052 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3053 pWlanDev->netdev_ops = &wlan_drv_ops;
3054#else
3055 pWlanDev->open = hdd_open;
3056 pWlanDev->stop = hdd_stop;
3057 pWlanDev->uninit = hdd_uninit;
3058 pWlanDev->hard_start_xmit = NULL;
3059 pWlanDev->tx_timeout = hdd_tx_timeout;
3060 pWlanDev->get_stats = hdd_stats;
3061 pWlanDev->do_ioctl = hdd_ioctl;
3062 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3063 pWlanDev->set_mac_address = hdd_set_mac_address;
3064#endif
3065}
3066
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003067static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003068{
3069 struct net_device *pWlanDev = NULL;
3070 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003071 /*
3072 * cfg80211 initialization and registration....
3073 */
3074 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3075
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 if(pWlanDev != NULL)
3077 {
3078
3079 //Save the pointer to the net_device in the HDD adapter
3080 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3081
Jeff Johnson295189b2012-06-20 16:38:30 -07003082 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3083
3084 pAdapter->dev = pWlanDev;
3085 pAdapter->pHddCtx = pHddCtx;
3086 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3087
3088 init_completion(&pAdapter->session_open_comp_var);
3089 init_completion(&pAdapter->session_close_comp_var);
3090 init_completion(&pAdapter->disconnect_comp_var);
3091 init_completion(&pAdapter->linkup_event_var);
3092 init_completion(&pAdapter->cancel_rem_on_chan_var);
3093 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003094#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3095 init_completion(&pAdapter->offchannel_tx_event);
3096#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003098#ifdef FEATURE_WLAN_TDLS
3099 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003100 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003101 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303102 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003103#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003104 init_completion(&pHddCtx->mc_sus_event_var);
3105 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303106 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003107 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003108
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 pAdapter->isLinkUpSvcNeeded = FALSE;
3110 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3111 //Init the net_device structure
3112 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3113
3114 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3115 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3116 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3117 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3118
3119 hdd_set_station_ops( pAdapter->dev );
3120
3121 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3123 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3124 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003125 /* set pWlanDev's parent to underlying device */
3126 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3127 }
3128
3129 return pAdapter;
3130}
3131
3132VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3133{
3134 struct net_device *pWlanDev = pAdapter->dev;
3135 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3136 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3137 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3138
3139 if( rtnl_lock_held )
3140 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003141 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3143 {
3144 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3145 return VOS_STATUS_E_FAILURE;
3146 }
3147 }
3148 if (register_netdevice(pWlanDev))
3149 {
3150 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3151 return VOS_STATUS_E_FAILURE;
3152 }
3153 }
3154 else
3155 {
3156 if(register_netdev(pWlanDev))
3157 {
3158 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3159 return VOS_STATUS_E_FAILURE;
3160 }
3161 }
3162 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3163
3164 return VOS_STATUS_SUCCESS;
3165}
3166
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003167static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003168{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003169 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003170
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003171 if (NULL == pAdapter)
3172 {
3173 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3174 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003176
3177 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3178 {
3179 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3180 return eHAL_STATUS_NOT_INITIALIZED;
3181 }
3182
3183 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3184
3185 /* need to make sure all of our scheduled work has completed.
3186 * This callback is called from MC thread context, so it is safe to
3187 * to call below flush workqueue API from here.
3188 */
3189 flush_scheduled_work();
3190
3191 /* We can be blocked while waiting for scheduled work to be
3192 * flushed, and the adapter structure can potentially be freed, in
3193 * which case the magic will have been reset. So make sure the
3194 * magic is still good, and hence the adapter structure is still
3195 * valid, before signaling completion */
3196 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3197 {
3198 complete(&pAdapter->session_close_comp_var);
3199 }
3200
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 return eHAL_STATUS_SUCCESS;
3202}
3203
3204VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3205{
3206 struct net_device *pWlanDev = pAdapter->dev;
3207 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3208 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3209 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3210 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3211 int rc = 0;
3212
3213 INIT_COMPLETION(pAdapter->session_open_comp_var);
3214 //Open a SME session for future operation
3215 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3216 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3217 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3218 {
3219 hddLog(VOS_TRACE_LEVEL_FATAL,
3220 "sme_OpenSession() failed with status code %08d [x%08lx]",
3221 halStatus, halStatus );
3222 status = VOS_STATUS_E_FAILURE;
3223 goto error_sme_open;
3224 }
3225
3226 //Block on a completion variable. Can't wait forever though.
3227 rc = wait_for_completion_interruptible_timeout(
3228 &pAdapter->session_open_comp_var,
3229 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3230 if (!rc)
3231 {
3232 hddLog(VOS_TRACE_LEVEL_FATAL,
3233 "Session is not opened within timeout period code %08d", rc );
3234 status = VOS_STATUS_E_FAILURE;
3235 goto error_sme_open;
3236 }
3237
3238 // Register wireless extensions
3239 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3240 {
3241 hddLog(VOS_TRACE_LEVEL_FATAL,
3242 "hdd_register_wext() failed with status code %08d [x%08lx]",
3243 halStatus, halStatus );
3244 status = VOS_STATUS_E_FAILURE;
3245 goto error_register_wext;
3246 }
3247 //Safe to register the hard_start_xmit function again
3248#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3249 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3250#else
3251 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3252#endif
3253
3254 //Set the Connection State to Not Connected
3255 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3256
3257 //Set the default operation channel
3258 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3259
3260 /* Make the default Auth Type as OPEN*/
3261 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3262
3263 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3264 {
3265 hddLog(VOS_TRACE_LEVEL_FATAL,
3266 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3267 status, status );
3268 goto error_init_txrx;
3269 }
3270
3271 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3272
3273 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3274 {
3275 hddLog(VOS_TRACE_LEVEL_FATAL,
3276 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3277 status, status );
3278 goto error_wmm_init;
3279 }
3280
3281 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3282
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003283#ifdef FEATURE_WLAN_TDLS
3284 if(0 != wlan_hdd_tdls_init(pAdapter))
3285 {
3286 status = VOS_STATUS_E_FAILURE;
3287 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3288 goto error_tdls_init;
3289 }
3290 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3291#endif
3292
Jeff Johnson295189b2012-06-20 16:38:30 -07003293 return VOS_STATUS_SUCCESS;
3294
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003295#ifdef FEATURE_WLAN_TDLS
3296error_tdls_init:
3297 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3298 hdd_wmm_adapter_close(pAdapter);
3299#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003300error_wmm_init:
3301 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3302 hdd_deinit_tx_rx(pAdapter);
3303error_init_txrx:
3304 hdd_UnregisterWext(pWlanDev);
3305error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003306 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003307 {
3308 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003309 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003311 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003312 {
3313 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003314 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003316 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 }
3318}
3319error_sme_open:
3320 return status;
3321}
3322
Jeff Johnson295189b2012-06-20 16:38:30 -07003323void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3324{
3325 hdd_cfg80211_state_t *cfgState;
3326
3327 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3328
3329 if( NULL != cfgState->buf )
3330 {
3331 int rc;
3332 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3333 rc = wait_for_completion_interruptible_timeout(
3334 &pAdapter->tx_action_cnf_event,
3335 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3336 if(!rc)
3337 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003339 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3340 }
3341 }
3342 return;
3343}
Jeff Johnson295189b2012-06-20 16:38:30 -07003344
3345void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3346{
3347 ENTER();
3348 switch ( pAdapter->device_mode )
3349 {
3350 case WLAN_HDD_INFRA_STATION:
3351 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003352 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003353 {
3354 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3355 {
3356 hdd_deinit_tx_rx( pAdapter );
3357 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3358 }
3359
3360 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3361 {
3362 hdd_wmm_adapter_close( pAdapter );
3363 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3364 }
3365
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003367#ifdef FEATURE_WLAN_TDLS
3368 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3369 {
3370 wlan_hdd_tdls_exit(pAdapter);
3371 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3372 }
3373#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003374
3375 break;
3376 }
3377
3378 case WLAN_HDD_SOFTAP:
3379 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003380 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003382
3383 hdd_unregister_hostapd(pAdapter);
3384 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003385 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 break;
3387 }
3388
3389 case WLAN_HDD_MONITOR:
3390 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003391 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003392 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3393 {
3394 hdd_deinit_tx_rx( pAdapter );
3395 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003397 if(NULL != pAdapterforTx)
3398 {
3399 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3400 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003401 break;
3402 }
3403
3404
3405 default:
3406 break;
3407 }
3408
3409 EXIT();
3410}
3411
3412void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3413{
3414 struct net_device *pWlanDev = pAdapter->dev;
3415
3416 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3417 if( rtnl_held )
3418 {
3419 unregister_netdevice(pWlanDev);
3420 }
3421 else
3422 {
3423 unregister_netdev(pWlanDev);
3424 }
3425 // note that the pAdapter is no longer valid at this point
3426 // since the memory has been reclaimed
3427 }
3428
3429}
3430
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003431void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3432{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303433 VOS_STATUS status;
3434 hdd_adapter_t *pAdapter = NULL;
3435 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003436
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303437 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003438
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303439 /*loop through all adapters.*/
3440 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003441 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303442 pAdapter = pAdapterNode->pAdapter;
3443 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3444 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003445
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303446 { // we skip this registration for modes other than STA and P2P client modes.
3447 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3448 pAdapterNode = pNext;
3449 continue;
3450 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003451
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303452 //Apply Dynamic DTIM For P2P
3453 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3454 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3455 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3456 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3457 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3458 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3459 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3460 (eConnectionState_Associated ==
3461 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3462 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3463 {
3464 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003465
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303466 powerRequest.uIgnoreDTIM = 1;
3467 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3468
3469 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3470 {
3471 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3472 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3473 }
3474 else
3475 {
3476 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3477 }
3478
3479 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3480 * specified during Enter/Exit BMPS when LCD off*/
3481 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3482 NULL, eANI_BOOLEAN_FALSE);
3483 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3484 NULL, eANI_BOOLEAN_FALSE);
3485
3486 /* switch to the DTIM specified in cfg.ini */
3487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3488 "Switch to DTIM %d", powerRequest.uListenInterval);
3489 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3490 break;
3491
3492 }
3493
3494 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3495 pAdapterNode = pNext;
3496 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003497}
3498
3499void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3500{
3501 /*Switch back to DTIM 1*/
3502 tSirSetPowerParamsReq powerRequest = { 0 };
3503
3504 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3505 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003506 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003507
3508 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3509 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3510 NULL, eANI_BOOLEAN_FALSE);
3511 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3512 NULL, eANI_BOOLEAN_FALSE);
3513
3514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3515 "Switch to DTIM%d",powerRequest.uListenInterval);
3516 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3517
3518}
3519
Jeff Johnson295189b2012-06-20 16:38:30 -07003520VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3521{
3522 VOS_STATUS status = VOS_STATUS_SUCCESS;
3523
3524 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3525 {
3526 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3527 }
3528
3529 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3530 {
3531 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3532 }
3533
3534 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3535 {
3536 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3537 }
3538
3539 return status;
3540}
3541
3542VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3543{
3544 hdd_adapter_t *pAdapter = NULL;
3545 eHalStatus halStatus;
3546 VOS_STATUS status = VOS_STATUS_E_INVAL;
3547 v_BOOL_t disableBmps = FALSE;
3548 v_BOOL_t disableImps = FALSE;
3549
3550 switch(session_type)
3551 {
3552 case WLAN_HDD_INFRA_STATION:
3553 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 case WLAN_HDD_P2P_CLIENT:
3555 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003556 //Exit BMPS -> Is Sta/P2P Client is already connected
3557 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3558 if((NULL != pAdapter)&&
3559 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3560 {
3561 disableBmps = TRUE;
3562 }
3563
3564 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3565 if((NULL != pAdapter)&&
3566 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3567 {
3568 disableBmps = TRUE;
3569 }
3570
3571 //Exit both Bmps and Imps incase of Go/SAP Mode
3572 if((WLAN_HDD_SOFTAP == session_type) ||
3573 (WLAN_HDD_P2P_GO == session_type))
3574 {
3575 disableBmps = TRUE;
3576 disableImps = TRUE;
3577 }
3578
3579 if(TRUE == disableImps)
3580 {
3581 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3582 {
3583 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3584 }
3585 }
3586
3587 if(TRUE == disableBmps)
3588 {
3589 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3590 {
3591 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3592
3593 if(eHAL_STATUS_SUCCESS != halStatus)
3594 {
3595 status = VOS_STATUS_E_FAILURE;
3596 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3597 VOS_ASSERT(0);
3598 return status;
3599 }
3600 }
3601
3602 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3603 {
3604 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3605
3606 if(eHAL_STATUS_SUCCESS != halStatus)
3607 {
3608 status = VOS_STATUS_E_FAILURE;
3609 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3610 VOS_ASSERT(0);
3611 return status;
3612 }
3613 }
3614 }
3615
3616 if((TRUE == disableBmps) ||
3617 (TRUE == disableImps))
3618 {
3619 /* Now, get the chip into Full Power now */
3620 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3621 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3622 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3623
3624 if(halStatus != eHAL_STATUS_SUCCESS)
3625 {
3626 if(halStatus == eHAL_STATUS_PMC_PENDING)
3627 {
3628 //Block on a completion variable. Can't wait forever though
3629 wait_for_completion_interruptible_timeout(
3630 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3631 }
3632 else
3633 {
3634 status = VOS_STATUS_E_FAILURE;
3635 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3636 VOS_ASSERT(0);
3637 return status;
3638 }
3639 }
3640
3641 status = VOS_STATUS_SUCCESS;
3642 }
3643
3644 break;
3645 }
3646 return status;
3647}
3648
3649hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003650 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003651 tANI_U8 rtnl_held )
3652{
3653 hdd_adapter_t *pAdapter = NULL;
3654 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3655 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3656 VOS_STATUS exitbmpsStatus;
3657
3658 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3659
3660 //Disable BMPS incase of Concurrency
3661 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3662
3663 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3664 {
3665 //Fail to Exit BMPS
3666 VOS_ASSERT(0);
3667 return NULL;
3668 }
3669
3670 switch(session_type)
3671 {
3672 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003674 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003675 {
3676 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3677
3678 if( NULL == pAdapter )
3679 return NULL;
3680
Jeff Johnsone7245742012-09-05 17:12:55 -07003681 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3682 NL80211_IFTYPE_P2P_CLIENT:
3683 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003684
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 pAdapter->device_mode = session_type;
3686
3687 status = hdd_init_station_mode( pAdapter );
3688 if( VOS_STATUS_SUCCESS != status )
3689 goto err_free_netdev;
3690
3691 status = hdd_register_interface( pAdapter, rtnl_held );
3692 if( VOS_STATUS_SUCCESS != status )
3693 {
3694 hdd_deinit_adapter(pHddCtx, pAdapter);
3695 goto err_free_netdev;
3696 }
3697 //Stop the Interface TX queue.
3698 netif_tx_disable(pAdapter->dev);
3699 //netif_tx_disable(pWlanDev);
3700 netif_carrier_off(pAdapter->dev);
3701
3702 break;
3703 }
3704
Jeff Johnson295189b2012-06-20 16:38:30 -07003705 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003706 case WLAN_HDD_SOFTAP:
3707 {
3708 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3709 if( NULL == pAdapter )
3710 return NULL;
3711
Jeff Johnson295189b2012-06-20 16:38:30 -07003712 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3713 NL80211_IFTYPE_AP:
3714 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003715 pAdapter->device_mode = session_type;
3716
3717 status = hdd_init_ap_mode(pAdapter);
3718 if( VOS_STATUS_SUCCESS != status )
3719 goto err_free_netdev;
3720
3721 status = hdd_register_hostapd( pAdapter, rtnl_held );
3722 if( VOS_STATUS_SUCCESS != status )
3723 {
3724 hdd_deinit_adapter(pHddCtx, pAdapter);
3725 goto err_free_netdev;
3726 }
3727
3728 netif_tx_disable(pAdapter->dev);
3729 netif_carrier_off(pAdapter->dev);
3730
3731 hdd_set_conparam( 1 );
3732 break;
3733 }
3734 case WLAN_HDD_MONITOR:
3735 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003736 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3737 if( NULL == pAdapter )
3738 return NULL;
3739
3740 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3741 pAdapter->device_mode = session_type;
3742 status = hdd_register_interface( pAdapter, rtnl_held );
3743#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3744 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3745#else
3746 pAdapter->dev->open = hdd_mon_open;
3747 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3748#endif
3749 hdd_init_tx_rx( pAdapter );
3750 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3751 //Set adapter to be used for data tx. It will use either GO or softap.
3752 pAdapter->sessionCtx.monitor.pAdapterForTx =
3753 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3755 {
3756 pAdapter->sessionCtx.monitor.pAdapterForTx =
3757 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3758 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003759 /* This workqueue will be used to transmit management packet over
3760 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003761 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3762 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3763 return NULL;
3764 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003765
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3767 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 }
3769 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 case WLAN_HDD_FTM:
3771 {
3772 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3773
3774 if( NULL == pAdapter )
3775 return NULL;
3776 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3777 * message while loading driver in FTM mode. */
3778 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3779 pAdapter->device_mode = session_type;
3780 status = hdd_register_interface( pAdapter, rtnl_held );
3781 }
3782 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003783 default:
3784 {
3785 VOS_ASSERT(0);
3786 return NULL;
3787 }
3788 }
3789
3790
3791 if( VOS_STATUS_SUCCESS == status )
3792 {
3793 //Add it to the hdd's session list.
3794 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3795 if( NULL == pHddAdapterNode )
3796 {
3797 status = VOS_STATUS_E_NOMEM;
3798 }
3799 else
3800 {
3801 pHddAdapterNode->pAdapter = pAdapter;
3802 status = hdd_add_adapter_back ( pHddCtx,
3803 pHddAdapterNode );
3804 }
3805 }
3806
3807 if( VOS_STATUS_SUCCESS != status )
3808 {
3809 if( NULL != pAdapter )
3810 {
3811 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3812 pAdapter = NULL;
3813 }
3814 if( NULL != pHddAdapterNode )
3815 {
3816 vos_mem_free( pHddAdapterNode );
3817 }
3818
3819 goto resume_bmps;
3820 }
3821
3822 if(VOS_STATUS_SUCCESS == status)
3823 {
3824 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3825
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003826 //Initialize the WoWL service
3827 if(!hdd_init_wowl(pAdapter))
3828 {
3829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3830 goto err_free_netdev;
3831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003833 return pAdapter;
3834
3835err_free_netdev:
3836 free_netdev(pAdapter->dev);
3837 wlan_hdd_release_intf_addr( pHddCtx,
3838 pAdapter->macAddressCurrent.bytes );
3839
3840resume_bmps:
3841 //If bmps disabled enable it
3842 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3843 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303844 if (pHddCtx->hdd_wlan_suspended)
3845 {
3846 hdd_set_pwrparams(pHddCtx);
3847 }
3848 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003849 }
3850 return NULL;
3851}
3852
3853VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3854 tANI_U8 rtnl_held )
3855{
3856 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3857 VOS_STATUS status;
3858
3859 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3860 if( VOS_STATUS_SUCCESS != status )
3861 return status;
3862
3863 while ( pCurrent->pAdapter != pAdapter )
3864 {
3865 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3866 if( VOS_STATUS_SUCCESS != status )
3867 break;
3868
3869 pCurrent = pNext;
3870 }
3871 pAdapterNode = pCurrent;
3872 if( VOS_STATUS_SUCCESS == status )
3873 {
3874 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3875 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3876 hdd_remove_adapter( pHddCtx, pAdapterNode );
3877 vos_mem_free( pAdapterNode );
3878
Jeff Johnson295189b2012-06-20 16:38:30 -07003879
3880 /* If there is a single session of STA/P2P client, re-enable BMPS */
3881 if ((!vos_concurrent_sessions_running()) &&
3882 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3883 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3884 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303885 if (pHddCtx->hdd_wlan_suspended)
3886 {
3887 hdd_set_pwrparams(pHddCtx);
3888 }
3889 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003890 }
3891
3892 return VOS_STATUS_SUCCESS;
3893 }
3894
3895 return VOS_STATUS_E_FAILURE;
3896}
3897
3898VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3899{
3900 hdd_adapter_list_node_t *pHddAdapterNode;
3901 VOS_STATUS status;
3902
3903 ENTER();
3904
3905 do
3906 {
3907 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3908 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3909 {
3910 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3911 vos_mem_free( pHddAdapterNode );
3912 }
3913 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3914
3915 EXIT();
3916
3917 return VOS_STATUS_SUCCESS;
3918}
3919
3920void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3921{
3922 v_U8_t addIE[1] = {0};
3923
3924 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3925 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3926 eANI_BOOLEAN_FALSE) )
3927 {
3928 hddLog(LOGE,
3929 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3930 }
3931
3932 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3933 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3934 eANI_BOOLEAN_FALSE) )
3935 {
3936 hddLog(LOGE,
3937 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3938 }
3939
3940 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3941 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3942 eANI_BOOLEAN_FALSE) )
3943 {
3944 hddLog(LOGE,
3945 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3946 }
3947}
3948
3949VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3950{
3951 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3952 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3953 union iwreq_data wrqu;
3954
3955 ENTER();
3956
3957 switch(pAdapter->device_mode)
3958 {
3959 case WLAN_HDD_INFRA_STATION:
3960 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003961 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003962 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3963 {
3964 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3965 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3966 pAdapter->sessionId,
3967 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3968 else
3969 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3970 pAdapter->sessionId,
3971 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3972 //success implies disconnect command got queued up successfully
3973 if(halStatus == eHAL_STATUS_SUCCESS)
3974 {
3975 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3976 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3977 }
3978 memset(&wrqu, '\0', sizeof(wrqu));
3979 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3980 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3981 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3982 }
3983 else
3984 {
3985 hdd_abort_mac_scan(pHddCtx);
3986 }
3987
3988 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3989 {
3990 INIT_COMPLETION(pAdapter->session_close_comp_var);
3991 if (eHAL_STATUS_SUCCESS ==
3992 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3993 hdd_smeCloseSessionCallback, pAdapter))
3994 {
3995 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003996 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003997 &pAdapter->session_close_comp_var,
3998 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3999 }
4000 }
4001
4002 break;
4003
4004 case WLAN_HDD_SOFTAP:
4005 case WLAN_HDD_P2P_GO:
4006 //Any softap specific cleanup here...
4007 mutex_lock(&pHddCtx->sap_lock);
4008 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4009 {
4010 VOS_STATUS status;
4011 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4012
4013 //Stop Bss.
4014 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4015 if (VOS_IS_STATUS_SUCCESS(status))
4016 {
4017 hdd_hostapd_state_t *pHostapdState =
4018 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4019
4020 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4021
4022 if (!VOS_IS_STATUS_SUCCESS(status))
4023 {
4024 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004025 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 }
4027 }
4028 else
4029 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004030 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004031 }
4032 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4033
4034 if (eHAL_STATUS_FAILURE ==
4035 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4036 0, NULL, eANI_BOOLEAN_FALSE))
4037 {
4038 hddLog(LOGE,
4039 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004040 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004041 }
4042
4043 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4044 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4045 eANI_BOOLEAN_FALSE) )
4046 {
4047 hddLog(LOGE,
4048 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4049 }
4050
4051 // Reset WNI_CFG_PROBE_RSP Flags
4052 wlan_hdd_reset_prob_rspies(pAdapter);
4053 kfree(pAdapter->sessionCtx.ap.beacon);
4054 pAdapter->sessionCtx.ap.beacon = NULL;
4055 }
4056 mutex_unlock(&pHddCtx->sap_lock);
4057 break;
4058 case WLAN_HDD_MONITOR:
4059 break;
4060 default:
4061 break;
4062 }
4063
4064 EXIT();
4065 return VOS_STATUS_SUCCESS;
4066}
4067
4068VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4069{
4070 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4071 VOS_STATUS status;
4072 hdd_adapter_t *pAdapter;
4073
4074 ENTER();
4075
4076 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4077
4078 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4079 {
4080 pAdapter = pAdapterNode->pAdapter;
4081 netif_tx_disable(pAdapter->dev);
4082 netif_carrier_off(pAdapter->dev);
4083
4084 hdd_stop_adapter( pHddCtx, pAdapter );
4085
4086 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4087 pAdapterNode = pNext;
4088 }
4089
4090 EXIT();
4091
4092 return VOS_STATUS_SUCCESS;
4093}
4094
4095VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4096{
4097 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4098 VOS_STATUS status;
4099 hdd_adapter_t *pAdapter;
4100
4101 ENTER();
4102
4103 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4104
4105 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4106 {
4107 pAdapter = pAdapterNode->pAdapter;
4108 netif_tx_disable(pAdapter->dev);
4109 netif_carrier_off(pAdapter->dev);
4110
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 hdd_deinit_tx_rx(pAdapter);
4112 hdd_wmm_adapter_close(pAdapter);
4113
4114 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4115 pAdapterNode = pNext;
4116 }
4117
4118 EXIT();
4119
4120 return VOS_STATUS_SUCCESS;
4121}
4122
4123VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4124{
4125 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4126 VOS_STATUS status;
4127 hdd_adapter_t *pAdapter;
4128 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304129 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004130
4131 ENTER();
4132
4133 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4134
4135 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4136 {
4137 pAdapter = pAdapterNode->pAdapter;
4138
4139 switch(pAdapter->device_mode)
4140 {
4141 case WLAN_HDD_INFRA_STATION:
4142 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004143 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304144
4145 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4146
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 hdd_init_station_mode(pAdapter);
4148 /* Open the gates for HDD to receive Wext commands */
4149 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004150 pHddCtx->scan_info.mScanPending = FALSE;
4151 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004152
4153 //Trigger the initial scan
4154 hdd_wlan_initial_scan(pAdapter);
4155
4156 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304157 if (eConnectionState_Associated == connState ||
4158 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 {
4160 union iwreq_data wrqu;
4161 memset(&wrqu, '\0', sizeof(wrqu));
4162 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4163 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4164 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004165
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 /* indicate disconnected event to nl80211 */
4167 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4168 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304170 else if (eConnectionState_Connecting == connState)
4171 {
4172 /*
4173 * Indicate connect failure to supplicant if we were in the
4174 * process of connecting
4175 */
4176 cfg80211_connect_result(pAdapter->dev, NULL,
4177 NULL, 0, NULL, 0,
4178 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4179 GFP_KERNEL);
4180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004181 break;
4182
4183 case WLAN_HDD_SOFTAP:
4184 /* softAP can handle SSR */
4185 break;
4186
4187 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004188 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4189 __func__);
4190 /* event supplicant to restart */
4191 cfg80211_del_sta(pAdapter->dev,
4192 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004193 break;
4194
4195 case WLAN_HDD_MONITOR:
4196 /* monitor interface start */
4197 break;
4198 default:
4199 break;
4200 }
4201
4202 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4203 pAdapterNode = pNext;
4204 }
4205
4206 EXIT();
4207
4208 return VOS_STATUS_SUCCESS;
4209}
4210
4211VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4212{
4213 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4214 hdd_adapter_t *pAdapter;
4215 VOS_STATUS status;
4216 v_U32_t roamId;
4217
4218 ENTER();
4219
4220 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4221
4222 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4223 {
4224 pAdapter = pAdapterNode->pAdapter;
4225
4226 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4227 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4228 {
4229 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4230 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4231
4232 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4233 init_completion(&pAdapter->disconnect_comp_var);
4234 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4235 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4236
4237 wait_for_completion_interruptible_timeout(
4238 &pAdapter->disconnect_comp_var,
4239 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4240
4241 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4242 pHddCtx->isAmpAllowed = VOS_FALSE;
4243 sme_RoamConnect(pHddCtx->hHal,
4244 pAdapter->sessionId, &(pWextState->roamProfile),
4245 &roamId);
4246 }
4247
4248 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4249 pAdapterNode = pNext;
4250 }
4251
4252 EXIT();
4253
4254 return VOS_STATUS_SUCCESS;
4255}
4256
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004257void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4258{
4259 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4260 VOS_STATUS status;
4261 hdd_adapter_t *pAdapter;
4262 hdd_station_ctx_t *pHddStaCtx;
4263 hdd_ap_ctx_t *pHddApCtx;
4264 hdd_hostapd_state_t * pHostapdState;
4265 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4266 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4267 const char *p2pMode = "DEV";
4268 const char *ccMode = "Standalone";
4269 int n;
4270
4271 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4272 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4273 {
4274 pAdapter = pAdapterNode->pAdapter;
4275 switch (pAdapter->device_mode) {
4276 case WLAN_HDD_INFRA_STATION:
4277 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4278 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4279 staChannel = pHddStaCtx->conn_info.operationChannel;
4280 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4281 }
4282 break;
4283 case WLAN_HDD_P2P_CLIENT:
4284 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4285 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4286 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4287 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4288 p2pMode = "CLI";
4289 }
4290 break;
4291 case WLAN_HDD_P2P_GO:
4292 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4293 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4294 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4295 p2pChannel = pHddApCtx->operatingChannel;
4296 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4297 }
4298 p2pMode = "GO";
4299 break;
4300 case WLAN_HDD_SOFTAP:
4301 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4302 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4303 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4304 apChannel = pHddApCtx->operatingChannel;
4305 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4306 }
4307 break;
4308 default:
4309 break;
4310 }
4311 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4312 pAdapterNode = pNext;
4313 }
4314 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4315 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4316 }
4317 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4318 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4319 if (p2pChannel > 0) {
4320 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4321 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4322 }
4323 if (apChannel > 0) {
4324 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4325 apChannel, MAC_ADDR_ARRAY(apBssid));
4326 }
4327
4328 if (p2pChannel > 0 && apChannel > 0) {
4329 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4330 }
4331}
4332
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004333bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004334{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004335 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004336}
4337
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004338/* Once SSR is disabled then it cannot be set. */
4339void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004340{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004341 if (HDD_SSR_DISABLED == isSsrRequired)
4342 return;
4343
Jeff Johnson295189b2012-06-20 16:38:30 -07004344 isSsrRequired = value;
4345}
4346
4347VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4348 hdd_adapter_list_node_t** ppAdapterNode)
4349{
4350 VOS_STATUS status;
4351 spin_lock(&pHddCtx->hddAdapters.lock);
4352 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4353 (hdd_list_node_t**) ppAdapterNode );
4354 spin_unlock(&pHddCtx->hddAdapters.lock);
4355 return status;
4356}
4357
4358VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4359 hdd_adapter_list_node_t* pAdapterNode,
4360 hdd_adapter_list_node_t** pNextAdapterNode)
4361{
4362 VOS_STATUS status;
4363 spin_lock(&pHddCtx->hddAdapters.lock);
4364 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4365 (hdd_list_node_t*) pAdapterNode,
4366 (hdd_list_node_t**)pNextAdapterNode );
4367
4368 spin_unlock(&pHddCtx->hddAdapters.lock);
4369 return status;
4370}
4371
4372VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4373 hdd_adapter_list_node_t* pAdapterNode)
4374{
4375 VOS_STATUS status;
4376 spin_lock(&pHddCtx->hddAdapters.lock);
4377 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4378 &pAdapterNode->node );
4379 spin_unlock(&pHddCtx->hddAdapters.lock);
4380 return status;
4381}
4382
4383VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4384 hdd_adapter_list_node_t** ppAdapterNode)
4385{
4386 VOS_STATUS status;
4387 spin_lock(&pHddCtx->hddAdapters.lock);
4388 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4389 (hdd_list_node_t**) ppAdapterNode );
4390 spin_unlock(&pHddCtx->hddAdapters.lock);
4391 return status;
4392}
4393
4394VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4395 hdd_adapter_list_node_t* pAdapterNode)
4396{
4397 VOS_STATUS status;
4398 spin_lock(&pHddCtx->hddAdapters.lock);
4399 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4400 (hdd_list_node_t*) pAdapterNode );
4401 spin_unlock(&pHddCtx->hddAdapters.lock);
4402 return status;
4403}
4404
4405VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4406 hdd_adapter_list_node_t* pAdapterNode)
4407{
4408 VOS_STATUS status;
4409 spin_lock(&pHddCtx->hddAdapters.lock);
4410 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4411 (hdd_list_node_t*) pAdapterNode );
4412 spin_unlock(&pHddCtx->hddAdapters.lock);
4413 return status;
4414}
4415
4416hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4417 tSirMacAddr macAddr )
4418{
4419 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4420 hdd_adapter_t *pAdapter;
4421 VOS_STATUS status;
4422
4423 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4424
4425 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4426 {
4427 pAdapter = pAdapterNode->pAdapter;
4428
4429 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4430 macAddr, sizeof(tSirMacAddr) ) )
4431 {
4432 return pAdapter;
4433 }
4434 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4435 pAdapterNode = pNext;
4436 }
4437
4438 return NULL;
4439
4440}
4441
4442hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4443{
4444 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4445 hdd_adapter_t *pAdapter;
4446 VOS_STATUS status;
4447
4448 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4449
4450 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4451 {
4452 pAdapter = pAdapterNode->pAdapter;
4453
4454 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4455 IFNAMSIZ ) )
4456 {
4457 return pAdapter;
4458 }
4459 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4460 pAdapterNode = pNext;
4461 }
4462
4463 return NULL;
4464
4465}
4466
4467hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4468{
4469 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4470 hdd_adapter_t *pAdapter;
4471 VOS_STATUS status;
4472
4473 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4474
4475 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4476 {
4477 pAdapter = pAdapterNode->pAdapter;
4478
4479 if( pAdapter && (mode == pAdapter->device_mode) )
4480 {
4481 return pAdapter;
4482 }
4483 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4484 pAdapterNode = pNext;
4485 }
4486
4487 return NULL;
4488
4489}
4490
4491//Remove this function later
4492hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4493{
4494 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4495 hdd_adapter_t *pAdapter;
4496 VOS_STATUS status;
4497
4498 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4499
4500 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4501 {
4502 pAdapter = pAdapterNode->pAdapter;
4503
4504 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4505 {
4506 return pAdapter;
4507 }
4508
4509 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4510 pAdapterNode = pNext;
4511 }
4512
4513 return NULL;
4514
4515}
4516
Jeff Johnson295189b2012-06-20 16:38:30 -07004517/**---------------------------------------------------------------------------
4518
4519 \brief hdd_set_monitor_tx_adapter() -
4520
4521 This API initializes the adapter to be used while transmitting on monitor
4522 adapter.
4523
4524 \param - pHddCtx - Pointer to the HDD context.
4525 pAdapter - Adapter that will used for TX. This can be NULL.
4526 \return - None.
4527 --------------------------------------------------------------------------*/
4528void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4529{
4530 hdd_adapter_t *pMonAdapter;
4531
4532 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4533
4534 if( NULL != pMonAdapter )
4535 {
4536 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4537 }
4538}
Jeff Johnson295189b2012-06-20 16:38:30 -07004539/**---------------------------------------------------------------------------
4540
4541 \brief hdd_select_queue() -
4542
4543 This API returns the operating channel of the requested device mode
4544
4545 \param - pHddCtx - Pointer to the HDD context.
4546 - mode - Device mode for which operating channel is required
4547 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4548 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4549 \return - channel number. "0" id the requested device is not found OR it is not connected.
4550 --------------------------------------------------------------------------*/
4551v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4552{
4553 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4554 VOS_STATUS status;
4555 hdd_adapter_t *pAdapter;
4556 v_U8_t operatingChannel = 0;
4557
4558 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4559
4560 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4561 {
4562 pAdapter = pAdapterNode->pAdapter;
4563
4564 if( mode == pAdapter->device_mode )
4565 {
4566 switch(pAdapter->device_mode)
4567 {
4568 case WLAN_HDD_INFRA_STATION:
4569 case WLAN_HDD_P2P_CLIENT:
4570 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4571 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4572 break;
4573 case WLAN_HDD_SOFTAP:
4574 case WLAN_HDD_P2P_GO:
4575 /*softap connection info */
4576 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4577 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4578 break;
4579 default:
4580 break;
4581 }
4582
4583 break; //Found the device of interest. break the loop
4584 }
4585
4586 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4587 pAdapterNode = pNext;
4588 }
4589 return operatingChannel;
4590}
4591
4592#ifdef WLAN_FEATURE_PACKET_FILTERING
4593/**---------------------------------------------------------------------------
4594
4595 \brief hdd_set_multicast_list() -
4596
4597 This used to set the multicast address list.
4598
4599 \param - dev - Pointer to the WLAN device.
4600 - skb - Pointer to OS packet (sk_buff).
4601 \return - success/fail
4602
4603 --------------------------------------------------------------------------*/
4604static void hdd_set_multicast_list(struct net_device *dev)
4605{
4606 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 int mc_count;
4608 int i = 0;
4609 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304610
4611 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004612 {
4613 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304614 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004615 return;
4616 }
4617
4618 if (dev->flags & IFF_ALLMULTI)
4619 {
4620 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004621 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304622 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004623 }
4624 else
4625 {
4626 mc_count = netdev_mc_count(dev);
4627 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004628 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004629 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4630 {
4631 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004632 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304633 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 return;
4635 }
4636
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304637 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004638
4639 netdev_for_each_mc_addr(ha, dev) {
4640 if (i == mc_count)
4641 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304642 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4643 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4644 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304646 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004647 i++;
4648 }
4649 }
4650 return;
4651}
4652#endif
4653
4654/**---------------------------------------------------------------------------
4655
4656 \brief hdd_select_queue() -
4657
4658 This function is registered with the Linux OS for network
4659 core to decide which queue to use first.
4660
4661 \param - dev - Pointer to the WLAN device.
4662 - skb - Pointer to OS packet (sk_buff).
4663 \return - ac, Queue Index/access category corresponding to UP in IP header
4664
4665 --------------------------------------------------------------------------*/
4666v_U16_t hdd_select_queue(struct net_device *dev,
4667 struct sk_buff *skb)
4668{
4669 return hdd_wmm_select_queue(dev, skb);
4670}
4671
4672
4673/**---------------------------------------------------------------------------
4674
4675 \brief hdd_wlan_initial_scan() -
4676
4677 This function triggers the initial scan
4678
4679 \param - pAdapter - Pointer to the HDD adapter.
4680
4681 --------------------------------------------------------------------------*/
4682void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4683{
4684 tCsrScanRequest scanReq;
4685 tCsrChannelInfo channelInfo;
4686 eHalStatus halStatus;
4687 unsigned long scanId;
4688 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4689
4690 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4691 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4692 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4693
4694 if(sme_Is11dSupported(pHddCtx->hHal))
4695 {
4696 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4697 if ( HAL_STATUS_SUCCESS( halStatus ) )
4698 {
4699 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4700 if( !scanReq.ChannelInfo.ChannelList )
4701 {
4702 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4703 vos_mem_free(channelInfo.ChannelList);
4704 return;
4705 }
4706 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4707 channelInfo.numOfChannels);
4708 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4709 vos_mem_free(channelInfo.ChannelList);
4710 }
4711
4712 scanReq.scanType = eSIR_PASSIVE_SCAN;
4713 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4714 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4715 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4716 }
4717 else
4718 {
4719 scanReq.scanType = eSIR_ACTIVE_SCAN;
4720 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4721 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4722 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4723 }
4724
4725 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4726 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4727 {
4728 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4729 __func__, halStatus );
4730 }
4731
4732 if(sme_Is11dSupported(pHddCtx->hHal))
4733 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4734}
4735
4736struct fullPowerContext
4737{
4738 struct completion completion;
4739 unsigned int magic;
4740};
4741#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4742
4743/**---------------------------------------------------------------------------
4744
4745 \brief hdd_full_power_callback() - HDD full power callback function
4746
4747 This is the function invoked by SME to inform the result of a full power
4748 request issued by HDD
4749
4750 \param - callbackcontext - Pointer to cookie
4751 \param - status - result of request
4752
4753 \return - None
4754
4755 --------------------------------------------------------------------------*/
4756static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4757{
4758 struct fullPowerContext *pContext = callbackContext;
4759
4760 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304761 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004762
4763 if (NULL == callbackContext)
4764 {
4765 hddLog(VOS_TRACE_LEVEL_ERROR,
4766 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004767 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 return;
4769 }
4770
4771 /* there is a race condition that exists between this callback function
4772 and the caller since the caller could time out either before or
4773 while this code is executing. we'll assume the timeout hasn't
4774 occurred, but we'll verify that right before we save our work */
4775
4776 if (POWER_CONTEXT_MAGIC != pContext->magic)
4777 {
4778 /* the caller presumably timed out so there is nothing we can do */
4779 hddLog(VOS_TRACE_LEVEL_WARN,
4780 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004781 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004782 return;
4783 }
4784
4785 /* the race is on. caller could have timed out immediately after
4786 we verified the magic, but if so, caller will wait a short time
4787 for us to notify the caller, so the context will stay valid */
4788 complete(&pContext->completion);
4789}
4790
4791/**---------------------------------------------------------------------------
4792
4793 \brief hdd_wlan_exit() - HDD WLAN exit function
4794
4795 This is the driver exit point (invoked during rmmod)
4796
4797 \param - pHddCtx - Pointer to the HDD Context
4798
4799 \return - None
4800
4801 --------------------------------------------------------------------------*/
4802void hdd_wlan_exit(hdd_context_t *pHddCtx)
4803{
4804 eHalStatus halStatus;
4805 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4806 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304807 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004808 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 struct fullPowerContext powerContext;
4810 long lrc;
4811
4812 ENTER();
4813
Jeff Johnson88ba7742013-02-27 14:36:02 -08004814 if (VOS_FTM_MODE != hdd_get_conparam())
4815 {
4816 // Unloading, restart logic is no more required.
4817 wlan_hdd_restart_deinit(pHddCtx);
4818 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004819
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 {
4824 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4825 WLAN_HDD_INFRA_STATION);
4826 if (pAdapter == NULL)
4827 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4828
4829 if (pAdapter != NULL)
4830 {
4831 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4832 hdd_UnregisterWext(pAdapter->dev);
4833 }
4834 }
4835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004836
Jeff Johnson295189b2012-06-20 16:38:30 -07004837 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004838 {
4839 wlan_hdd_ftm_close(pHddCtx);
4840 goto free_hdd_ctx;
4841 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004842 //Stop the Interface TX queue.
4843 //netif_tx_disable(pWlanDev);
4844 //netif_carrier_off(pWlanDev);
4845
Jeff Johnson295189b2012-06-20 16:38:30 -07004846 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4847 {
4848 pAdapter = hdd_get_adapter(pHddCtx,
4849 WLAN_HDD_SOFTAP);
4850 }
4851 else
4852 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004853 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 {
4855 pAdapter = hdd_get_adapter(pHddCtx,
4856 WLAN_HDD_INFRA_STATION);
4857 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 /* DeRegister with platform driver as client for Suspend/Resume */
4860 vosStatus = hddDeregisterPmOps(pHddCtx);
4861 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4862 {
4863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4864 VOS_ASSERT(0);
4865 }
4866
4867 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4868 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4869 {
4870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4871 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004872
4873 // Cancel any outstanding scan requests. We are about to close all
4874 // of our adapters, but an adapter structure is what SME passes back
4875 // to our callback function. Hence if there are any outstanding scan
4876 // requests then there is a race condition between when the adapter
4877 // is closed and when the callback is invoked. We try to resolve that
4878 // race condition here by canceling any outstanding scans before we
4879 // close the adapters.
4880 // Note that the scans may be cancelled in an asynchronous manner, so
4881 // ideally there needs to be some kind of synchronization. Rather than
4882 // introduce a new synchronization here, we will utilize the fact that
4883 // we are about to Request Full Power, and since that is synchronized,
4884 // the expectation is that by the time Request Full Power has completed,
4885 // all scans will be cancelled.
4886 hdd_abort_mac_scan( pHddCtx );
4887
4888 //Disable IMPS/BMPS as we do not want the device to enter any power
4889 //save mode during shutdown
4890 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4891 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4892 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4893
4894 //Ensure that device is in full power as we will touch H/W during vos_Stop
4895 init_completion(&powerContext.completion);
4896 powerContext.magic = POWER_CONTEXT_MAGIC;
4897
4898 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4899 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4900
4901 if (eHAL_STATUS_SUCCESS != halStatus)
4902 {
4903 if (eHAL_STATUS_PMC_PENDING == halStatus)
4904 {
4905 /* request was sent -- wait for the response */
4906 lrc = wait_for_completion_interruptible_timeout(
4907 &powerContext.completion,
4908 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4909 /* either we have a response or we timed out
4910 either way, first invalidate our magic */
4911 powerContext.magic = 0;
4912 if (lrc <= 0)
4913 {
4914 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004915 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 /* there is a race condition such that the callback
4917 function could be executing at the same time we are. of
4918 primary concern is if the callback function had already
4919 verified the "magic" but hasn't yet set the completion
4920 variable. Since the completion variable is on our
4921 stack, we'll delay just a bit to make sure the data is
4922 still valid if that is the case */
4923 msleep(50);
4924 }
4925 }
4926 else
4927 {
4928 hddLog(VOS_TRACE_LEVEL_ERROR,
4929 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004930 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 VOS_ASSERT(0);
4932 /* continue -- need to clean up as much as possible */
4933 }
4934 }
4935
4936 // Unregister the Net Device Notifier
4937 unregister_netdevice_notifier(&hdd_netdev_notifier);
4938
Jeff Johnson295189b2012-06-20 16:38:30 -07004939 hdd_stop_all_adapters( pHddCtx );
4940
Jeff Johnson295189b2012-06-20 16:38:30 -07004941#ifdef WLAN_BTAMP_FEATURE
4942 vosStatus = WLANBAP_Stop(pVosContext);
4943 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4944 {
4945 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4946 "%s: Failed to stop BAP",__func__);
4947 }
4948#endif //WLAN_BTAMP_FEATURE
4949
4950 //Stop all the modules
4951 vosStatus = vos_stop( pVosContext );
4952 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4953 {
4954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4955 "%s: Failed to stop VOSS",__func__);
4956 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4957 }
4958
Jeff Johnson295189b2012-06-20 16:38:30 -07004959 //Assert Deep sleep signal now to put Libra HW in lowest power state
4960 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4961 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4962
4963 //Vote off any PMIC voltage supplies
4964 vos_chipPowerDown(NULL, NULL, NULL);
4965
4966 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4967
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004970
4971 //Close the scheduler before calling vos_close to make sure no thread is
4972 // scheduled after the each module close is called i.e after all the data
4973 // structures are freed.
4974 vosStatus = vos_sched_close( pVosContext );
4975 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4976 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4977 "%s: Failed to close VOSS Scheduler",__func__);
4978 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4979 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004980#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004981#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4982 /* Destroy the wake lock */
4983 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4984#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004985 /* Destroy the wake lock */
4986 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004987#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004988
4989 //Close VOSS
4990 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4991 vos_close(pVosContext);
4992
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 //Close Watchdog
4994 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4995 vos_watchdog_close(pVosContext);
4996
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05304997 //Clean up HDD Nlink Service
4998 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4999 nl_srv_exit();
5000
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 /* Cancel the vote for XO Core ON.
5002 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5003 * exited at this point
5004 */
5005 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5006 " when WLAN is turned OFF\n");
5007 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5008 {
5009 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5010 " Not returning failure."
5011 " Power consumed will be high\n");
5012 }
5013
5014 hdd_close_all_adapters( pHddCtx );
5015
5016
5017 //Free up dynamically allocated members inside HDD Adapter
5018 kfree(pHddCtx->cfg_ini);
5019 pHddCtx->cfg_ini= NULL;
5020
5021 /* free the power on lock from platform driver */
5022 if (free_riva_power_on_lock("wlan"))
5023 {
5024 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5025 __func__);
5026 }
5027
Jeff Johnson88ba7742013-02-27 14:36:02 -08005028free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005029 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005030 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 if (hdd_is_ssr_required())
5032 {
5033 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005034 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005035 msleep(5000);
5036 }
5037 hdd_set_ssr_required (VOS_FALSE);
5038}
5039
5040
5041/**---------------------------------------------------------------------------
5042
5043 \brief hdd_update_config_from_nv() - Function to update the contents of
5044 the running configuration with parameters taken from NV storage
5045
5046 \param - pHddCtx - Pointer to the HDD global context
5047
5048 \return - VOS_STATUS_SUCCESS if successful
5049
5050 --------------------------------------------------------------------------*/
5051static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5052{
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 v_BOOL_t itemIsValid = VOS_FALSE;
5054 VOS_STATUS status;
5055 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5056 v_U8_t macLoop;
5057
5058 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5059 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5060 if(status != VOS_STATUS_SUCCESS)
5061 {
5062 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5063 return VOS_STATUS_E_FAILURE;
5064 }
5065
5066 if (itemIsValid == VOS_TRUE)
5067 {
5068 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5069 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5070 VOS_MAX_CONCURRENCY_PERSONA);
5071 if(status != VOS_STATUS_SUCCESS)
5072 {
5073 /* Get MAC from NV fail, not update CFG info
5074 * INI MAC value will be used for MAC setting */
5075 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5076 return VOS_STATUS_E_FAILURE;
5077 }
5078
5079 /* If first MAC is not valid, treat all others are not valid
5080 * Then all MACs will be got from ini file */
5081 if(vos_is_macaddr_zero(&macFromNV[0]))
5082 {
5083 /* MAC address in NV file is not configured yet */
5084 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5085 return VOS_STATUS_E_INVAL;
5086 }
5087
5088 /* Get MAC address from NV, update CFG info */
5089 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5090 {
5091 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5092 {
5093 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5094 /* This MAC is not valid, skip it
5095 * This MAC will be got from ini file */
5096 }
5097 else
5098 {
5099 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5100 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5101 VOS_MAC_ADDR_SIZE);
5102 }
5103 }
5104 }
5105 else
5106 {
5107 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5108 return VOS_STATUS_E_FAILURE;
5109 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005110
Jeff Johnson295189b2012-06-20 16:38:30 -07005111
5112 return VOS_STATUS_SUCCESS;
5113}
5114
5115/**---------------------------------------------------------------------------
5116
5117 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5118
5119 \param - pAdapter - Pointer to the HDD
5120
5121 \return - None
5122
5123 --------------------------------------------------------------------------*/
5124VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5125{
5126 eHalStatus halStatus;
5127 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305128 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005129
Jeff Johnson295189b2012-06-20 16:38:30 -07005130
5131 // Send ready indication to the HDD. This will kick off the MAC
5132 // into a 'running' state and should kick off an initial scan.
5133 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5134 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5135 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305136 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 "code %08d [x%08x]",__func__, halStatus, halStatus );
5138 return VOS_STATUS_E_FAILURE;
5139 }
5140
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305141 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005142 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5143 // And RIVA will crash
5144 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5145 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305146 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5147 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5148
5149
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 return VOS_STATUS_SUCCESS;
5151}
5152
Jeff Johnson295189b2012-06-20 16:38:30 -07005153/* wake lock APIs for HDD */
5154void hdd_prevent_suspend(void)
5155{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005156#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005158#else
5159 wcnss_prevent_suspend();
5160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005161}
5162
5163void hdd_allow_suspend(void)
5164{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005165#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005167#else
5168 wcnss_allow_suspend();
5169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005170}
5171
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005172void hdd_allow_suspend_timeout(v_U32_t timeout)
5173{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005174#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005175 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005176#else
5177 /* Do nothing as there is no API in wcnss for timeout*/
5178#endif
5179}
5180
Jeff Johnson295189b2012-06-20 16:38:30 -07005181/**---------------------------------------------------------------------------
5182
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005183 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5184 information between Host and Riva
5185
5186 This function gets reported version of FW
5187 It also finds the version of Riva headers used to compile the host
5188 It compares the above two and prints a warning if they are different
5189 It gets the SW and HW version string
5190 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5191 indicating the features they support through a bitmap
5192
5193 \param - pHddCtx - Pointer to HDD context
5194
5195 \return - void
5196
5197 --------------------------------------------------------------------------*/
5198
5199void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5200{
5201
5202 tSirVersionType versionCompiled;
5203 tSirVersionType versionReported;
5204 tSirVersionString versionString;
5205 tANI_U8 fwFeatCapsMsgSupported = 0;
5206 VOS_STATUS vstatus;
5207
5208 /* retrieve and display WCNSS version information */
5209 do {
5210
5211 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5212 &versionCompiled);
5213 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5214 {
5215 hddLog(VOS_TRACE_LEVEL_FATAL,
5216 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005217 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005218 break;
5219 }
5220
5221 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5222 &versionReported);
5223 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5224 {
5225 hddLog(VOS_TRACE_LEVEL_FATAL,
5226 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005227 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005228 break;
5229 }
5230
5231 if ((versionCompiled.major != versionReported.major) ||
5232 (versionCompiled.minor != versionReported.minor) ||
5233 (versionCompiled.version != versionReported.version) ||
5234 (versionCompiled.revision != versionReported.revision))
5235 {
5236 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5237 "Host expected %u.%u.%u.%u\n",
5238 WLAN_MODULE_NAME,
5239 (int)versionReported.major,
5240 (int)versionReported.minor,
5241 (int)versionReported.version,
5242 (int)versionReported.revision,
5243 (int)versionCompiled.major,
5244 (int)versionCompiled.minor,
5245 (int)versionCompiled.version,
5246 (int)versionCompiled.revision);
5247 }
5248 else
5249 {
5250 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5251 WLAN_MODULE_NAME,
5252 (int)versionReported.major,
5253 (int)versionReported.minor,
5254 (int)versionReported.version,
5255 (int)versionReported.revision);
5256 }
5257
5258 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5259 versionString,
5260 sizeof(versionString));
5261 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5262 {
5263 hddLog(VOS_TRACE_LEVEL_FATAL,
5264 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005265 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005266 break;
5267 }
5268
5269 pr_info("%s: WCNSS software version %s\n",
5270 WLAN_MODULE_NAME, versionString);
5271
5272 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5273 versionString,
5274 sizeof(versionString));
5275 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5276 {
5277 hddLog(VOS_TRACE_LEVEL_FATAL,
5278 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005279 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005280 break;
5281 }
5282
5283 pr_info("%s: WCNSS hardware version %s\n",
5284 WLAN_MODULE_NAME, versionString);
5285
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005286 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5287 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005288 send the message only if it the riva is 1.1
5289 minor numbers for different riva branches:
5290 0 -> (1.0)Mainline Build
5291 1 -> (1.1)Mainline Build
5292 2->(1.04) Stability Build
5293 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005294 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005295 ((versionReported.minor>=1) && (versionReported.version>=1)))
5296 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5297 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005298
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005299 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005300 {
5301#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5302 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5303 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5304#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005305 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005306 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005307
5308 } while (0);
5309
5310}
5311
5312/**---------------------------------------------------------------------------
5313
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 \brief hdd_wlan_startup() - HDD init function
5315
5316 This is the driver startup code executed once a WLAN device has been detected
5317
5318 \param - dev - Pointer to the underlying device
5319
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005320 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005321
5322 --------------------------------------------------------------------------*/
5323
5324int hdd_wlan_startup(struct device *dev )
5325{
5326 VOS_STATUS status;
5327 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005328 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005329 hdd_context_t *pHddCtx = NULL;
5330 v_CONTEXT_t pVosContext= NULL;
5331#ifdef WLAN_BTAMP_FEATURE
5332 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5333 WLANBAP_ConfigType btAmpConfig;
5334 hdd_config_t *pConfig;
5335#endif
5336 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005337 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005338
5339 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 /*
5341 * cfg80211: wiphy allocation
5342 */
5343 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5344
5345 if(wiphy == NULL)
5346 {
5347 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005348 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005349 }
5350
5351 pHddCtx = wiphy_priv(wiphy);
5352
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 //Initialize the adapter context to zeros.
5354 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5355
Jeff Johnson295189b2012-06-20 16:38:30 -07005356 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 hdd_prevent_suspend();
5358 pHddCtx->isLoadUnloadInProgress = TRUE;
5359
5360 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5361
5362 /*Get vos context here bcoz vos_open requires it*/
5363 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5364
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005365 if(pVosContext == NULL)
5366 {
5367 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5368 goto err_free_hdd_context;
5369 }
5370
Jeff Johnson295189b2012-06-20 16:38:30 -07005371 //Save the Global VOSS context in adapter context for future.
5372 pHddCtx->pvosContext = pVosContext;
5373
5374 //Save the adapter context in global context for future.
5375 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5376
Jeff Johnson295189b2012-06-20 16:38:30 -07005377 pHddCtx->parent_dev = dev;
5378
5379 init_completion(&pHddCtx->full_pwr_comp_var);
5380 init_completion(&pHddCtx->standby_comp_var);
5381 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005382 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005383 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005384
5385 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5386
5387 // Load all config first as TL config is needed during vos_open
5388 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5389 if(pHddCtx->cfg_ini == NULL)
5390 {
5391 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5392 goto err_free_hdd_context;
5393 }
5394
5395 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5396
5397 // Read and parse the qcom_cfg.ini file
5398 status = hdd_parse_config_ini( pHddCtx );
5399 if ( VOS_STATUS_SUCCESS != status )
5400 {
5401 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5402 __func__, WLAN_INI_FILE);
5403 goto err_config;
5404 }
5405
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305406 /* INI has been read, initialise the configuredMcastBcastFilter with
5407 * INI value as this will serve as the default value
5408 */
5409 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5410 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5411 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 /*
5413 * cfg80211: Initialization and registration ...
5414 */
5415 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5416 {
5417 hddLog(VOS_TRACE_LEVEL_FATAL,
5418 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5419 goto err_wiphy_reg;
5420 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005421
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005422 // Update VOS trace levels based upon the cfg.ini
5423 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5424 pHddCtx->cfg_ini->vosTraceEnableBAP);
5425 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5426 pHddCtx->cfg_ini->vosTraceEnableTL);
5427 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5428 pHddCtx->cfg_ini->vosTraceEnableWDI);
5429 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5430 pHddCtx->cfg_ini->vosTraceEnableHDD);
5431 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5432 pHddCtx->cfg_ini->vosTraceEnableSME);
5433 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5434 pHddCtx->cfg_ini->vosTraceEnablePE);
5435 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5436 pHddCtx->cfg_ini->vosTraceEnableWDA);
5437 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5438 pHddCtx->cfg_ini->vosTraceEnableSYS);
5439 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5440 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005441 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5442 pHddCtx->cfg_ini->vosTraceEnableSAP);
5443 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5444 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005445
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 // Update WDI trace levels based upon the cfg.ini
5447 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5448 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5449 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5450 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5451 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5452 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5453 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5454 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005455
Jeff Johnson88ba7742013-02-27 14:36:02 -08005456 if (VOS_FTM_MODE == hdd_get_conparam())
5457 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5459 {
5460 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5461 goto err_free_hdd_context;
5462 }
5463 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5464 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005466
Jeff Johnson88ba7742013-02-27 14:36:02 -08005467 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5469 {
5470 status = vos_watchdog_open(pVosContext,
5471 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5472
5473 if(!VOS_IS_STATUS_SUCCESS( status ))
5474 {
5475 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 }
5478 }
5479
5480 pHddCtx->isLogpInProgress = FALSE;
5481 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5482
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5484 if(!VOS_IS_STATUS_SUCCESS(status))
5485 {
5486 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 }
5489
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 status = vos_open( &pVosContext, 0);
5491 if ( !VOS_IS_STATUS_SUCCESS( status ))
5492 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005493 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5494 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 }
5496
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5498
5499 if ( NULL == pHddCtx->hHal )
5500 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005501 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 goto err_vosclose;
5503 }
5504
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005505 status = vos_preStart( pHddCtx->pvosContext );
5506 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5507 {
5508 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5509 goto err_vosclose;
5510 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005511
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005512 /* Note that the vos_preStart() sequence triggers the cfg download.
5513 The cfg download must occur before we update the SME config
5514 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005515 status = hdd_set_sme_config( pHddCtx );
5516
5517 if ( VOS_STATUS_SUCCESS != status )
5518 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005519 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5520 goto err_vosclose;
5521 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005522
5523 //Initialize the WMM module
5524 status = hdd_wmm_init(pHddCtx);
5525 if (!VOS_IS_STATUS_SUCCESS(status))
5526 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005527 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 goto err_vosclose;
5529 }
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 /* In the integrated architecture we update the configuration from
5532 the INI file and from NV before vOSS has been started so that
5533 the final contents are available to send down to the cCPU */
5534
5535 // Apply the cfg.ini to cfg.dat
5536 if (FALSE == hdd_update_config_dat(pHddCtx))
5537 {
5538 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5539 goto err_vosclose;
5540 }
5541
5542 // Apply the NV to cfg.dat
5543 /* Prima Update MAC address only at here */
5544 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5545 {
5546#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5547 /* There was not a valid set of MAC Addresses in NV. See if the
5548 default addresses were modified by the cfg.ini settings. If so,
5549 we'll use them, but if not, we'll autogenerate a set of MAC
5550 addresses based upon the device serial number */
5551
5552 static const v_MACADDR_t default_address =
5553 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5554 unsigned int serialno;
5555 int i;
5556
5557 serialno = wcnss_get_serial_number();
5558 if ((0 != serialno) &&
5559 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5560 sizeof(default_address))))
5561 {
5562 /* cfg.ini has the default address, invoke autogen logic */
5563
5564 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5565 bytes of the serial number that can be used to generate
5566 the other 3 bytes of the MAC address. Mask off all but
5567 the lower 3 bytes (this will also make sure we don't
5568 overflow in the next step) */
5569 serialno &= 0x00FFFFFF;
5570
5571 /* we need a unique address for each session */
5572 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5573
5574 /* autogen all addresses */
5575 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5576 {
5577 /* start with the entire default address */
5578 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5579 /* then replace the lower 3 bytes */
5580 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5581 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5582 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5583
5584 serialno++;
5585 }
5586
5587 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5588 MAC_ADDRESS_STR,
5589 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5590 }
5591 else
5592#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5593 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005594 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005595 "%s: Invalid MAC address in NV, using MAC from ini file "
5596 MAC_ADDRESS_STR, __func__,
5597 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5598 }
5599 }
5600 {
5601 eHalStatus halStatus;
5602 // Set the MAC Address
5603 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5604 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5605 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5606 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5607
5608 if (!HAL_STATUS_SUCCESS( halStatus ))
5609 {
5610 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5611 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005612 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 }
5614 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005615
5616 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5617 Note: Firmware image will be read and downloaded inside vos_start API */
5618 status = vos_start( pHddCtx->pvosContext );
5619 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5620 {
5621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5622 goto err_vosclose;
5623 }
5624
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005625 /* Exchange capability info between Host and FW and also get versioning info from FW */
5626 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005627
5628 status = hdd_post_voss_start_config( pHddCtx );
5629 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5630 {
5631 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5632 __func__);
5633 goto err_vosstop;
5634 }
5635
Jeff Johnson295189b2012-06-20 16:38:30 -07005636 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5637 {
5638 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5639 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5640 }
5641 else
5642 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5644 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5645 if (pAdapter != NULL)
5646 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305647 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005648 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305649 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5650 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5651 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005652
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305653 /* Generate the P2P Device Address. This consists of the device's
5654 * primary MAC address with the locally administered bit set.
5655 */
5656 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005657 }
5658 else
5659 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305660 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5661 if (p2p_dev_addr != NULL)
5662 {
5663 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5664 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5665 }
5666 else
5667 {
5668 hddLog(VOS_TRACE_LEVEL_FATAL,
5669 "%s: Failed to allocate mac_address for p2p_device",
5670 __func__);
5671 goto err_close_adapter;
5672 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005673 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005674
5675 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5676 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5677 if ( NULL == pP2pAdapter )
5678 {
5679 hddLog(VOS_TRACE_LEVEL_FATAL,
5680 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005681 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005682 goto err_close_adapter;
5683 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005684 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005686
5687 if( pAdapter == NULL )
5688 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5690 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005691 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005692
Jeff Johnson295189b2012-06-20 16:38:30 -07005693#ifdef WLAN_BTAMP_FEATURE
5694 vStatus = WLANBAP_Open(pVosContext);
5695 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5696 {
5697 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5698 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005699 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005700 }
5701
5702 vStatus = BSL_Init(pVosContext);
5703 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5704 {
5705 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5706 "%s: Failed to Init BSL",__func__);
5707 goto err_bap_close;
5708 }
5709 vStatus = WLANBAP_Start(pVosContext);
5710 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5711 {
5712 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5713 "%s: Failed to start TL",__func__);
5714 goto err_bap_close;
5715 }
5716
5717 pConfig = pHddCtx->cfg_ini;
5718 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5719 status = WLANBAP_SetConfig(&btAmpConfig);
5720
5721#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005722
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005723#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5724 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5725 {
5726 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5727 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5728 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5729 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5730 }
5731#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005732#ifdef FEATURE_WLAN_SCAN_PNO
5733 /*SME must send channel update configuration to RIVA*/
5734 sme_UpdateChannelConfig(pHddCtx->hHal);
5735#endif
5736
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 /* Register with platform driver as client for Suspend/Resume */
5738 status = hddRegisterPmOps(pHddCtx);
5739 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5740 {
5741 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5742#ifdef WLAN_BTAMP_FEATURE
5743 goto err_bap_stop;
5744#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005745 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005746#endif //WLAN_BTAMP_FEATURE
5747 }
5748
5749 /* Register TM level change handler function to the platform */
5750 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5751 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5752 {
5753 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5754 goto err_unregister_pmops;
5755 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005756
5757 /* register for riva power on lock to platform driver */
5758 if (req_riva_power_on_lock("wlan"))
5759 {
5760 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5761 __func__);
5762 goto err_unregister_pmops;
5763 }
5764
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 // register net device notifier for device change notification
5766 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5767
5768 if(ret < 0)
5769 {
5770 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5771 goto err_free_power_on_lock;
5772 }
5773
5774 //Initialize the nlink service
5775 if(nl_srv_init() != 0)
5776 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305777 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 goto err_reg_netdev;
5779 }
5780
5781 //Initialize the BTC service
5782 if(btc_activate_service(pHddCtx) != 0)
5783 {
5784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5785 goto err_nl_srv;
5786 }
5787
5788#ifdef PTT_SOCK_SVC_ENABLE
5789 //Initialize the PTT service
5790 if(ptt_sock_activate_svc(pHddCtx) != 0)
5791 {
5792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5793 goto err_nl_srv;
5794 }
5795#endif
5796
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005800 /* Action frame registered in one adapter which will
5801 * applicable to all interfaces
5802 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005803 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005805
5806 mutex_init(&pHddCtx->sap_lock);
5807
5808 pHddCtx->isLoadUnloadInProgress = FALSE;
5809
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005810#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005811#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5812 /* Initialize the wake lcok */
5813 wake_lock_init(&pHddCtx->rx_wake_lock,
5814 WAKE_LOCK_SUSPEND,
5815 "qcom_rx_wakelock");
5816#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005817 /* Initialize the wake lcok */
5818 wake_lock_init(&pHddCtx->sap_wake_lock,
5819 WAKE_LOCK_SUSPEND,
5820 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005821#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005822
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005823 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5824 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005825
5826 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5827 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005828
5829 // Initialize the restart logic
5830 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305831
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 goto success;
5833
5834err_nl_srv:
5835 nl_srv_exit();
5836
5837err_reg_netdev:
5838 unregister_netdevice_notifier(&hdd_netdev_notifier);
5839
5840err_free_power_on_lock:
5841 free_riva_power_on_lock("wlan");
5842
5843err_unregister_pmops:
5844 hddDevTmUnregisterNotifyCallback(pHddCtx);
5845 hddDeregisterPmOps(pHddCtx);
5846
5847#ifdef WLAN_BTAMP_FEATURE
5848err_bap_stop:
5849 WLANBAP_Stop(pVosContext);
5850#endif
5851
5852#ifdef WLAN_BTAMP_FEATURE
5853err_bap_close:
5854 WLANBAP_Close(pVosContext);
5855#endif
5856
Jeff Johnson295189b2012-06-20 16:38:30 -07005857err_close_adapter:
5858 hdd_close_all_adapters( pHddCtx );
5859
5860err_vosstop:
5861 vos_stop(pVosContext);
5862
5863err_vosclose:
5864 status = vos_sched_close( pVosContext );
5865 if (!VOS_IS_STATUS_SUCCESS(status)) {
5866 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5867 "%s: Failed to close VOSS Scheduler", __func__);
5868 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5869 }
5870 vos_close(pVosContext );
5871
Jeff Johnson295189b2012-06-20 16:38:30 -07005872err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005873 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005874
5875err_wdclose:
5876 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5877 vos_watchdog_close(pVosContext);
5878
Jeff Johnson295189b2012-06-20 16:38:30 -07005879err_wiphy_reg:
5880 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005881
5882err_config:
5883 kfree(pHddCtx->cfg_ini);
5884 pHddCtx->cfg_ini= NULL;
5885
5886err_free_hdd_context:
5887 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 wiphy_free(wiphy) ;
5889 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 VOS_BUG(1);
5891
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005892 if (hdd_is_ssr_required())
5893 {
5894 /* WDI timeout had happened during load, so SSR is needed here */
5895 subsystem_restart("wcnss");
5896 msleep(5000);
5897 }
5898 hdd_set_ssr_required (VOS_FALSE);
5899
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005900 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005901
5902success:
5903 EXIT();
5904 return 0;
5905}
5906
5907/**---------------------------------------------------------------------------
5908
Jeff Johnson32d95a32012-09-10 13:15:23 -07005909 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005910
Jeff Johnson32d95a32012-09-10 13:15:23 -07005911 This is the driver entry point - called in different timeline depending
5912 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005913
5914 \param - None
5915
5916 \return - 0 for success, non zero for failure
5917
5918 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005919static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005920{
5921 VOS_STATUS status;
5922 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005923 struct device *dev = NULL;
5924 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005925#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5926 int max_retries = 0;
5927#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005928
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305929#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5930 vos_wconn_trace_init();
5931#endif
5932
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 ENTER();
5934
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005935#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005936 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005937#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005938
5939 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5940 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5941
5942 //Power Up Libra WLAN card first if not already powered up
5943 status = vos_chipPowerUp(NULL,NULL,NULL);
5944 if (!VOS_IS_STATUS_SUCCESS(status))
5945 {
5946 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5947 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005948 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 }
5950
Jeff Johnson295189b2012-06-20 16:38:30 -07005951#ifdef ANI_BUS_TYPE_PCI
5952
5953 dev = wcnss_wlan_get_device();
5954
5955#endif // ANI_BUS_TYPE_PCI
5956
5957#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005958
5959#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5960 /* wait until WCNSS driver downloads NV */
5961 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5962 msleep(1000);
5963 }
5964 if (max_retries >= 5) {
5965 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5966 return -ENODEV;
5967 }
5968#endif
5969
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 dev = wcnss_wlan_get_device();
5971#endif // ANI_BUS_TYPE_PLATFORM
5972
5973
5974 do {
5975 if (NULL == dev) {
5976 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5977 ret_status = -1;
5978 break;
5979 }
5980
5981#ifdef MEMORY_DEBUG
5982 vos_mem_init();
5983#endif
5984
5985#ifdef TIMER_MANAGER
5986 vos_timer_manager_init();
5987#endif
5988
5989 /* Preopen VOSS so that it is ready to start at least SAL */
5990 status = vos_preOpen(&pVosContext);
5991
5992 if (!VOS_IS_STATUS_SUCCESS(status))
5993 {
5994 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5995 ret_status = -1;
5996 break;
5997 }
5998
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005999#ifndef MODULE
6000 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6001 */
6002 hdd_set_conparam((v_UINT_t)con_mode);
6003#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006004
6005 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006006 if (hdd_wlan_startup(dev))
6007 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006009 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 vos_preClose( &pVosContext );
6011 ret_status = -1;
6012 break;
6013 }
6014
6015 /* Cancel the vote for XO Core ON
6016 * This is done here for safety purposes in case we re-initialize without turning
6017 * it OFF in any error scenario.
6018 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006019 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006021 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006022 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6023 {
6024 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6025 " Power consumed will be high\n");
6026 }
6027 } while (0);
6028
6029 if (0 != ret_status)
6030 {
6031 //Assert Deep sleep signal now to put Libra HW in lowest power state
6032 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6033 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6034
6035 //Vote off any PMIC voltage supplies
6036 vos_chipPowerDown(NULL, NULL, NULL);
6037#ifdef TIMER_MANAGER
6038 vos_timer_exit();
6039#endif
6040#ifdef MEMORY_DEBUG
6041 vos_mem_exit();
6042#endif
6043
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006044#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006046#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6048 }
6049 else
6050 {
6051 //Send WLAN UP indication to Nlink Service
6052 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6053
6054 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6055
6056 }
6057
6058 EXIT();
6059
6060 return ret_status;
6061}
6062
Jeff Johnson32d95a32012-09-10 13:15:23 -07006063/**---------------------------------------------------------------------------
6064
6065 \brief hdd_module_init() - Init Function
6066
6067 This is the driver entry point (invoked when module is loaded using insmod)
6068
6069 \param - None
6070
6071 \return - 0 for success, non zero for failure
6072
6073 --------------------------------------------------------------------------*/
6074#ifdef MODULE
6075static int __init hdd_module_init ( void)
6076{
6077 return hdd_driver_init();
6078}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006079#else /* #ifdef MODULE */
6080static int __init hdd_module_init ( void)
6081{
6082 /* Driver initialization is delayed to fwpath_changed_handler */
6083 return 0;
6084}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006085#endif /* #ifdef MODULE */
6086
Jeff Johnson295189b2012-06-20 16:38:30 -07006087
6088/**---------------------------------------------------------------------------
6089
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006090 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006091
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006092 This is the driver exit point (invoked when module is unloaded using rmmod
6093 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006094
6095 \param - None
6096
6097 \return - None
6098
6099 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006100static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006101{
6102 hdd_context_t *pHddCtx = NULL;
6103 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006104
6105 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6106
6107 //Get the global vos context
6108 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6109
6110 if(!pVosContext)
6111 {
6112 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6113 goto done;
6114 }
6115
6116 //Get the HDD context.
6117 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6118
6119 if(!pHddCtx)
6120 {
6121 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6122 }
6123 else
6124 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006125 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006126 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006127 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6128 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006129 }
6130
6131 pHddCtx->isLoadUnloadInProgress = TRUE;
6132 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6133
6134 //Do all the cleanup before deregistering the driver
6135 hdd_wlan_exit(pHddCtx);
6136 }
6137
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 vos_preClose( &pVosContext );
6139
6140#ifdef TIMER_MANAGER
6141 vos_timer_exit();
6142#endif
6143#ifdef MEMORY_DEBUG
6144 vos_mem_exit();
6145#endif
6146
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306147#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6148 vos_wconn_trace_exit();
6149#endif
6150
Jeff Johnson295189b2012-06-20 16:38:30 -07006151done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006152#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006155 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6156}
6157
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006158/**---------------------------------------------------------------------------
6159
6160 \brief hdd_module_exit() - Exit function
6161
6162 This is the driver exit point (invoked when module is unloaded using rmmod)
6163
6164 \param - None
6165
6166 \return - None
6167
6168 --------------------------------------------------------------------------*/
6169static void __exit hdd_module_exit(void)
6170{
6171 hdd_driver_exit();
6172}
6173
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006174#ifdef MODULE
6175static int fwpath_changed_handler(const char *kmessage,
6176 struct kernel_param *kp)
6177{
Jeff Johnson76052702013-04-16 13:55:05 -07006178 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006179}
6180
6181static int con_mode_handler(const char *kmessage,
6182 struct kernel_param *kp)
6183{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006184 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006185}
6186#else /* #ifdef MODULE */
6187/**---------------------------------------------------------------------------
6188
Jeff Johnson76052702013-04-16 13:55:05 -07006189 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006190
Jeff Johnson76052702013-04-16 13:55:05 -07006191 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006192 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006193 - invoked when module parameter fwpath is modified from userspace to signal
6194 initializing the WLAN driver or when con_mode is modified from userspace
6195 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006196
6197 \return - 0 for success, non zero for failure
6198
6199 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006200static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006201{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006202 int ret_status;
6203
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006204 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006205 ret_status = hdd_driver_init();
6206 wlan_hdd_inited = ret_status ? 0 : 1;
6207 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006208 }
6209
6210 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006211
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006212 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006213
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006214 ret_status = hdd_driver_init();
6215 wlan_hdd_inited = ret_status ? 0 : 1;
6216 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006217}
6218
Jeff Johnson295189b2012-06-20 16:38:30 -07006219/**---------------------------------------------------------------------------
6220
Jeff Johnson76052702013-04-16 13:55:05 -07006221 \brief fwpath_changed_handler() - Handler Function
6222
6223 Handle changes to the fwpath parameter
6224
6225 \return - 0 for success, non zero for failure
6226
6227 --------------------------------------------------------------------------*/
6228static int fwpath_changed_handler(const char *kmessage,
6229 struct kernel_param *kp)
6230{
6231 int ret;
6232
6233 ret = param_set_copystring(kmessage, kp);
6234 if (0 == ret)
6235 ret = kickstart_driver();
6236 return ret;
6237}
6238
6239/**---------------------------------------------------------------------------
6240
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006241 \brief con_mode_handler() -
6242
6243 Handler function for module param con_mode when it is changed by userspace
6244 Dynamically linked - do nothing
6245 Statically linked - exit and init driver, as in rmmod and insmod
6246
Jeff Johnson76052702013-04-16 13:55:05 -07006247 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006248
Jeff Johnson76052702013-04-16 13:55:05 -07006249 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006250
6251 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006252static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006253{
Jeff Johnson76052702013-04-16 13:55:05 -07006254 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006255
Jeff Johnson76052702013-04-16 13:55:05 -07006256 ret = param_set_int(kmessage, kp);
6257 if (0 == ret)
6258 ret = kickstart_driver();
6259 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006260}
6261#endif /* #ifdef MODULE */
6262
6263/**---------------------------------------------------------------------------
6264
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 \brief hdd_get_conparam() -
6266
6267 This is the driver exit point (invoked when module is unloaded using rmmod)
6268
6269 \param - None
6270
6271 \return - tVOS_CON_MODE
6272
6273 --------------------------------------------------------------------------*/
6274tVOS_CON_MODE hdd_get_conparam ( void )
6275{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006276#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006277 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006278#else
6279 return (tVOS_CON_MODE)curr_con_mode;
6280#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006281}
6282void hdd_set_conparam ( v_UINT_t newParam )
6283{
6284 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006285#ifndef MODULE
6286 curr_con_mode = con_mode;
6287#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006288}
6289/**---------------------------------------------------------------------------
6290
6291 \brief hdd_softap_sta_deauth() - function
6292
6293 This to take counter measure to handle deauth req from HDD
6294
6295 \param - pAdapter - Pointer to the HDD
6296
6297 \param - enable - boolean value
6298
6299 \return - None
6300
6301 --------------------------------------------------------------------------*/
6302
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006303VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006304{
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006306 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006307
6308 ENTER();
6309
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306310 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006311
6312 //Ignore request to deauth bcmc station
6313 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006314 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006315
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006316 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006317
6318 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006319 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006320}
6321
6322/**---------------------------------------------------------------------------
6323
6324 \brief hdd_softap_sta_disassoc() - function
6325
6326 This to take counter measure to handle deauth req from HDD
6327
6328 \param - pAdapter - Pointer to the HDD
6329
6330 \param - enable - boolean value
6331
6332 \return - None
6333
6334 --------------------------------------------------------------------------*/
6335
6336void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6337{
6338 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6339
6340 ENTER();
6341
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306342 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006343
6344 //Ignore request to disassoc bcmc station
6345 if( pDestMacAddress[0] & 0x1 )
6346 return;
6347
6348 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6349}
6350
6351void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6352{
6353 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6354
6355 ENTER();
6356
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306357 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006358
6359 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6360}
6361
Jeff Johnson295189b2012-06-20 16:38:30 -07006362/**---------------------------------------------------------------------------
6363 *
6364 * \brief hdd_get__concurrency_mode() -
6365 *
6366 *
6367 * \param - None
6368 *
6369 * \return - CONCURRENCY MODE
6370 *
6371 * --------------------------------------------------------------------------*/
6372tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6373{
6374 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6375 hdd_context_t *pHddCtx;
6376
6377 if (NULL != pVosContext)
6378 {
6379 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6380 if (NULL != pHddCtx)
6381 {
6382 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6383 }
6384 }
6385
6386 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006387 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 return VOS_STA;
6389}
6390
6391/* Decide whether to allow/not the apps power collapse.
6392 * Allow apps power collapse if we are in connected state.
6393 * if not, allow only if we are in IMPS */
6394v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6395{
6396 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006397 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006398 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006399 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6400 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6401 hdd_adapter_t *pAdapter = NULL;
6402 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006403 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006404
Jeff Johnson295189b2012-06-20 16:38:30 -07006405 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6406 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006407
Yathish9f22e662012-12-10 14:21:35 -08006408 concurrent_state = hdd_get_concurrency_mode();
6409
6410#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6411 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6412 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6413 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6414 return TRUE;
6415#endif
6416
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 /*loop through all adapters. TBD fix for Concurrency */
6418 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6419 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6420 {
6421 pAdapter = pAdapterNode->pAdapter;
6422 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6423 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6424 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006425 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006426 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006427 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006428 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6429 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006430 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006431 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006432 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6433 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006434 return FALSE;
6435 }
6436 }
6437 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6438 pAdapterNode = pNext;
6439 }
6440 return TRUE;
6441}
6442
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006443/* Decides whether to send suspend notification to Riva
6444 * if any adapter is in BMPS; then it is required */
6445v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6446{
6447 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6448 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6449
6450 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6451 {
6452 return TRUE;
6453 }
6454 return FALSE;
6455}
6456
Jeff Johnson295189b2012-06-20 16:38:30 -07006457void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6458{
6459 switch(mode)
6460 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006461 case VOS_STA_MODE:
6462 case VOS_P2P_CLIENT_MODE:
6463 case VOS_P2P_GO_MODE:
6464 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006465 pHddCtx->concurrency_mode |= (1 << mode);
6466 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 break;
6468 default:
6469 break;
6470
6471 }
6472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6473 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6474}
6475
6476
6477void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6478{
6479 switch(mode)
6480 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006481 case VOS_STA_MODE:
6482 case VOS_P2P_CLIENT_MODE:
6483 case VOS_P2P_GO_MODE:
6484 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 pHddCtx->no_of_sessions[mode]--;
6486 if (!(pHddCtx->no_of_sessions[mode]))
6487 pHddCtx->concurrency_mode &= (~(1 << mode));
6488 break;
6489 default:
6490 break;
6491 }
6492 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6493 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6494}
6495
Jeff Johnsone7245742012-09-05 17:12:55 -07006496/**---------------------------------------------------------------------------
6497 *
6498 * \brief wlan_hdd_restart_init
6499 *
6500 * This function initalizes restart timer/flag. An internal function.
6501 *
6502 * \param - pHddCtx
6503 *
6504 * \return - None
6505 *
6506 * --------------------------------------------------------------------------*/
6507
6508static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6509{
6510 /* Initialize */
6511 pHddCtx->hdd_restart_retries = 0;
6512 atomic_set(&pHddCtx->isRestartInProgress, 0);
6513 vos_timer_init(&pHddCtx->hdd_restart_timer,
6514 VOS_TIMER_TYPE_SW,
6515 wlan_hdd_restart_timer_cb,
6516 pHddCtx);
6517}
6518/**---------------------------------------------------------------------------
6519 *
6520 * \brief wlan_hdd_restart_deinit
6521 *
6522 * This function cleans up the resources used. An internal function.
6523 *
6524 * \param - pHddCtx
6525 *
6526 * \return - None
6527 *
6528 * --------------------------------------------------------------------------*/
6529
6530static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6531{
6532
6533 VOS_STATUS vos_status;
6534 /* Block any further calls */
6535 atomic_set(&pHddCtx->isRestartInProgress, 1);
6536 /* Cleanup */
6537 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6538 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006539 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006540 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6541 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006542 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006543
6544}
6545
6546/**---------------------------------------------------------------------------
6547 *
6548 * \brief wlan_hdd_framework_restart
6549 *
6550 * This function uses a cfg80211 API to start a framework initiated WLAN
6551 * driver module unload/load.
6552 *
6553 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6554 *
6555 *
6556 * \param - pHddCtx
6557 *
6558 * \return - VOS_STATUS_SUCCESS: Success
6559 * VOS_STATUS_E_EMPTY: Adapter is Empty
6560 * VOS_STATUS_E_NOMEM: No memory
6561
6562 * --------------------------------------------------------------------------*/
6563
6564static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6565{
6566 VOS_STATUS status = VOS_STATUS_SUCCESS;
6567 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006568 int len = (sizeof (struct ieee80211_mgmt));
6569 struct ieee80211_mgmt *mgmt = NULL;
6570
6571 /* Prepare the DEAUTH managment frame with reason code */
6572 mgmt = kzalloc(len, GFP_KERNEL);
6573 if(mgmt == NULL)
6574 {
6575 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6576 "%s: memory allocation failed (%d bytes)", __func__, len);
6577 return VOS_STATUS_E_NOMEM;
6578 }
6579 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006580
6581 /* Iterate over all adapters/devices */
6582 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6583 do
6584 {
6585 if( (status == VOS_STATUS_SUCCESS) &&
6586 pAdapterNode &&
6587 pAdapterNode->pAdapter)
6588 {
6589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6590 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6591 pAdapterNode->pAdapter->dev->name,
6592 pAdapterNode->pAdapter->device_mode,
6593 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006594 /*
6595 * CFG80211 event to restart the driver
6596 *
6597 * 'cfg80211_send_unprot_deauth' sends a
6598 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6599 * of SME(Linux Kernel) state machine.
6600 *
6601 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6602 * the driver.
6603 *
6604 */
6605
6606 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006607 }
6608 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6609 pAdapterNode = pNext;
6610 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6611
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006612
6613 /* Free the allocated management frame */
6614 kfree(mgmt);
6615
Jeff Johnsone7245742012-09-05 17:12:55 -07006616 /* Retry until we unload or reach max count */
6617 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6618 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6619
6620 return status;
6621
6622}
6623/**---------------------------------------------------------------------------
6624 *
6625 * \brief wlan_hdd_restart_timer_cb
6626 *
6627 * Restart timer callback. An internal function.
6628 *
6629 * \param - User data:
6630 *
6631 * \return - None
6632 *
6633 * --------------------------------------------------------------------------*/
6634
6635void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6636{
6637 hdd_context_t *pHddCtx = usrDataForCallback;
6638 wlan_hdd_framework_restart(pHddCtx);
6639 return;
6640
6641}
6642
6643
6644/**---------------------------------------------------------------------------
6645 *
6646 * \brief wlan_hdd_restart_driver
6647 *
6648 * This function sends an event to supplicant to restart the WLAN driver.
6649 *
6650 * This function is called from vos_wlanRestart.
6651 *
6652 * \param - pHddCtx
6653 *
6654 * \return - VOS_STATUS_SUCCESS: Success
6655 * VOS_STATUS_E_EMPTY: Adapter is Empty
6656 * VOS_STATUS_E_ALREADY: Request already in progress
6657
6658 * --------------------------------------------------------------------------*/
6659VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6660{
6661 VOS_STATUS status = VOS_STATUS_SUCCESS;
6662
6663 /* A tight check to make sure reentrancy */
6664 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6665 {
6666 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6667 "%s: WLAN restart is already in progress", __func__);
6668
6669 return VOS_STATUS_E_ALREADY;
6670 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006671 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006672#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006673 wcnss_reset_intr();
6674#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006675
Jeff Johnsone7245742012-09-05 17:12:55 -07006676 return status;
6677}
6678
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006679/*
6680 * API to find if there is any STA or P2P-Client is connected
6681 */
6682VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6683{
6684 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6685}
Jeff Johnsone7245742012-09-05 17:12:55 -07006686
Jeff Johnson295189b2012-06-20 16:38:30 -07006687//Register the module init/exit functions
6688module_init(hdd_module_init);
6689module_exit(hdd_module_exit);
6690
6691MODULE_LICENSE("Dual BSD/GPL");
6692MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6693MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6694
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006695module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6696 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006697
Jeff Johnson76052702013-04-16 13:55:05 -07006698module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006699 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);