blob: c02fb76ce99667e78335b31365ff23fdccfc99c0 [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
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302002#ifdef WLAN_FEATURE_PACKET_FILTERING
2003 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2004 {
2005 tANI_U8 filterType = 0;
2006 tANI_U8 *value = command;
2007
2008 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2009 value = value + 22;
2010
2011 /* Convert the value from ascii to integer */
2012 ret = kstrtou8(value, 10, &filterType);
2013 if (ret < 0)
2014 {
2015 /* If the input value is greater than max value of datatype,
2016 * then also kstrtou8 fails
2017 */
2018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2019 "%s: kstrtou8 failed range ", __func__);
2020 ret = -EINVAL;
2021 goto exit;
2022 }
2023
2024 if (filterType != 0 && filterType != 1)
2025 {
2026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2027 "%s: Accepted Values are 0 and 1 ", __func__);
2028 ret = -EINVAL;
2029 goto exit;
2030 }
2031 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2032 pAdapter->sessionId);
2033 }
2034#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002035 else {
2036 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2037 __func__, command);
2038 }
2039
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 }
2041exit:
2042 if (command)
2043 {
2044 kfree(command);
2045 }
2046 return ret;
2047}
2048
Srinivas Girigowdade697412013-02-14 16:31:48 -08002049#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2050void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2051{
2052 eCsrBand band = -1;
2053 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2054 switch (band)
2055 {
2056 case eCSR_BAND_ALL:
2057 *pBand = WLAN_HDD_UI_BAND_AUTO;
2058 break;
2059
2060 case eCSR_BAND_24:
2061 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2062 break;
2063
2064 case eCSR_BAND_5G:
2065 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2066 break;
2067
2068 default:
2069 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2070 *pBand = -1;
2071 break;
2072 }
2073}
2074
2075/**---------------------------------------------------------------------------
2076
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002077 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2078
2079 This function parses the send action frame data passed in the format
2080 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2081
2082 \param - pValue Pointer to input country code revision
2083 \param - pTargetApBssid Pointer to target Ap bssid
2084 \param - pChannel Pointer to the Target AP channel
2085 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2086 \param - pBuf Pointer to data
2087 \param - pBufLen Pointer to data length
2088
2089 \return - 0 for success non-zero for failure
2090
2091 --------------------------------------------------------------------------*/
2092VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2093 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2094{
2095 tANI_U8 *inPtr = pValue;
2096 tANI_U8 *dataEnd;
2097 int tempInt;
2098 int j = 0;
2099 int i = 0;
2100 int v = 0;
2101 tANI_U8 tempBuf[32];
2102 tANI_U8 tempByte = 0;
2103
2104 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2105 /*no argument after the command*/
2106 if (NULL == inPtr)
2107 {
2108 return -EINVAL;
2109 }
2110
2111 /*no space after the command*/
2112 else if (SPACE_ASCII_VALUE != *inPtr)
2113 {
2114 return -EINVAL;
2115 }
2116
2117 /*removing empty spaces*/
2118 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2119
2120 /*no argument followed by spaces*/
2121 if ('\0' == *inPtr)
2122 {
2123 return -EINVAL;
2124 }
2125
2126 /*getting the first argument ie the target AP bssid */
2127 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2128 {
2129 return -EINVAL;
2130 }
2131 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2132 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2133 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2134
2135 /* point to the next argument */
2136 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2137 /*no argument after the command*/
2138 if (NULL == inPtr) return -EINVAL;
2139
2140 /*removing empty spaces*/
2141 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2142
2143 /*no argument followed by spaces*/
2144 if ('\0' == *inPtr)
2145 {
2146 return -EINVAL;
2147 }
2148
2149 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002150 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002151 v = kstrtos32(tempBuf, 10, &tempInt);
2152 if ( v < 0) return -EINVAL;
2153
2154 *pChannel = tempInt;
2155
2156 /* point to the next argument */
2157 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2158 /*no argument after the command*/
2159 if (NULL == inPtr) return -EINVAL;
2160 /*removing empty spaces*/
2161 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2162
2163 /*no argument followed by spaces*/
2164 if ('\0' == *inPtr)
2165 {
2166 return -EINVAL;
2167 }
2168
2169 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002170 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002171 v = kstrtos32(tempBuf, 10, &tempInt);
2172 if ( v < 0) return -EINVAL;
2173
2174 *pDwellTime = tempInt;
2175
2176 /* point to the next argument */
2177 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2178 /*no argument after the command*/
2179 if (NULL == inPtr) return -EINVAL;
2180 /*removing empty spaces*/
2181 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2182
2183 /*no argument followed by spaces*/
2184 if ('\0' == *inPtr)
2185 {
2186 return -EINVAL;
2187 }
2188
2189 /* find the length of data */
2190 dataEnd = inPtr;
2191 while(('\0' != *dataEnd) )
2192 {
2193 dataEnd++;
2194 ++(*pBufLen);
2195 }
2196 if ( *pBufLen <= 0) return -EINVAL;
2197
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002198 /* Allocate the number of bytes based on the number of input characters
2199 whether it is even or odd.
2200 if the number of input characters are even, then we need N/2 byte.
2201 if the number of input characters are odd, then we need do (N+1)/2 to
2202 compensate rounding off.
2203 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2204 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2205 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002206 if (NULL == *pBuf)
2207 {
2208 hddLog(VOS_TRACE_LEVEL_FATAL,
2209 "%s: vos_mem_alloc failed ", __func__);
2210 return -EINVAL;
2211 }
2212
2213 /* the buffer received from the upper layer is character buffer,
2214 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2215 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2216 and f0 in 3rd location */
2217 for (i = 0, j = 0; j < *pBufLen; j += 2)
2218 {
2219 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2220 (*pBuf)[i++] = tempByte;
2221 }
2222 *pBufLen = i;
2223 return VOS_STATUS_SUCCESS;
2224}
2225
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002226/**---------------------------------------------------------------------------
2227
Srinivas Girigowdade697412013-02-14 16:31:48 -08002228 \brief hdd_parse_countryrev() - HDD Parse country code revision
2229
2230 This function parses the country code revision passed in the format
2231 SETCOUNTRYREV<space><Country code><space>revision
2232
2233 \param - pValue Pointer to input country code revision
2234 \param - pCountryCode Pointer to local output array to record country code
2235 \param - pRevision Pointer to store revision integer number
2236
2237 \return - 0 for success non-zero for failure
2238
2239 --------------------------------------------------------------------------*/
2240VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2241{
2242 tANI_U8 *inPtr = pValue;
2243 int tempInt;
2244
2245 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2246 /*no argument after the command*/
2247 if (NULL == inPtr)
2248 {
2249 return -EINVAL;
2250 }
2251
2252 /*no space after the command*/
2253 else if (SPACE_ASCII_VALUE != *inPtr)
2254 {
2255 return -EINVAL;
2256 }
2257
2258 /*removing empty spaces*/
2259 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2260
2261 /*no argument followed by spaces*/
2262 if ('\0' == *inPtr)
2263 {
2264 return -EINVAL;
2265 }
2266
2267 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002268 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002269
2270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2271 "Country code is : %s", pCountryCode);
2272
2273 /*inPtr pointing to the beginning of first space after country code */
2274 inPtr = strpbrk( inPtr, " " );
2275 /*no revision number after the country code argument */
2276 if (NULL == inPtr)
2277 {
2278 return -EINVAL;
2279 }
2280
2281 inPtr++;
2282
2283 /*removing empty space*/
2284 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2285
2286 /*no channel list after the number of channels argument and spaces*/
2287 if (0 == strncmp(pCountryCode, "KR", 2))
2288 {
2289 if ('\0' == *inPtr)
2290 {
2291 return -EINVAL;
2292 }
2293
2294 sscanf(inPtr, "%d", &tempInt);
2295 *pRevision = tempInt;
2296 }
2297 else
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2300 "Revision input is required only for Country KR");
2301 return -EINVAL;
2302 }
2303 return VOS_STATUS_SUCCESS;
2304}
2305
2306/**---------------------------------------------------------------------------
2307
2308 \brief hdd_parse_channellist() - HDD Parse channel list
2309
2310 This function parses the channel list passed in the format
2311 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002312 if the Number of channels (N) does not match with the actual number of channels passed
2313 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2314 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2315 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2316 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002317
2318 \param - pValue Pointer to input channel list
2319 \param - ChannelList Pointer to local output array to record channel list
2320 \param - pNumChannels Pointer to number of roam scan channels
2321
2322 \return - 0 for success non-zero for failure
2323
2324 --------------------------------------------------------------------------*/
2325VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2326{
2327 tANI_U8 *inPtr = pValue;
2328 int tempInt;
2329 int j = 0;
2330 int v = 0;
2331 char buf[32];
2332
2333 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2334 /*no argument after the command*/
2335 if (NULL == inPtr)
2336 {
2337 return -EINVAL;
2338 }
2339
2340 /*no space after the command*/
2341 else if (SPACE_ASCII_VALUE != *inPtr)
2342 {
2343 return -EINVAL;
2344 }
2345
2346 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002347 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002348
2349 /*no argument followed by spaces*/
2350 if ('\0' == *inPtr)
2351 {
2352 return -EINVAL;
2353 }
2354
2355 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002356 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002357 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002358 if ((v < 0) ||
2359 (tempInt <= 0) ||
2360 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2361 {
2362 return -EINVAL;
2363 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002364
2365 *pNumChannels = tempInt;
2366
2367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2368 "Number of channels are: %d", *pNumChannels);
2369
2370 for (j = 0; j < (*pNumChannels); j++)
2371 {
2372 /*inPtr pointing to the beginning of first space after number of channels*/
2373 inPtr = strpbrk( inPtr, " " );
2374 /*no channel list after the number of channels argument*/
2375 if (NULL == inPtr)
2376 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002377 if (0 != j)
2378 {
2379 *pNumChannels = j;
2380 return VOS_STATUS_SUCCESS;
2381 }
2382 else
2383 {
2384 return -EINVAL;
2385 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002386 }
2387
2388 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002389 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002390
2391 /*no channel list after the number of channels argument and spaces*/
2392 if ( '\0' == *inPtr )
2393 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002394 if (0 != j)
2395 {
2396 *pNumChannels = j;
2397 return VOS_STATUS_SUCCESS;
2398 }
2399 else
2400 {
2401 return -EINVAL;
2402 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002403 }
2404
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002405 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002406 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002407 if ((v < 0) ||
2408 (tempInt <= 0) ||
2409 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2410 {
2411 return -EINVAL;
2412 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002413 pChannelList[j] = tempInt;
2414
2415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2416 "Channel %d added to preferred channel list",
2417 pChannelList[j] );
2418 }
2419
Srinivas Girigowdade697412013-02-14 16:31:48 -08002420 return VOS_STATUS_SUCCESS;
2421}
2422
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002423
2424/**---------------------------------------------------------------------------
2425
2426 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2427
2428 This function parses the reasoc command data passed in the format
2429 REASSOC<space><bssid><space><channel>
2430
2431 \param - pValue Pointer to input country code revision
2432 \param - pTargetApBssid Pointer to target Ap bssid
2433 \param - pChannel Pointer to the Target AP channel
2434
2435 \return - 0 for success non-zero for failure
2436
2437 --------------------------------------------------------------------------*/
2438VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2439{
2440 tANI_U8 *inPtr = pValue;
2441 int tempInt;
2442 int v = 0;
2443 tANI_U8 tempBuf[32];
2444
2445 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2446 /*no argument after the command*/
2447 if (NULL == inPtr)
2448 {
2449 return -EINVAL;
2450 }
2451
2452 /*no space after the command*/
2453 else if (SPACE_ASCII_VALUE != *inPtr)
2454 {
2455 return -EINVAL;
2456 }
2457
2458 /*removing empty spaces*/
2459 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2460
2461 /*no argument followed by spaces*/
2462 if ('\0' == *inPtr)
2463 {
2464 return -EINVAL;
2465 }
2466
2467 /*getting the first argument ie the target AP bssid */
2468 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2469 {
2470 return -EINVAL;
2471 }
2472 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2473 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2474 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2475
2476 /* point to the next argument */
2477 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2478 /*no argument after the command*/
2479 if (NULL == inPtr) return -EINVAL;
2480
2481 /*removing empty spaces*/
2482 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2483
2484 /*no argument followed by spaces*/
2485 if ('\0' == *inPtr)
2486 {
2487 return -EINVAL;
2488 }
2489
2490 /*getting the next argument ie the channel number */
2491 sscanf(inPtr, "%s ", tempBuf);
2492 v = kstrtos32(tempBuf, 10, &tempInt);
2493 if ( v < 0) return -EINVAL;
2494
2495 *pChannel = tempInt;
2496 return VOS_STATUS_SUCCESS;
2497}
2498
2499#endif
2500
Jeff Johnson295189b2012-06-20 16:38:30 -07002501/**---------------------------------------------------------------------------
2502
2503 \brief hdd_open() - HDD Open function
2504
2505 This is called in response to ifconfig up
2506
2507 \param - dev Pointer to net_device structure
2508
2509 \return - 0 for success non-zero for failure
2510
2511 --------------------------------------------------------------------------*/
2512int hdd_open (struct net_device *dev)
2513{
2514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2515 hdd_context_t *pHddCtx;
2516 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2517 VOS_STATUS status;
2518 v_BOOL_t in_standby = TRUE;
2519
2520 if (NULL == pAdapter)
2521 {
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002523 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002524 return -ENODEV;
2525 }
2526
2527 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2528 if (NULL == pHddCtx)
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002531 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002532 return -ENODEV;
2533 }
2534
2535 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2536 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2537 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002538 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2539 {
2540 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302541 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002542 in_standby = FALSE;
2543 break;
2544 }
2545 else
2546 {
2547 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2548 pAdapterNode = pNext;
2549 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 }
2551
2552 if (TRUE == in_standby)
2553 {
2554 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2555 {
2556 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2557 "wlan out of power save", __func__);
2558 return -EINVAL;
2559 }
2560 }
2561
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002562 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2564 {
2565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002566 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 /* Enable TX queues only when we are connected */
2568 netif_tx_start_all_queues(dev);
2569 }
2570
2571 return 0;
2572}
2573
2574int hdd_mon_open (struct net_device *dev)
2575{
2576 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2577
2578 if(pAdapter == NULL) {
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__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002581 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002582 }
2583
2584 netif_start_queue(dev);
2585
2586 return 0;
2587}
2588/**---------------------------------------------------------------------------
2589
2590 \brief hdd_stop() - HDD stop function
2591
2592 This is called in response to ifconfig down
2593
2594 \param - dev Pointer to net_device structure
2595
2596 \return - 0 for success non-zero for failure
2597
2598 --------------------------------------------------------------------------*/
2599
2600int hdd_stop (struct net_device *dev)
2601{
2602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2603 hdd_context_t *pHddCtx;
2604 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2605 VOS_STATUS status;
2606 v_BOOL_t enter_standby = TRUE;
2607
2608 ENTER();
2609
2610 if (NULL == pAdapter)
2611 {
2612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002613 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002614 return -ENODEV;
2615 }
2616
2617 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2618 if (NULL == pHddCtx)
2619 {
2620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002621 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002622 return -ENODEV;
2623 }
2624
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002625 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2627 netif_tx_disable(pAdapter->dev);
2628 netif_carrier_off(pAdapter->dev);
2629
2630
2631 /* SoftAP ifaces should never go in power save mode
2632 making sure same here. */
2633 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2634 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 )
2637 {
2638 /* SoftAP mode, so return from here */
2639 EXIT();
2640 return 0;
2641 }
2642
2643 /* Find if any iface is up then
2644 if any iface is up then can't put device to sleep/ power save mode. */
2645 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2646 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2647 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002648 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2649 {
2650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302651 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002652 enter_standby = FALSE;
2653 break;
2654 }
2655 else
2656 {
2657 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2658 pAdapterNode = pNext;
2659 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002660 }
2661
2662 if (TRUE == enter_standby)
2663 {
2664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2665 "entering standby", __func__);
2666 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2667 {
2668 /*log and return success*/
2669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2670 "wlan in power save", __func__);
2671 }
2672 }
2673
2674 EXIT();
2675 return 0;
2676}
2677
2678/**---------------------------------------------------------------------------
2679
2680 \brief hdd_uninit() - HDD uninit function
2681
2682 This is called during the netdev unregister to uninitialize all data
2683associated with the device
2684
2685 \param - dev Pointer to net_device structure
2686
2687 \return - void
2688
2689 --------------------------------------------------------------------------*/
2690static void hdd_uninit (struct net_device *dev)
2691{
2692 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2693
2694 ENTER();
2695
2696 do
2697 {
2698 if (NULL == pAdapter)
2699 {
2700 hddLog(VOS_TRACE_LEVEL_FATAL,
2701 "%s: NULL pAdapter", __func__);
2702 break;
2703 }
2704
2705 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2706 {
2707 hddLog(VOS_TRACE_LEVEL_FATAL,
2708 "%s: Invalid magic", __func__);
2709 break;
2710 }
2711
2712 if (NULL == pAdapter->pHddCtx)
2713 {
2714 hddLog(VOS_TRACE_LEVEL_FATAL,
2715 "%s: NULL pHddCtx", __func__);
2716 break;
2717 }
2718
2719 if (dev != pAdapter->dev)
2720 {
2721 hddLog(VOS_TRACE_LEVEL_FATAL,
2722 "%s: Invalid device reference", __func__);
2723 /* we haven't validated all cases so let this go for now */
2724 }
2725
2726 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2727
2728 /* after uninit our adapter structure will no longer be valid */
2729 pAdapter->dev = NULL;
2730 pAdapter->magic = 0;
2731 } while (0);
2732
2733 EXIT();
2734}
2735
2736/**---------------------------------------------------------------------------
2737
2738 \brief hdd_release_firmware() -
2739
2740 This function calls the release firmware API to free the firmware buffer.
2741
2742 \param - pFileName Pointer to the File Name.
2743 pCtx - Pointer to the adapter .
2744
2745
2746 \return - 0 for success, non zero for failure
2747
2748 --------------------------------------------------------------------------*/
2749
2750VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2751{
2752 VOS_STATUS status = VOS_STATUS_SUCCESS;
2753 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2754 ENTER();
2755
2756
2757 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2758
2759 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2760
2761 if(pHddCtx->fw) {
2762 release_firmware(pHddCtx->fw);
2763 pHddCtx->fw = NULL;
2764 }
2765 else
2766 status = VOS_STATUS_E_FAILURE;
2767 }
2768 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2769 if(pHddCtx->nv) {
2770 release_firmware(pHddCtx->nv);
2771 pHddCtx->nv = NULL;
2772 }
2773 else
2774 status = VOS_STATUS_E_FAILURE;
2775
2776 }
2777
2778 EXIT();
2779 return status;
2780}
2781
2782/**---------------------------------------------------------------------------
2783
2784 \brief hdd_request_firmware() -
2785
2786 This function reads the firmware file using the request firmware
2787 API and returns the the firmware data and the firmware file size.
2788
2789 \param - pfileName - Pointer to the file name.
2790 - pCtx - Pointer to the adapter .
2791 - ppfw_data - Pointer to the pointer of the firmware data.
2792 - pSize - Pointer to the file size.
2793
2794 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2795
2796 --------------------------------------------------------------------------*/
2797
2798
2799VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2800{
2801 int status;
2802 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2803 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2804 ENTER();
2805
2806 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2807
2808 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2809
2810 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2811 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2812 __func__, pfileName);
2813 retval = VOS_STATUS_E_FAILURE;
2814 }
2815
2816 else {
2817 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2818 *pSize = pHddCtx->fw->size;
2819 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2820 __func__, *pSize);
2821 }
2822 }
2823 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2824
2825 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2826
2827 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2828 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2829 __func__, pfileName);
2830 retval = VOS_STATUS_E_FAILURE;
2831 }
2832
2833 else {
2834 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2835 *pSize = pHddCtx->nv->size;
2836 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2837 __func__, *pSize);
2838 }
2839 }
2840
2841 EXIT();
2842 return retval;
2843}
2844/**---------------------------------------------------------------------------
2845 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2846
2847 This is the function invoked by SME to inform the result of a full power
2848 request issued by HDD
2849
2850 \param - callbackcontext - Pointer to cookie
2851 status - result of request
2852
2853 \return - None
2854
2855--------------------------------------------------------------------------*/
2856void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2857{
2858 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2859
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002860 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002861 if(&pHddCtx->full_pwr_comp_var)
2862 {
2863 complete(&pHddCtx->full_pwr_comp_var);
2864 }
2865}
2866
2867/**---------------------------------------------------------------------------
2868
2869 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2870
2871 This is the function invoked by SME to inform the result of BMPS
2872 request issued by HDD
2873
2874 \param - callbackcontext - Pointer to cookie
2875 status - result of request
2876
2877 \return - None
2878
2879--------------------------------------------------------------------------*/
2880void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2881{
2882
2883 struct completion *completion_var = (struct completion*) callbackContext;
2884
2885 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2886 if(completion_var != NULL)
2887 {
2888 complete(completion_var);
2889 }
2890}
2891
2892/**---------------------------------------------------------------------------
2893
2894 \brief hdd_get_cfg_file_size() -
2895
2896 This function reads the configuration file using the request firmware
2897 API and returns the configuration file size.
2898
2899 \param - pCtx - Pointer to the adapter .
2900 - pFileName - Pointer to the file name.
2901 - pBufSize - Pointer to the buffer size.
2902
2903 \return - 0 for success, non zero for failure
2904
2905 --------------------------------------------------------------------------*/
2906
2907VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2908{
2909 int status;
2910 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2911
2912 ENTER();
2913
2914 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2915
2916 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2917 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2918 status = VOS_STATUS_E_FAILURE;
2919 }
2920 else {
2921 *pBufSize = pHddCtx->fw->size;
2922 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2923 release_firmware(pHddCtx->fw);
2924 pHddCtx->fw = NULL;
2925 }
2926
2927 EXIT();
2928 return VOS_STATUS_SUCCESS;
2929}
2930
2931/**---------------------------------------------------------------------------
2932
2933 \brief hdd_read_cfg_file() -
2934
2935 This function reads the configuration file using the request firmware
2936 API and returns the cfg data and the buffer size of the configuration file.
2937
2938 \param - pCtx - Pointer to the adapter .
2939 - pFileName - Pointer to the file name.
2940 - pBuffer - Pointer to the data buffer.
2941 - pBufSize - Pointer to the buffer size.
2942
2943 \return - 0 for success, non zero for failure
2944
2945 --------------------------------------------------------------------------*/
2946
2947VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2948 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2949{
2950 int status;
2951 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2952
2953 ENTER();
2954
2955 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2956
2957 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2958 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2959 return VOS_STATUS_E_FAILURE;
2960 }
2961 else {
2962 if(*pBufSize != pHddCtx->fw->size) {
2963 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2964 "file size", __func__);
2965 release_firmware(pHddCtx->fw);
2966 pHddCtx->fw = NULL;
2967 return VOS_STATUS_E_FAILURE;
2968 }
2969 else {
2970 if(pBuffer) {
2971 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2972 }
2973 release_firmware(pHddCtx->fw);
2974 pHddCtx->fw = NULL;
2975 }
2976 }
2977
2978 EXIT();
2979
2980 return VOS_STATUS_SUCCESS;
2981}
2982
2983/**---------------------------------------------------------------------------
2984
Jeff Johnson295189b2012-06-20 16:38:30 -07002985 \brief hdd_set_mac_address() -
2986
2987 This function sets the user specified mac address using
2988 the command ifconfig wlanX hw ether <mac adress>.
2989
2990 \param - dev - Pointer to the net device.
2991 - addr - Pointer to the sockaddr.
2992 \return - 0 for success, non zero for failure
2993
2994 --------------------------------------------------------------------------*/
2995
2996static int hdd_set_mac_address(struct net_device *dev, void *addr)
2997{
2998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2999 struct sockaddr *psta_mac_addr = addr;
3000 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3001
3002 ENTER();
3003
3004 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3005
3006#ifdef HDD_SESSIONIZE
3007 // set the MAC address though the STA ID CFG.
3008 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3009 (v_U8_t *)&pAdapter->macAddressCurrent,
3010 sizeof( pAdapter->macAddressCurrent ),
3011 hdd_set_mac_addr_cb, VOS_FALSE );
3012#endif
3013
3014 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3015
3016 EXIT();
3017 return halStatus;
3018}
3019
3020tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3021{
3022 int i;
3023 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3024 {
3025 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3026 break;
3027 }
3028
3029 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3030 return NULL;
3031
3032 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3033 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3034}
3035
3036void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3037{
3038 int i;
3039 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3040 {
3041 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3042 {
3043 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3044 break;
3045 }
3046 }
3047 return;
3048}
3049
3050#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3051 static struct net_device_ops wlan_drv_ops = {
3052 .ndo_open = hdd_open,
3053 .ndo_stop = hdd_stop,
3054 .ndo_uninit = hdd_uninit,
3055 .ndo_start_xmit = hdd_hard_start_xmit,
3056 .ndo_tx_timeout = hdd_tx_timeout,
3057 .ndo_get_stats = hdd_stats,
3058 .ndo_do_ioctl = hdd_ioctl,
3059 .ndo_set_mac_address = hdd_set_mac_address,
3060 .ndo_select_queue = hdd_select_queue,
3061#ifdef WLAN_FEATURE_PACKET_FILTERING
3062#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3063 .ndo_set_rx_mode = hdd_set_multicast_list,
3064#else
3065 .ndo_set_multicast_list = hdd_set_multicast_list,
3066#endif //LINUX_VERSION_CODE
3067#endif
3068 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 static struct net_device_ops wlan_mon_drv_ops = {
3070 .ndo_open = hdd_mon_open,
3071 .ndo_stop = hdd_stop,
3072 .ndo_uninit = hdd_uninit,
3073 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3074 .ndo_tx_timeout = hdd_tx_timeout,
3075 .ndo_get_stats = hdd_stats,
3076 .ndo_do_ioctl = hdd_ioctl,
3077 .ndo_set_mac_address = hdd_set_mac_address,
3078 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003079
3080#endif
3081
3082void hdd_set_station_ops( struct net_device *pWlanDev )
3083{
3084#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3085 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3086 pWlanDev->netdev_ops = &wlan_drv_ops;
3087#else
3088 pWlanDev->open = hdd_open;
3089 pWlanDev->stop = hdd_stop;
3090 pWlanDev->uninit = hdd_uninit;
3091 pWlanDev->hard_start_xmit = NULL;
3092 pWlanDev->tx_timeout = hdd_tx_timeout;
3093 pWlanDev->get_stats = hdd_stats;
3094 pWlanDev->do_ioctl = hdd_ioctl;
3095 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3096 pWlanDev->set_mac_address = hdd_set_mac_address;
3097#endif
3098}
3099
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003100static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003101{
3102 struct net_device *pWlanDev = NULL;
3103 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003104 /*
3105 * cfg80211 initialization and registration....
3106 */
3107 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3108
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 if(pWlanDev != NULL)
3110 {
3111
3112 //Save the pointer to the net_device in the HDD adapter
3113 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3114
Jeff Johnson295189b2012-06-20 16:38:30 -07003115 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3116
3117 pAdapter->dev = pWlanDev;
3118 pAdapter->pHddCtx = pHddCtx;
3119 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3120
3121 init_completion(&pAdapter->session_open_comp_var);
3122 init_completion(&pAdapter->session_close_comp_var);
3123 init_completion(&pAdapter->disconnect_comp_var);
3124 init_completion(&pAdapter->linkup_event_var);
3125 init_completion(&pAdapter->cancel_rem_on_chan_var);
3126 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003127#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3128 init_completion(&pAdapter->offchannel_tx_event);
3129#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003130 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003131#ifdef FEATURE_WLAN_TDLS
3132 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003133 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003134 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303135 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003137 init_completion(&pHddCtx->mc_sus_event_var);
3138 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303139 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003140 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003141
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 pAdapter->isLinkUpSvcNeeded = FALSE;
3143 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3144 //Init the net_device structure
3145 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3146
3147 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3148 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3149 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3150 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3151
3152 hdd_set_station_ops( pAdapter->dev );
3153
3154 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003155 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3156 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3157 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003158 /* set pWlanDev's parent to underlying device */
3159 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3160 }
3161
3162 return pAdapter;
3163}
3164
3165VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3166{
3167 struct net_device *pWlanDev = pAdapter->dev;
3168 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3169 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3170 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3171
3172 if( rtnl_lock_held )
3173 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003174 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3176 {
3177 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3178 return VOS_STATUS_E_FAILURE;
3179 }
3180 }
3181 if (register_netdevice(pWlanDev))
3182 {
3183 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3184 return VOS_STATUS_E_FAILURE;
3185 }
3186 }
3187 else
3188 {
3189 if(register_netdev(pWlanDev))
3190 {
3191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3192 return VOS_STATUS_E_FAILURE;
3193 }
3194 }
3195 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3196
3197 return VOS_STATUS_SUCCESS;
3198}
3199
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003200static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003201{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003202 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003203
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003204 if (NULL == pAdapter)
3205 {
3206 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3207 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003208 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003209
3210 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3211 {
3212 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3213 return eHAL_STATUS_NOT_INITIALIZED;
3214 }
3215
3216 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3217
3218 /* need to make sure all of our scheduled work has completed.
3219 * This callback is called from MC thread context, so it is safe to
3220 * to call below flush workqueue API from here.
3221 */
3222 flush_scheduled_work();
3223
3224 /* We can be blocked while waiting for scheduled work to be
3225 * flushed, and the adapter structure can potentially be freed, in
3226 * which case the magic will have been reset. So make sure the
3227 * magic is still good, and hence the adapter structure is still
3228 * valid, before signaling completion */
3229 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3230 {
3231 complete(&pAdapter->session_close_comp_var);
3232 }
3233
Jeff Johnson295189b2012-06-20 16:38:30 -07003234 return eHAL_STATUS_SUCCESS;
3235}
3236
3237VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3238{
3239 struct net_device *pWlanDev = pAdapter->dev;
3240 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3241 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3242 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3243 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3244 int rc = 0;
3245
3246 INIT_COMPLETION(pAdapter->session_open_comp_var);
3247 //Open a SME session for future operation
3248 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3249 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3250 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3251 {
3252 hddLog(VOS_TRACE_LEVEL_FATAL,
3253 "sme_OpenSession() failed with status code %08d [x%08lx]",
3254 halStatus, halStatus );
3255 status = VOS_STATUS_E_FAILURE;
3256 goto error_sme_open;
3257 }
3258
3259 //Block on a completion variable. Can't wait forever though.
3260 rc = wait_for_completion_interruptible_timeout(
3261 &pAdapter->session_open_comp_var,
3262 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3263 if (!rc)
3264 {
3265 hddLog(VOS_TRACE_LEVEL_FATAL,
3266 "Session is not opened within timeout period code %08d", rc );
3267 status = VOS_STATUS_E_FAILURE;
3268 goto error_sme_open;
3269 }
3270
3271 // Register wireless extensions
3272 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3273 {
3274 hddLog(VOS_TRACE_LEVEL_FATAL,
3275 "hdd_register_wext() failed with status code %08d [x%08lx]",
3276 halStatus, halStatus );
3277 status = VOS_STATUS_E_FAILURE;
3278 goto error_register_wext;
3279 }
3280 //Safe to register the hard_start_xmit function again
3281#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3282 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3283#else
3284 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3285#endif
3286
3287 //Set the Connection State to Not Connected
3288 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3289
3290 //Set the default operation channel
3291 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3292
3293 /* Make the default Auth Type as OPEN*/
3294 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3295
3296 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3297 {
3298 hddLog(VOS_TRACE_LEVEL_FATAL,
3299 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3300 status, status );
3301 goto error_init_txrx;
3302 }
3303
3304 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3305
3306 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3307 {
3308 hddLog(VOS_TRACE_LEVEL_FATAL,
3309 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3310 status, status );
3311 goto error_wmm_init;
3312 }
3313
3314 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3315
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003316#ifdef FEATURE_WLAN_TDLS
3317 if(0 != wlan_hdd_tdls_init(pAdapter))
3318 {
3319 status = VOS_STATUS_E_FAILURE;
3320 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3321 goto error_tdls_init;
3322 }
3323 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3324#endif
3325
Jeff Johnson295189b2012-06-20 16:38:30 -07003326 return VOS_STATUS_SUCCESS;
3327
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003328#ifdef FEATURE_WLAN_TDLS
3329error_tdls_init:
3330 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3331 hdd_wmm_adapter_close(pAdapter);
3332#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003333error_wmm_init:
3334 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3335 hdd_deinit_tx_rx(pAdapter);
3336error_init_txrx:
3337 hdd_UnregisterWext(pWlanDev);
3338error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003339 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003340 {
3341 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003342 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003343 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003344 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003345 {
3346 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003347 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003349 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003350 }
3351}
3352error_sme_open:
3353 return status;
3354}
3355
Jeff Johnson295189b2012-06-20 16:38:30 -07003356void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3357{
3358 hdd_cfg80211_state_t *cfgState;
3359
3360 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3361
3362 if( NULL != cfgState->buf )
3363 {
3364 int rc;
3365 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3366 rc = wait_for_completion_interruptible_timeout(
3367 &pAdapter->tx_action_cnf_event,
3368 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3369 if(!rc)
3370 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003371 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3373 }
3374 }
3375 return;
3376}
Jeff Johnson295189b2012-06-20 16:38:30 -07003377
3378void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3379{
3380 ENTER();
3381 switch ( pAdapter->device_mode )
3382 {
3383 case WLAN_HDD_INFRA_STATION:
3384 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003385 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 {
3387 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3388 {
3389 hdd_deinit_tx_rx( pAdapter );
3390 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3391 }
3392
3393 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3394 {
3395 hdd_wmm_adapter_close( pAdapter );
3396 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3397 }
3398
Jeff Johnson295189b2012-06-20 16:38:30 -07003399 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003400#ifdef FEATURE_WLAN_TDLS
3401 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3402 {
3403 wlan_hdd_tdls_exit(pAdapter);
3404 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3405 }
3406#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003407
3408 break;
3409 }
3410
3411 case WLAN_HDD_SOFTAP:
3412 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003413 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003415
3416 hdd_unregister_hostapd(pAdapter);
3417 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003418 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003419 break;
3420 }
3421
3422 case WLAN_HDD_MONITOR:
3423 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003425 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3426 {
3427 hdd_deinit_tx_rx( pAdapter );
3428 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3429 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003430 if(NULL != pAdapterforTx)
3431 {
3432 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3433 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 break;
3435 }
3436
3437
3438 default:
3439 break;
3440 }
3441
3442 EXIT();
3443}
3444
3445void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3446{
3447 struct net_device *pWlanDev = pAdapter->dev;
3448
3449 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3450 if( rtnl_held )
3451 {
3452 unregister_netdevice(pWlanDev);
3453 }
3454 else
3455 {
3456 unregister_netdev(pWlanDev);
3457 }
3458 // note that the pAdapter is no longer valid at this point
3459 // since the memory has been reclaimed
3460 }
3461
3462}
3463
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003464void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3465{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303466 VOS_STATUS status;
3467 hdd_adapter_t *pAdapter = NULL;
3468 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003469
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303470 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003471
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303472 /*loop through all adapters.*/
3473 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003474 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303475 pAdapter = pAdapterNode->pAdapter;
3476 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3477 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003478
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303479 { // we skip this registration for modes other than STA and P2P client modes.
3480 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3481 pAdapterNode = pNext;
3482 continue;
3483 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003484
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303485 //Apply Dynamic DTIM For P2P
3486 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3487 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3488 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3489 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3490 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3491 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3492 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3493 (eConnectionState_Associated ==
3494 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3495 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3496 {
3497 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003498
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303499 powerRequest.uIgnoreDTIM = 1;
3500 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3501
3502 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3503 {
3504 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3505 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3506 }
3507 else
3508 {
3509 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3510 }
3511
3512 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3513 * specified during Enter/Exit BMPS when LCD off*/
3514 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3515 NULL, eANI_BOOLEAN_FALSE);
3516 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3517 NULL, eANI_BOOLEAN_FALSE);
3518
3519 /* switch to the DTIM specified in cfg.ini */
3520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3521 "Switch to DTIM %d", powerRequest.uListenInterval);
3522 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3523 break;
3524
3525 }
3526
3527 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3528 pAdapterNode = pNext;
3529 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003530}
3531
3532void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3533{
3534 /*Switch back to DTIM 1*/
3535 tSirSetPowerParamsReq powerRequest = { 0 };
3536
3537 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3538 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003539 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003540
3541 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3542 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3543 NULL, eANI_BOOLEAN_FALSE);
3544 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3545 NULL, eANI_BOOLEAN_FALSE);
3546
3547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3548 "Switch to DTIM%d",powerRequest.uListenInterval);
3549 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3550
3551}
3552
Jeff Johnson295189b2012-06-20 16:38:30 -07003553VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3554{
3555 VOS_STATUS status = VOS_STATUS_SUCCESS;
3556
3557 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3558 {
3559 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3560 }
3561
3562 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3563 {
3564 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3565 }
3566
3567 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3568 {
3569 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3570 }
3571
3572 return status;
3573}
3574
3575VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3576{
3577 hdd_adapter_t *pAdapter = NULL;
3578 eHalStatus halStatus;
3579 VOS_STATUS status = VOS_STATUS_E_INVAL;
3580 v_BOOL_t disableBmps = FALSE;
3581 v_BOOL_t disableImps = FALSE;
3582
3583 switch(session_type)
3584 {
3585 case WLAN_HDD_INFRA_STATION:
3586 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003587 case WLAN_HDD_P2P_CLIENT:
3588 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003589 //Exit BMPS -> Is Sta/P2P Client is already connected
3590 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3591 if((NULL != pAdapter)&&
3592 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3593 {
3594 disableBmps = TRUE;
3595 }
3596
3597 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3598 if((NULL != pAdapter)&&
3599 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3600 {
3601 disableBmps = TRUE;
3602 }
3603
3604 //Exit both Bmps and Imps incase of Go/SAP Mode
3605 if((WLAN_HDD_SOFTAP == session_type) ||
3606 (WLAN_HDD_P2P_GO == session_type))
3607 {
3608 disableBmps = TRUE;
3609 disableImps = TRUE;
3610 }
3611
3612 if(TRUE == disableImps)
3613 {
3614 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3615 {
3616 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3617 }
3618 }
3619
3620 if(TRUE == disableBmps)
3621 {
3622 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3623 {
3624 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3625
3626 if(eHAL_STATUS_SUCCESS != halStatus)
3627 {
3628 status = VOS_STATUS_E_FAILURE;
3629 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3630 VOS_ASSERT(0);
3631 return status;
3632 }
3633 }
3634
3635 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3636 {
3637 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3638
3639 if(eHAL_STATUS_SUCCESS != halStatus)
3640 {
3641 status = VOS_STATUS_E_FAILURE;
3642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3643 VOS_ASSERT(0);
3644 return status;
3645 }
3646 }
3647 }
3648
3649 if((TRUE == disableBmps) ||
3650 (TRUE == disableImps))
3651 {
3652 /* Now, get the chip into Full Power now */
3653 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3654 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3655 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3656
3657 if(halStatus != eHAL_STATUS_SUCCESS)
3658 {
3659 if(halStatus == eHAL_STATUS_PMC_PENDING)
3660 {
3661 //Block on a completion variable. Can't wait forever though
3662 wait_for_completion_interruptible_timeout(
3663 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3664 }
3665 else
3666 {
3667 status = VOS_STATUS_E_FAILURE;
3668 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3669 VOS_ASSERT(0);
3670 return status;
3671 }
3672 }
3673
3674 status = VOS_STATUS_SUCCESS;
3675 }
3676
3677 break;
3678 }
3679 return status;
3680}
3681
3682hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003683 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003684 tANI_U8 rtnl_held )
3685{
3686 hdd_adapter_t *pAdapter = NULL;
3687 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3688 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3689 VOS_STATUS exitbmpsStatus;
3690
3691 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3692
3693 //Disable BMPS incase of Concurrency
3694 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3695
3696 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3697 {
3698 //Fail to Exit BMPS
3699 VOS_ASSERT(0);
3700 return NULL;
3701 }
3702
3703 switch(session_type)
3704 {
3705 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003706 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003707 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003708 {
3709 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3710
3711 if( NULL == pAdapter )
3712 return NULL;
3713
Jeff Johnsone7245742012-09-05 17:12:55 -07003714 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3715 NL80211_IFTYPE_P2P_CLIENT:
3716 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003717
Jeff Johnson295189b2012-06-20 16:38:30 -07003718 pAdapter->device_mode = session_type;
3719
3720 status = hdd_init_station_mode( pAdapter );
3721 if( VOS_STATUS_SUCCESS != status )
3722 goto err_free_netdev;
3723
3724 status = hdd_register_interface( pAdapter, rtnl_held );
3725 if( VOS_STATUS_SUCCESS != status )
3726 {
3727 hdd_deinit_adapter(pHddCtx, pAdapter);
3728 goto err_free_netdev;
3729 }
3730 //Stop the Interface TX queue.
3731 netif_tx_disable(pAdapter->dev);
3732 //netif_tx_disable(pWlanDev);
3733 netif_carrier_off(pAdapter->dev);
3734
3735 break;
3736 }
3737
Jeff Johnson295189b2012-06-20 16:38:30 -07003738 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 case WLAN_HDD_SOFTAP:
3740 {
3741 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3742 if( NULL == pAdapter )
3743 return NULL;
3744
Jeff Johnson295189b2012-06-20 16:38:30 -07003745 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3746 NL80211_IFTYPE_AP:
3747 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 pAdapter->device_mode = session_type;
3749
3750 status = hdd_init_ap_mode(pAdapter);
3751 if( VOS_STATUS_SUCCESS != status )
3752 goto err_free_netdev;
3753
3754 status = hdd_register_hostapd( pAdapter, rtnl_held );
3755 if( VOS_STATUS_SUCCESS != status )
3756 {
3757 hdd_deinit_adapter(pHddCtx, pAdapter);
3758 goto err_free_netdev;
3759 }
3760
3761 netif_tx_disable(pAdapter->dev);
3762 netif_carrier_off(pAdapter->dev);
3763
3764 hdd_set_conparam( 1 );
3765 break;
3766 }
3767 case WLAN_HDD_MONITOR:
3768 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3770 if( NULL == pAdapter )
3771 return NULL;
3772
3773 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3774 pAdapter->device_mode = session_type;
3775 status = hdd_register_interface( pAdapter, rtnl_held );
3776#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3777 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3778#else
3779 pAdapter->dev->open = hdd_mon_open;
3780 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3781#endif
3782 hdd_init_tx_rx( pAdapter );
3783 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3784 //Set adapter to be used for data tx. It will use either GO or softap.
3785 pAdapter->sessionCtx.monitor.pAdapterForTx =
3786 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3788 {
3789 pAdapter->sessionCtx.monitor.pAdapterForTx =
3790 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3791 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 /* This workqueue will be used to transmit management packet over
3793 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003794 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3795 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3796 return NULL;
3797 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003798
Jeff Johnson295189b2012-06-20 16:38:30 -07003799 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3800 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 }
3802 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003803 case WLAN_HDD_FTM:
3804 {
3805 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3806
3807 if( NULL == pAdapter )
3808 return NULL;
3809 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3810 * message while loading driver in FTM mode. */
3811 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3812 pAdapter->device_mode = session_type;
3813 status = hdd_register_interface( pAdapter, rtnl_held );
3814 }
3815 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003816 default:
3817 {
3818 VOS_ASSERT(0);
3819 return NULL;
3820 }
3821 }
3822
3823
3824 if( VOS_STATUS_SUCCESS == status )
3825 {
3826 //Add it to the hdd's session list.
3827 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3828 if( NULL == pHddAdapterNode )
3829 {
3830 status = VOS_STATUS_E_NOMEM;
3831 }
3832 else
3833 {
3834 pHddAdapterNode->pAdapter = pAdapter;
3835 status = hdd_add_adapter_back ( pHddCtx,
3836 pHddAdapterNode );
3837 }
3838 }
3839
3840 if( VOS_STATUS_SUCCESS != status )
3841 {
3842 if( NULL != pAdapter )
3843 {
3844 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3845 pAdapter = NULL;
3846 }
3847 if( NULL != pHddAdapterNode )
3848 {
3849 vos_mem_free( pHddAdapterNode );
3850 }
3851
3852 goto resume_bmps;
3853 }
3854
3855 if(VOS_STATUS_SUCCESS == status)
3856 {
3857 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3858
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003859 //Initialize the WoWL service
3860 if(!hdd_init_wowl(pAdapter))
3861 {
3862 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3863 goto err_free_netdev;
3864 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 return pAdapter;
3867
3868err_free_netdev:
3869 free_netdev(pAdapter->dev);
3870 wlan_hdd_release_intf_addr( pHddCtx,
3871 pAdapter->macAddressCurrent.bytes );
3872
3873resume_bmps:
3874 //If bmps disabled enable it
3875 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3876 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303877 if (pHddCtx->hdd_wlan_suspended)
3878 {
3879 hdd_set_pwrparams(pHddCtx);
3880 }
3881 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 }
3883 return NULL;
3884}
3885
3886VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3887 tANI_U8 rtnl_held )
3888{
3889 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3890 VOS_STATUS status;
3891
3892 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3893 if( VOS_STATUS_SUCCESS != status )
3894 return status;
3895
3896 while ( pCurrent->pAdapter != pAdapter )
3897 {
3898 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3899 if( VOS_STATUS_SUCCESS != status )
3900 break;
3901
3902 pCurrent = pNext;
3903 }
3904 pAdapterNode = pCurrent;
3905 if( VOS_STATUS_SUCCESS == status )
3906 {
3907 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3908 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3909 hdd_remove_adapter( pHddCtx, pAdapterNode );
3910 vos_mem_free( pAdapterNode );
3911
Jeff Johnson295189b2012-06-20 16:38:30 -07003912
3913 /* If there is a single session of STA/P2P client, re-enable BMPS */
3914 if ((!vos_concurrent_sessions_running()) &&
3915 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3916 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3917 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303918 if (pHddCtx->hdd_wlan_suspended)
3919 {
3920 hdd_set_pwrparams(pHddCtx);
3921 }
3922 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003923 }
3924
3925 return VOS_STATUS_SUCCESS;
3926 }
3927
3928 return VOS_STATUS_E_FAILURE;
3929}
3930
3931VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3932{
3933 hdd_adapter_list_node_t *pHddAdapterNode;
3934 VOS_STATUS status;
3935
3936 ENTER();
3937
3938 do
3939 {
3940 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3941 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3942 {
3943 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3944 vos_mem_free( pHddAdapterNode );
3945 }
3946 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3947
3948 EXIT();
3949
3950 return VOS_STATUS_SUCCESS;
3951}
3952
3953void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3954{
3955 v_U8_t addIE[1] = {0};
3956
3957 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3958 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3959 eANI_BOOLEAN_FALSE) )
3960 {
3961 hddLog(LOGE,
3962 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3963 }
3964
3965 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3966 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3967 eANI_BOOLEAN_FALSE) )
3968 {
3969 hddLog(LOGE,
3970 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3971 }
3972
3973 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3974 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3975 eANI_BOOLEAN_FALSE) )
3976 {
3977 hddLog(LOGE,
3978 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3979 }
3980}
3981
3982VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3983{
3984 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3985 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3986 union iwreq_data wrqu;
3987
3988 ENTER();
3989
3990 switch(pAdapter->device_mode)
3991 {
3992 case WLAN_HDD_INFRA_STATION:
3993 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003994 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003995 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3996 {
3997 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3998 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3999 pAdapter->sessionId,
4000 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4001 else
4002 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4003 pAdapter->sessionId,
4004 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4005 //success implies disconnect command got queued up successfully
4006 if(halStatus == eHAL_STATUS_SUCCESS)
4007 {
4008 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4009 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4010 }
4011 memset(&wrqu, '\0', sizeof(wrqu));
4012 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4013 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4014 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4015 }
4016 else
4017 {
4018 hdd_abort_mac_scan(pHddCtx);
4019 }
4020
4021 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4022 {
4023 INIT_COMPLETION(pAdapter->session_close_comp_var);
4024 if (eHAL_STATUS_SUCCESS ==
4025 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4026 hdd_smeCloseSessionCallback, pAdapter))
4027 {
4028 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004029 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004030 &pAdapter->session_close_comp_var,
4031 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4032 }
4033 }
4034
4035 break;
4036
4037 case WLAN_HDD_SOFTAP:
4038 case WLAN_HDD_P2P_GO:
4039 //Any softap specific cleanup here...
4040 mutex_lock(&pHddCtx->sap_lock);
4041 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4042 {
4043 VOS_STATUS status;
4044 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4045
4046 //Stop Bss.
4047 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4048 if (VOS_IS_STATUS_SUCCESS(status))
4049 {
4050 hdd_hostapd_state_t *pHostapdState =
4051 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4052
4053 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4054
4055 if (!VOS_IS_STATUS_SUCCESS(status))
4056 {
4057 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004058 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 }
4060 }
4061 else
4062 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004063 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004064 }
4065 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4066
4067 if (eHAL_STATUS_FAILURE ==
4068 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4069 0, NULL, eANI_BOOLEAN_FALSE))
4070 {
4071 hddLog(LOGE,
4072 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004073 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004074 }
4075
4076 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4077 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4078 eANI_BOOLEAN_FALSE) )
4079 {
4080 hddLog(LOGE,
4081 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4082 }
4083
4084 // Reset WNI_CFG_PROBE_RSP Flags
4085 wlan_hdd_reset_prob_rspies(pAdapter);
4086 kfree(pAdapter->sessionCtx.ap.beacon);
4087 pAdapter->sessionCtx.ap.beacon = NULL;
4088 }
4089 mutex_unlock(&pHddCtx->sap_lock);
4090 break;
4091 case WLAN_HDD_MONITOR:
4092 break;
4093 default:
4094 break;
4095 }
4096
4097 EXIT();
4098 return VOS_STATUS_SUCCESS;
4099}
4100
4101VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4102{
4103 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4104 VOS_STATUS status;
4105 hdd_adapter_t *pAdapter;
4106
4107 ENTER();
4108
4109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4110
4111 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4112 {
4113 pAdapter = pAdapterNode->pAdapter;
4114 netif_tx_disable(pAdapter->dev);
4115 netif_carrier_off(pAdapter->dev);
4116
4117 hdd_stop_adapter( pHddCtx, pAdapter );
4118
4119 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4120 pAdapterNode = pNext;
4121 }
4122
4123 EXIT();
4124
4125 return VOS_STATUS_SUCCESS;
4126}
4127
4128VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4129{
4130 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4131 VOS_STATUS status;
4132 hdd_adapter_t *pAdapter;
4133
4134 ENTER();
4135
4136 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4137
4138 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4139 {
4140 pAdapter = pAdapterNode->pAdapter;
4141 netif_tx_disable(pAdapter->dev);
4142 netif_carrier_off(pAdapter->dev);
4143
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 hdd_deinit_tx_rx(pAdapter);
4145 hdd_wmm_adapter_close(pAdapter);
4146
4147 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4148 pAdapterNode = pNext;
4149 }
4150
4151 EXIT();
4152
4153 return VOS_STATUS_SUCCESS;
4154}
4155
4156VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4157{
4158 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4159 VOS_STATUS status;
4160 hdd_adapter_t *pAdapter;
4161 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304162 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004163
4164 ENTER();
4165
4166 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4167
4168 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4169 {
4170 pAdapter = pAdapterNode->pAdapter;
4171
4172 switch(pAdapter->device_mode)
4173 {
4174 case WLAN_HDD_INFRA_STATION:
4175 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004176 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304177
4178 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4179
Jeff Johnson295189b2012-06-20 16:38:30 -07004180 hdd_init_station_mode(pAdapter);
4181 /* Open the gates for HDD to receive Wext commands */
4182 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004183 pHddCtx->scan_info.mScanPending = FALSE;
4184 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004185
4186 //Trigger the initial scan
4187 hdd_wlan_initial_scan(pAdapter);
4188
4189 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304190 if (eConnectionState_Associated == connState ||
4191 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004192 {
4193 union iwreq_data wrqu;
4194 memset(&wrqu, '\0', sizeof(wrqu));
4195 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4196 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4197 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004198
Jeff Johnson295189b2012-06-20 16:38:30 -07004199 /* indicate disconnected event to nl80211 */
4200 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4201 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004202 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304203 else if (eConnectionState_Connecting == connState)
4204 {
4205 /*
4206 * Indicate connect failure to supplicant if we were in the
4207 * process of connecting
4208 */
4209 cfg80211_connect_result(pAdapter->dev, NULL,
4210 NULL, 0, NULL, 0,
4211 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4212 GFP_KERNEL);
4213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 break;
4215
4216 case WLAN_HDD_SOFTAP:
4217 /* softAP can handle SSR */
4218 break;
4219
4220 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4222 __func__);
4223 /* event supplicant to restart */
4224 cfg80211_del_sta(pAdapter->dev,
4225 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004226 break;
4227
4228 case WLAN_HDD_MONITOR:
4229 /* monitor interface start */
4230 break;
4231 default:
4232 break;
4233 }
4234
4235 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4236 pAdapterNode = pNext;
4237 }
4238
4239 EXIT();
4240
4241 return VOS_STATUS_SUCCESS;
4242}
4243
4244VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4245{
4246 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4247 hdd_adapter_t *pAdapter;
4248 VOS_STATUS status;
4249 v_U32_t roamId;
4250
4251 ENTER();
4252
4253 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4254
4255 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4256 {
4257 pAdapter = pAdapterNode->pAdapter;
4258
4259 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4260 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4261 {
4262 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4263 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4264
4265 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4266 init_completion(&pAdapter->disconnect_comp_var);
4267 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4268 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4269
4270 wait_for_completion_interruptible_timeout(
4271 &pAdapter->disconnect_comp_var,
4272 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4273
4274 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4275 pHddCtx->isAmpAllowed = VOS_FALSE;
4276 sme_RoamConnect(pHddCtx->hHal,
4277 pAdapter->sessionId, &(pWextState->roamProfile),
4278 &roamId);
4279 }
4280
4281 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4282 pAdapterNode = pNext;
4283 }
4284
4285 EXIT();
4286
4287 return VOS_STATUS_SUCCESS;
4288}
4289
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004290void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4291{
4292 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4293 VOS_STATUS status;
4294 hdd_adapter_t *pAdapter;
4295 hdd_station_ctx_t *pHddStaCtx;
4296 hdd_ap_ctx_t *pHddApCtx;
4297 hdd_hostapd_state_t * pHostapdState;
4298 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4299 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4300 const char *p2pMode = "DEV";
4301 const char *ccMode = "Standalone";
4302 int n;
4303
4304 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4305 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4306 {
4307 pAdapter = pAdapterNode->pAdapter;
4308 switch (pAdapter->device_mode) {
4309 case WLAN_HDD_INFRA_STATION:
4310 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4311 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4312 staChannel = pHddStaCtx->conn_info.operationChannel;
4313 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4314 }
4315 break;
4316 case WLAN_HDD_P2P_CLIENT:
4317 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4318 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4319 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4320 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4321 p2pMode = "CLI";
4322 }
4323 break;
4324 case WLAN_HDD_P2P_GO:
4325 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4326 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4327 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4328 p2pChannel = pHddApCtx->operatingChannel;
4329 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4330 }
4331 p2pMode = "GO";
4332 break;
4333 case WLAN_HDD_SOFTAP:
4334 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4335 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4336 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4337 apChannel = pHddApCtx->operatingChannel;
4338 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4339 }
4340 break;
4341 default:
4342 break;
4343 }
4344 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4345 pAdapterNode = pNext;
4346 }
4347 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4348 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4349 }
4350 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4351 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4352 if (p2pChannel > 0) {
4353 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4354 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4355 }
4356 if (apChannel > 0) {
4357 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4358 apChannel, MAC_ADDR_ARRAY(apBssid));
4359 }
4360
4361 if (p2pChannel > 0 && apChannel > 0) {
4362 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4363 }
4364}
4365
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004366bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004367{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004368 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004369}
4370
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004371/* Once SSR is disabled then it cannot be set. */
4372void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004373{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004374 if (HDD_SSR_DISABLED == isSsrRequired)
4375 return;
4376
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 isSsrRequired = value;
4378}
4379
4380VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4381 hdd_adapter_list_node_t** ppAdapterNode)
4382{
4383 VOS_STATUS status;
4384 spin_lock(&pHddCtx->hddAdapters.lock);
4385 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4386 (hdd_list_node_t**) ppAdapterNode );
4387 spin_unlock(&pHddCtx->hddAdapters.lock);
4388 return status;
4389}
4390
4391VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4392 hdd_adapter_list_node_t* pAdapterNode,
4393 hdd_adapter_list_node_t** pNextAdapterNode)
4394{
4395 VOS_STATUS status;
4396 spin_lock(&pHddCtx->hddAdapters.lock);
4397 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4398 (hdd_list_node_t*) pAdapterNode,
4399 (hdd_list_node_t**)pNextAdapterNode );
4400
4401 spin_unlock(&pHddCtx->hddAdapters.lock);
4402 return status;
4403}
4404
4405VOS_STATUS hdd_remove_adapter( 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_remove_node ( &pHddCtx->hddAdapters,
4411 &pAdapterNode->node );
4412 spin_unlock(&pHddCtx->hddAdapters.lock);
4413 return status;
4414}
4415
4416VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4417 hdd_adapter_list_node_t** ppAdapterNode)
4418{
4419 VOS_STATUS status;
4420 spin_lock(&pHddCtx->hddAdapters.lock);
4421 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4422 (hdd_list_node_t**) ppAdapterNode );
4423 spin_unlock(&pHddCtx->hddAdapters.lock);
4424 return status;
4425}
4426
4427VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4428 hdd_adapter_list_node_t* pAdapterNode)
4429{
4430 VOS_STATUS status;
4431 spin_lock(&pHddCtx->hddAdapters.lock);
4432 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4433 (hdd_list_node_t*) pAdapterNode );
4434 spin_unlock(&pHddCtx->hddAdapters.lock);
4435 return status;
4436}
4437
4438VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4439 hdd_adapter_list_node_t* pAdapterNode)
4440{
4441 VOS_STATUS status;
4442 spin_lock(&pHddCtx->hddAdapters.lock);
4443 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4444 (hdd_list_node_t*) pAdapterNode );
4445 spin_unlock(&pHddCtx->hddAdapters.lock);
4446 return status;
4447}
4448
4449hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4450 tSirMacAddr macAddr )
4451{
4452 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4453 hdd_adapter_t *pAdapter;
4454 VOS_STATUS status;
4455
4456 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4457
4458 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4459 {
4460 pAdapter = pAdapterNode->pAdapter;
4461
4462 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4463 macAddr, sizeof(tSirMacAddr) ) )
4464 {
4465 return pAdapter;
4466 }
4467 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4468 pAdapterNode = pNext;
4469 }
4470
4471 return NULL;
4472
4473}
4474
4475hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4476{
4477 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4478 hdd_adapter_t *pAdapter;
4479 VOS_STATUS status;
4480
4481 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4482
4483 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4484 {
4485 pAdapter = pAdapterNode->pAdapter;
4486
4487 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4488 IFNAMSIZ ) )
4489 {
4490 return pAdapter;
4491 }
4492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4493 pAdapterNode = pNext;
4494 }
4495
4496 return NULL;
4497
4498}
4499
4500hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4501{
4502 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4503 hdd_adapter_t *pAdapter;
4504 VOS_STATUS status;
4505
4506 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4507
4508 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4509 {
4510 pAdapter = pAdapterNode->pAdapter;
4511
4512 if( pAdapter && (mode == pAdapter->device_mode) )
4513 {
4514 return pAdapter;
4515 }
4516 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4517 pAdapterNode = pNext;
4518 }
4519
4520 return NULL;
4521
4522}
4523
4524//Remove this function later
4525hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4526{
4527 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4528 hdd_adapter_t *pAdapter;
4529 VOS_STATUS status;
4530
4531 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4532
4533 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4534 {
4535 pAdapter = pAdapterNode->pAdapter;
4536
4537 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4538 {
4539 return pAdapter;
4540 }
4541
4542 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4543 pAdapterNode = pNext;
4544 }
4545
4546 return NULL;
4547
4548}
4549
Jeff Johnson295189b2012-06-20 16:38:30 -07004550/**---------------------------------------------------------------------------
4551
4552 \brief hdd_set_monitor_tx_adapter() -
4553
4554 This API initializes the adapter to be used while transmitting on monitor
4555 adapter.
4556
4557 \param - pHddCtx - Pointer to the HDD context.
4558 pAdapter - Adapter that will used for TX. This can be NULL.
4559 \return - None.
4560 --------------------------------------------------------------------------*/
4561void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4562{
4563 hdd_adapter_t *pMonAdapter;
4564
4565 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4566
4567 if( NULL != pMonAdapter )
4568 {
4569 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4570 }
4571}
Jeff Johnson295189b2012-06-20 16:38:30 -07004572/**---------------------------------------------------------------------------
4573
4574 \brief hdd_select_queue() -
4575
4576 This API returns the operating channel of the requested device mode
4577
4578 \param - pHddCtx - Pointer to the HDD context.
4579 - mode - Device mode for which operating channel is required
4580 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4581 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4582 \return - channel number. "0" id the requested device is not found OR it is not connected.
4583 --------------------------------------------------------------------------*/
4584v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4585{
4586 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4587 VOS_STATUS status;
4588 hdd_adapter_t *pAdapter;
4589 v_U8_t operatingChannel = 0;
4590
4591 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4592
4593 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4594 {
4595 pAdapter = pAdapterNode->pAdapter;
4596
4597 if( mode == pAdapter->device_mode )
4598 {
4599 switch(pAdapter->device_mode)
4600 {
4601 case WLAN_HDD_INFRA_STATION:
4602 case WLAN_HDD_P2P_CLIENT:
4603 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4604 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4605 break;
4606 case WLAN_HDD_SOFTAP:
4607 case WLAN_HDD_P2P_GO:
4608 /*softap connection info */
4609 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4610 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4611 break;
4612 default:
4613 break;
4614 }
4615
4616 break; //Found the device of interest. break the loop
4617 }
4618
4619 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4620 pAdapterNode = pNext;
4621 }
4622 return operatingChannel;
4623}
4624
4625#ifdef WLAN_FEATURE_PACKET_FILTERING
4626/**---------------------------------------------------------------------------
4627
4628 \brief hdd_set_multicast_list() -
4629
4630 This used to set the multicast address list.
4631
4632 \param - dev - Pointer to the WLAN device.
4633 - skb - Pointer to OS packet (sk_buff).
4634 \return - success/fail
4635
4636 --------------------------------------------------------------------------*/
4637static void hdd_set_multicast_list(struct net_device *dev)
4638{
4639 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004640 int mc_count;
4641 int i = 0;
4642 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304643
4644 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 {
4646 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304647 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 return;
4649 }
4650
4651 if (dev->flags & IFF_ALLMULTI)
4652 {
4653 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004654 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304655 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 }
4657 else
4658 {
4659 mc_count = netdev_mc_count(dev);
4660 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004661 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004662 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4663 {
4664 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004665 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304666 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004667 return;
4668 }
4669
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304670 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004671
4672 netdev_for_each_mc_addr(ha, dev) {
4673 if (i == mc_count)
4674 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304675 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4676 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4677 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004678 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304679 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 i++;
4681 }
4682 }
4683 return;
4684}
4685#endif
4686
4687/**---------------------------------------------------------------------------
4688
4689 \brief hdd_select_queue() -
4690
4691 This function is registered with the Linux OS for network
4692 core to decide which queue to use first.
4693
4694 \param - dev - Pointer to the WLAN device.
4695 - skb - Pointer to OS packet (sk_buff).
4696 \return - ac, Queue Index/access category corresponding to UP in IP header
4697
4698 --------------------------------------------------------------------------*/
4699v_U16_t hdd_select_queue(struct net_device *dev,
4700 struct sk_buff *skb)
4701{
4702 return hdd_wmm_select_queue(dev, skb);
4703}
4704
4705
4706/**---------------------------------------------------------------------------
4707
4708 \brief hdd_wlan_initial_scan() -
4709
4710 This function triggers the initial scan
4711
4712 \param - pAdapter - Pointer to the HDD adapter.
4713
4714 --------------------------------------------------------------------------*/
4715void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4716{
4717 tCsrScanRequest scanReq;
4718 tCsrChannelInfo channelInfo;
4719 eHalStatus halStatus;
4720 unsigned long scanId;
4721 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4722
4723 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4724 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4725 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4726
4727 if(sme_Is11dSupported(pHddCtx->hHal))
4728 {
4729 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4730 if ( HAL_STATUS_SUCCESS( halStatus ) )
4731 {
4732 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4733 if( !scanReq.ChannelInfo.ChannelList )
4734 {
4735 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4736 vos_mem_free(channelInfo.ChannelList);
4737 return;
4738 }
4739 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4740 channelInfo.numOfChannels);
4741 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4742 vos_mem_free(channelInfo.ChannelList);
4743 }
4744
4745 scanReq.scanType = eSIR_PASSIVE_SCAN;
4746 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4747 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4748 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4749 }
4750 else
4751 {
4752 scanReq.scanType = eSIR_ACTIVE_SCAN;
4753 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4754 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4755 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4756 }
4757
4758 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4759 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4760 {
4761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4762 __func__, halStatus );
4763 }
4764
4765 if(sme_Is11dSupported(pHddCtx->hHal))
4766 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4767}
4768
4769struct fullPowerContext
4770{
4771 struct completion completion;
4772 unsigned int magic;
4773};
4774#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4775
4776/**---------------------------------------------------------------------------
4777
4778 \brief hdd_full_power_callback() - HDD full power callback function
4779
4780 This is the function invoked by SME to inform the result of a full power
4781 request issued by HDD
4782
4783 \param - callbackcontext - Pointer to cookie
4784 \param - status - result of request
4785
4786 \return - None
4787
4788 --------------------------------------------------------------------------*/
4789static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4790{
4791 struct fullPowerContext *pContext = callbackContext;
4792
4793 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304794 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004795
4796 if (NULL == callbackContext)
4797 {
4798 hddLog(VOS_TRACE_LEVEL_ERROR,
4799 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004800 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 return;
4802 }
4803
4804 /* there is a race condition that exists between this callback function
4805 and the caller since the caller could time out either before or
4806 while this code is executing. we'll assume the timeout hasn't
4807 occurred, but we'll verify that right before we save our work */
4808
4809 if (POWER_CONTEXT_MAGIC != pContext->magic)
4810 {
4811 /* the caller presumably timed out so there is nothing we can do */
4812 hddLog(VOS_TRACE_LEVEL_WARN,
4813 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004814 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 return;
4816 }
4817
4818 /* the race is on. caller could have timed out immediately after
4819 we verified the magic, but if so, caller will wait a short time
4820 for us to notify the caller, so the context will stay valid */
4821 complete(&pContext->completion);
4822}
4823
4824/**---------------------------------------------------------------------------
4825
4826 \brief hdd_wlan_exit() - HDD WLAN exit function
4827
4828 This is the driver exit point (invoked during rmmod)
4829
4830 \param - pHddCtx - Pointer to the HDD Context
4831
4832 \return - None
4833
4834 --------------------------------------------------------------------------*/
4835void hdd_wlan_exit(hdd_context_t *pHddCtx)
4836{
4837 eHalStatus halStatus;
4838 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4839 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304840 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004842 struct fullPowerContext powerContext;
4843 long lrc;
4844
4845 ENTER();
4846
Jeff Johnson88ba7742013-02-27 14:36:02 -08004847 if (VOS_FTM_MODE != hdd_get_conparam())
4848 {
4849 // Unloading, restart logic is no more required.
4850 wlan_hdd_restart_deinit(pHddCtx);
4851 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004852
Jeff Johnson295189b2012-06-20 16:38:30 -07004853 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 {
4857 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4858 WLAN_HDD_INFRA_STATION);
4859 if (pAdapter == NULL)
4860 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4861
4862 if (pAdapter != NULL)
4863 {
4864 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4865 hdd_UnregisterWext(pAdapter->dev);
4866 }
4867 }
4868 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004869
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004871 {
4872 wlan_hdd_ftm_close(pHddCtx);
4873 goto free_hdd_ctx;
4874 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004875 //Stop the Interface TX queue.
4876 //netif_tx_disable(pWlanDev);
4877 //netif_carrier_off(pWlanDev);
4878
Jeff Johnson295189b2012-06-20 16:38:30 -07004879 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4880 {
4881 pAdapter = hdd_get_adapter(pHddCtx,
4882 WLAN_HDD_SOFTAP);
4883 }
4884 else
4885 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004887 {
4888 pAdapter = hdd_get_adapter(pHddCtx,
4889 WLAN_HDD_INFRA_STATION);
4890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 /* DeRegister with platform driver as client for Suspend/Resume */
4893 vosStatus = hddDeregisterPmOps(pHddCtx);
4894 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4895 {
4896 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4897 VOS_ASSERT(0);
4898 }
4899
4900 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4901 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4902 {
4903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4904 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004905
4906 // Cancel any outstanding scan requests. We are about to close all
4907 // of our adapters, but an adapter structure is what SME passes back
4908 // to our callback function. Hence if there are any outstanding scan
4909 // requests then there is a race condition between when the adapter
4910 // is closed and when the callback is invoked. We try to resolve that
4911 // race condition here by canceling any outstanding scans before we
4912 // close the adapters.
4913 // Note that the scans may be cancelled in an asynchronous manner, so
4914 // ideally there needs to be some kind of synchronization. Rather than
4915 // introduce a new synchronization here, we will utilize the fact that
4916 // we are about to Request Full Power, and since that is synchronized,
4917 // the expectation is that by the time Request Full Power has completed,
4918 // all scans will be cancelled.
4919 hdd_abort_mac_scan( pHddCtx );
4920
4921 //Disable IMPS/BMPS as we do not want the device to enter any power
4922 //save mode during shutdown
4923 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4924 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4925 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4926
4927 //Ensure that device is in full power as we will touch H/W during vos_Stop
4928 init_completion(&powerContext.completion);
4929 powerContext.magic = POWER_CONTEXT_MAGIC;
4930
4931 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4932 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4933
4934 if (eHAL_STATUS_SUCCESS != halStatus)
4935 {
4936 if (eHAL_STATUS_PMC_PENDING == halStatus)
4937 {
4938 /* request was sent -- wait for the response */
4939 lrc = wait_for_completion_interruptible_timeout(
4940 &powerContext.completion,
4941 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4942 /* either we have a response or we timed out
4943 either way, first invalidate our magic */
4944 powerContext.magic = 0;
4945 if (lrc <= 0)
4946 {
4947 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004948 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004949 /* there is a race condition such that the callback
4950 function could be executing at the same time we are. of
4951 primary concern is if the callback function had already
4952 verified the "magic" but hasn't yet set the completion
4953 variable. Since the completion variable is on our
4954 stack, we'll delay just a bit to make sure the data is
4955 still valid if that is the case */
4956 msleep(50);
4957 }
4958 }
4959 else
4960 {
4961 hddLog(VOS_TRACE_LEVEL_ERROR,
4962 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004963 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 VOS_ASSERT(0);
4965 /* continue -- need to clean up as much as possible */
4966 }
4967 }
4968
4969 // Unregister the Net Device Notifier
4970 unregister_netdevice_notifier(&hdd_netdev_notifier);
4971
Jeff Johnson295189b2012-06-20 16:38:30 -07004972 hdd_stop_all_adapters( pHddCtx );
4973
Jeff Johnson295189b2012-06-20 16:38:30 -07004974#ifdef WLAN_BTAMP_FEATURE
4975 vosStatus = WLANBAP_Stop(pVosContext);
4976 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4977 {
4978 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4979 "%s: Failed to stop BAP",__func__);
4980 }
4981#endif //WLAN_BTAMP_FEATURE
4982
4983 //Stop all the modules
4984 vosStatus = vos_stop( pVosContext );
4985 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4986 {
4987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4988 "%s: Failed to stop VOSS",__func__);
4989 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4990 }
4991
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 //Assert Deep sleep signal now to put Libra HW in lowest power state
4993 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4994 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4995
4996 //Vote off any PMIC voltage supplies
4997 vos_chipPowerDown(NULL, NULL, NULL);
4998
4999 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5000
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005003
5004 //Close the scheduler before calling vos_close to make sure no thread is
5005 // scheduled after the each module close is called i.e after all the data
5006 // structures are freed.
5007 vosStatus = vos_sched_close( pVosContext );
5008 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5009 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5010 "%s: Failed to close VOSS Scheduler",__func__);
5011 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5012 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005013#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005014#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5015 /* Destroy the wake lock */
5016 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5017#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005018 /* Destroy the wake lock */
5019 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005020#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005021
5022 //Close VOSS
5023 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5024 vos_close(pVosContext);
5025
Jeff Johnson295189b2012-06-20 16:38:30 -07005026 //Close Watchdog
5027 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5028 vos_watchdog_close(pVosContext);
5029
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305030 //Clean up HDD Nlink Service
5031 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5032 nl_srv_exit();
5033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 /* Cancel the vote for XO Core ON.
5035 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5036 * exited at this point
5037 */
5038 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5039 " when WLAN is turned OFF\n");
5040 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5041 {
5042 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5043 " Not returning failure."
5044 " Power consumed will be high\n");
5045 }
5046
5047 hdd_close_all_adapters( pHddCtx );
5048
5049
5050 //Free up dynamically allocated members inside HDD Adapter
5051 kfree(pHddCtx->cfg_ini);
5052 pHddCtx->cfg_ini= NULL;
5053
5054 /* free the power on lock from platform driver */
5055 if (free_riva_power_on_lock("wlan"))
5056 {
5057 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5058 __func__);
5059 }
5060
Jeff Johnson88ba7742013-02-27 14:36:02 -08005061free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005062 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005063 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 if (hdd_is_ssr_required())
5065 {
5066 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005067 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005068 msleep(5000);
5069 }
5070 hdd_set_ssr_required (VOS_FALSE);
5071}
5072
5073
5074/**---------------------------------------------------------------------------
5075
5076 \brief hdd_update_config_from_nv() - Function to update the contents of
5077 the running configuration with parameters taken from NV storage
5078
5079 \param - pHddCtx - Pointer to the HDD global context
5080
5081 \return - VOS_STATUS_SUCCESS if successful
5082
5083 --------------------------------------------------------------------------*/
5084static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5085{
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 v_BOOL_t itemIsValid = VOS_FALSE;
5087 VOS_STATUS status;
5088 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5089 v_U8_t macLoop;
5090
5091 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5092 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5093 if(status != VOS_STATUS_SUCCESS)
5094 {
5095 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5096 return VOS_STATUS_E_FAILURE;
5097 }
5098
5099 if (itemIsValid == VOS_TRUE)
5100 {
5101 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5102 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5103 VOS_MAX_CONCURRENCY_PERSONA);
5104 if(status != VOS_STATUS_SUCCESS)
5105 {
5106 /* Get MAC from NV fail, not update CFG info
5107 * INI MAC value will be used for MAC setting */
5108 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5109 return VOS_STATUS_E_FAILURE;
5110 }
5111
5112 /* If first MAC is not valid, treat all others are not valid
5113 * Then all MACs will be got from ini file */
5114 if(vos_is_macaddr_zero(&macFromNV[0]))
5115 {
5116 /* MAC address in NV file is not configured yet */
5117 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5118 return VOS_STATUS_E_INVAL;
5119 }
5120
5121 /* Get MAC address from NV, update CFG info */
5122 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5123 {
5124 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5125 {
5126 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5127 /* This MAC is not valid, skip it
5128 * This MAC will be got from ini file */
5129 }
5130 else
5131 {
5132 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5133 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5134 VOS_MAC_ADDR_SIZE);
5135 }
5136 }
5137 }
5138 else
5139 {
5140 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5141 return VOS_STATUS_E_FAILURE;
5142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005143
Jeff Johnson295189b2012-06-20 16:38:30 -07005144
5145 return VOS_STATUS_SUCCESS;
5146}
5147
5148/**---------------------------------------------------------------------------
5149
5150 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5151
5152 \param - pAdapter - Pointer to the HDD
5153
5154 \return - None
5155
5156 --------------------------------------------------------------------------*/
5157VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5158{
5159 eHalStatus halStatus;
5160 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305161 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005162
Jeff Johnson295189b2012-06-20 16:38:30 -07005163
5164 // Send ready indication to the HDD. This will kick off the MAC
5165 // into a 'running' state and should kick off an initial scan.
5166 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5167 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5168 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305169 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005170 "code %08d [x%08x]",__func__, halStatus, halStatus );
5171 return VOS_STATUS_E_FAILURE;
5172 }
5173
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305174 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5176 // And RIVA will crash
5177 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5178 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305179 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5180 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5181
5182
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 return VOS_STATUS_SUCCESS;
5184}
5185
Jeff Johnson295189b2012-06-20 16:38:30 -07005186/* wake lock APIs for HDD */
5187void hdd_prevent_suspend(void)
5188{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005189#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005191#else
5192 wcnss_prevent_suspend();
5193#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005194}
5195
5196void hdd_allow_suspend(void)
5197{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005198#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005199 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005200#else
5201 wcnss_allow_suspend();
5202#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005203}
5204
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005205void hdd_allow_suspend_timeout(v_U32_t timeout)
5206{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005207#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005208 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005209#else
5210 /* Do nothing as there is no API in wcnss for timeout*/
5211#endif
5212}
5213
Jeff Johnson295189b2012-06-20 16:38:30 -07005214/**---------------------------------------------------------------------------
5215
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005216 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5217 information between Host and Riva
5218
5219 This function gets reported version of FW
5220 It also finds the version of Riva headers used to compile the host
5221 It compares the above two and prints a warning if they are different
5222 It gets the SW and HW version string
5223 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5224 indicating the features they support through a bitmap
5225
5226 \param - pHddCtx - Pointer to HDD context
5227
5228 \return - void
5229
5230 --------------------------------------------------------------------------*/
5231
5232void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5233{
5234
5235 tSirVersionType versionCompiled;
5236 tSirVersionType versionReported;
5237 tSirVersionString versionString;
5238 tANI_U8 fwFeatCapsMsgSupported = 0;
5239 VOS_STATUS vstatus;
5240
5241 /* retrieve and display WCNSS version information */
5242 do {
5243
5244 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5245 &versionCompiled);
5246 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5247 {
5248 hddLog(VOS_TRACE_LEVEL_FATAL,
5249 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005250 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005251 break;
5252 }
5253
5254 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5255 &versionReported);
5256 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5257 {
5258 hddLog(VOS_TRACE_LEVEL_FATAL,
5259 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005260 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005261 break;
5262 }
5263
5264 if ((versionCompiled.major != versionReported.major) ||
5265 (versionCompiled.minor != versionReported.minor) ||
5266 (versionCompiled.version != versionReported.version) ||
5267 (versionCompiled.revision != versionReported.revision))
5268 {
5269 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5270 "Host expected %u.%u.%u.%u\n",
5271 WLAN_MODULE_NAME,
5272 (int)versionReported.major,
5273 (int)versionReported.minor,
5274 (int)versionReported.version,
5275 (int)versionReported.revision,
5276 (int)versionCompiled.major,
5277 (int)versionCompiled.minor,
5278 (int)versionCompiled.version,
5279 (int)versionCompiled.revision);
5280 }
5281 else
5282 {
5283 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5284 WLAN_MODULE_NAME,
5285 (int)versionReported.major,
5286 (int)versionReported.minor,
5287 (int)versionReported.version,
5288 (int)versionReported.revision);
5289 }
5290
5291 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5292 versionString,
5293 sizeof(versionString));
5294 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5295 {
5296 hddLog(VOS_TRACE_LEVEL_FATAL,
5297 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005298 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005299 break;
5300 }
5301
5302 pr_info("%s: WCNSS software version %s\n",
5303 WLAN_MODULE_NAME, versionString);
5304
5305 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5306 versionString,
5307 sizeof(versionString));
5308 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5309 {
5310 hddLog(VOS_TRACE_LEVEL_FATAL,
5311 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005312 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005313 break;
5314 }
5315
5316 pr_info("%s: WCNSS hardware version %s\n",
5317 WLAN_MODULE_NAME, versionString);
5318
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005319 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5320 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005321 send the message only if it the riva is 1.1
5322 minor numbers for different riva branches:
5323 0 -> (1.0)Mainline Build
5324 1 -> (1.1)Mainline Build
5325 2->(1.04) Stability Build
5326 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005327 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005328 ((versionReported.minor>=1) && (versionReported.version>=1)))
5329 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5330 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005331
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005332 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005333 {
5334#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5335 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5336 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5337#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005338 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005339 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005340
5341 } while (0);
5342
5343}
5344
5345/**---------------------------------------------------------------------------
5346
Jeff Johnson295189b2012-06-20 16:38:30 -07005347 \brief hdd_wlan_startup() - HDD init function
5348
5349 This is the driver startup code executed once a WLAN device has been detected
5350
5351 \param - dev - Pointer to the underlying device
5352
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005353 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005354
5355 --------------------------------------------------------------------------*/
5356
5357int hdd_wlan_startup(struct device *dev )
5358{
5359 VOS_STATUS status;
5360 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005361 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005362 hdd_context_t *pHddCtx = NULL;
5363 v_CONTEXT_t pVosContext= NULL;
5364#ifdef WLAN_BTAMP_FEATURE
5365 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5366 WLANBAP_ConfigType btAmpConfig;
5367 hdd_config_t *pConfig;
5368#endif
5369 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005371
5372 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 /*
5374 * cfg80211: wiphy allocation
5375 */
5376 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5377
5378 if(wiphy == NULL)
5379 {
5380 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005381 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 }
5383
5384 pHddCtx = wiphy_priv(wiphy);
5385
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 //Initialize the adapter context to zeros.
5387 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5388
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 hdd_prevent_suspend();
5391 pHddCtx->isLoadUnloadInProgress = TRUE;
5392
5393 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5394
5395 /*Get vos context here bcoz vos_open requires it*/
5396 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5397
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005398 if(pVosContext == NULL)
5399 {
5400 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5401 goto err_free_hdd_context;
5402 }
5403
Jeff Johnson295189b2012-06-20 16:38:30 -07005404 //Save the Global VOSS context in adapter context for future.
5405 pHddCtx->pvosContext = pVosContext;
5406
5407 //Save the adapter context in global context for future.
5408 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5409
Jeff Johnson295189b2012-06-20 16:38:30 -07005410 pHddCtx->parent_dev = dev;
5411
5412 init_completion(&pHddCtx->full_pwr_comp_var);
5413 init_completion(&pHddCtx->standby_comp_var);
5414 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005415 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005416 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005417
5418 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5419
5420 // Load all config first as TL config is needed during vos_open
5421 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5422 if(pHddCtx->cfg_ini == NULL)
5423 {
5424 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5425 goto err_free_hdd_context;
5426 }
5427
5428 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5429
5430 // Read and parse the qcom_cfg.ini file
5431 status = hdd_parse_config_ini( pHddCtx );
5432 if ( VOS_STATUS_SUCCESS != status )
5433 {
5434 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5435 __func__, WLAN_INI_FILE);
5436 goto err_config;
5437 }
5438
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305439 /* INI has been read, initialise the configuredMcastBcastFilter with
5440 * INI value as this will serve as the default value
5441 */
5442 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5443 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5444 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 /*
5446 * cfg80211: Initialization and registration ...
5447 */
5448 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5449 {
5450 hddLog(VOS_TRACE_LEVEL_FATAL,
5451 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5452 goto err_wiphy_reg;
5453 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005454
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005455 // Update VOS trace levels based upon the cfg.ini
5456 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5457 pHddCtx->cfg_ini->vosTraceEnableBAP);
5458 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5459 pHddCtx->cfg_ini->vosTraceEnableTL);
5460 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5461 pHddCtx->cfg_ini->vosTraceEnableWDI);
5462 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5463 pHddCtx->cfg_ini->vosTraceEnableHDD);
5464 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5465 pHddCtx->cfg_ini->vosTraceEnableSME);
5466 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5467 pHddCtx->cfg_ini->vosTraceEnablePE);
5468 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5469 pHddCtx->cfg_ini->vosTraceEnableWDA);
5470 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5471 pHddCtx->cfg_ini->vosTraceEnableSYS);
5472 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5473 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005474 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5475 pHddCtx->cfg_ini->vosTraceEnableSAP);
5476 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5477 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005478
Jeff Johnson295189b2012-06-20 16:38:30 -07005479 // Update WDI trace levels based upon the cfg.ini
5480 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5481 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5482 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5483 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5484 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5485 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5486 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5487 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005488
Jeff Johnson88ba7742013-02-27 14:36:02 -08005489 if (VOS_FTM_MODE == hdd_get_conparam())
5490 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005491 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5492 {
5493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5494 goto err_free_hdd_context;
5495 }
5496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5497 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005499
Jeff Johnson88ba7742013-02-27 14:36:02 -08005500 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5502 {
5503 status = vos_watchdog_open(pVosContext,
5504 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5505
5506 if(!VOS_IS_STATUS_SUCCESS( status ))
5507 {
5508 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 }
5511 }
5512
5513 pHddCtx->isLogpInProgress = FALSE;
5514 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5515
Jeff Johnson295189b2012-06-20 16:38:30 -07005516 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5517 if(!VOS_IS_STATUS_SUCCESS(status))
5518 {
5519 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 }
5522
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 status = vos_open( &pVosContext, 0);
5524 if ( !VOS_IS_STATUS_SUCCESS( status ))
5525 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005526 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5527 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 }
5529
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5531
5532 if ( NULL == pHddCtx->hHal )
5533 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005534 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005535 goto err_vosclose;
5536 }
5537
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005538 status = vos_preStart( pHddCtx->pvosContext );
5539 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5540 {
5541 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5542 goto err_vosclose;
5543 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005544
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005545 /* Note that the vos_preStart() sequence triggers the cfg download.
5546 The cfg download must occur before we update the SME config
5547 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005548 status = hdd_set_sme_config( pHddCtx );
5549
5550 if ( VOS_STATUS_SUCCESS != status )
5551 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005552 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5553 goto err_vosclose;
5554 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005555
5556 //Initialize the WMM module
5557 status = hdd_wmm_init(pHddCtx);
5558 if (!VOS_IS_STATUS_SUCCESS(status))
5559 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005560 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 goto err_vosclose;
5562 }
5563
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 /* In the integrated architecture we update the configuration from
5565 the INI file and from NV before vOSS has been started so that
5566 the final contents are available to send down to the cCPU */
5567
5568 // Apply the cfg.ini to cfg.dat
5569 if (FALSE == hdd_update_config_dat(pHddCtx))
5570 {
5571 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5572 goto err_vosclose;
5573 }
5574
5575 // Apply the NV to cfg.dat
5576 /* Prima Update MAC address only at here */
5577 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5578 {
5579#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5580 /* There was not a valid set of MAC Addresses in NV. See if the
5581 default addresses were modified by the cfg.ini settings. If so,
5582 we'll use them, but if not, we'll autogenerate a set of MAC
5583 addresses based upon the device serial number */
5584
5585 static const v_MACADDR_t default_address =
5586 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5587 unsigned int serialno;
5588 int i;
5589
5590 serialno = wcnss_get_serial_number();
5591 if ((0 != serialno) &&
5592 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5593 sizeof(default_address))))
5594 {
5595 /* cfg.ini has the default address, invoke autogen logic */
5596
5597 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5598 bytes of the serial number that can be used to generate
5599 the other 3 bytes of the MAC address. Mask off all but
5600 the lower 3 bytes (this will also make sure we don't
5601 overflow in the next step) */
5602 serialno &= 0x00FFFFFF;
5603
5604 /* we need a unique address for each session */
5605 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5606
5607 /* autogen all addresses */
5608 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5609 {
5610 /* start with the entire default address */
5611 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5612 /* then replace the lower 3 bytes */
5613 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5614 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5615 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5616
5617 serialno++;
5618 }
5619
5620 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5621 MAC_ADDRESS_STR,
5622 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5623 }
5624 else
5625#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5626 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005627 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 "%s: Invalid MAC address in NV, using MAC from ini file "
5629 MAC_ADDRESS_STR, __func__,
5630 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5631 }
5632 }
5633 {
5634 eHalStatus halStatus;
5635 // Set the MAC Address
5636 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5637 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5638 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5639 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5640
5641 if (!HAL_STATUS_SUCCESS( halStatus ))
5642 {
5643 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5644 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005645 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 }
5647 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005648
5649 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5650 Note: Firmware image will be read and downloaded inside vos_start API */
5651 status = vos_start( pHddCtx->pvosContext );
5652 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5653 {
5654 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5655 goto err_vosclose;
5656 }
5657
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005658 /* Exchange capability info between Host and FW and also get versioning info from FW */
5659 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005660
5661 status = hdd_post_voss_start_config( pHddCtx );
5662 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5663 {
5664 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5665 __func__);
5666 goto err_vosstop;
5667 }
5668
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5670 {
5671 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5672 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5673 }
5674 else
5675 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005676 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5677 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5678 if (pAdapter != NULL)
5679 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305680 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005681 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305682 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5683 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5684 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005685
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305686 /* Generate the P2P Device Address. This consists of the device's
5687 * primary MAC address with the locally administered bit set.
5688 */
5689 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005690 }
5691 else
5692 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305693 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5694 if (p2p_dev_addr != NULL)
5695 {
5696 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5697 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5698 }
5699 else
5700 {
5701 hddLog(VOS_TRACE_LEVEL_FATAL,
5702 "%s: Failed to allocate mac_address for p2p_device",
5703 __func__);
5704 goto err_close_adapter;
5705 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005707
5708 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5709 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5710 if ( NULL == pP2pAdapter )
5711 {
5712 hddLog(VOS_TRACE_LEVEL_FATAL,
5713 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005714 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005715 goto err_close_adapter;
5716 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005717 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005718 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005719
5720 if( pAdapter == NULL )
5721 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005722 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5723 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005724 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005725
Jeff Johnson295189b2012-06-20 16:38:30 -07005726#ifdef WLAN_BTAMP_FEATURE
5727 vStatus = WLANBAP_Open(pVosContext);
5728 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5729 {
5730 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5731 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005732 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 }
5734
5735 vStatus = BSL_Init(pVosContext);
5736 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5737 {
5738 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5739 "%s: Failed to Init BSL",__func__);
5740 goto err_bap_close;
5741 }
5742 vStatus = WLANBAP_Start(pVosContext);
5743 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5744 {
5745 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5746 "%s: Failed to start TL",__func__);
5747 goto err_bap_close;
5748 }
5749
5750 pConfig = pHddCtx->cfg_ini;
5751 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5752 status = WLANBAP_SetConfig(&btAmpConfig);
5753
5754#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005755
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005756#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5757 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5758 {
5759 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5760 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5761 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5762 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5763 }
5764#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005765#ifdef FEATURE_WLAN_SCAN_PNO
5766 /*SME must send channel update configuration to RIVA*/
5767 sme_UpdateChannelConfig(pHddCtx->hHal);
5768#endif
5769
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 /* Register with platform driver as client for Suspend/Resume */
5771 status = hddRegisterPmOps(pHddCtx);
5772 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5773 {
5774 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5775#ifdef WLAN_BTAMP_FEATURE
5776 goto err_bap_stop;
5777#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005778 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005779#endif //WLAN_BTAMP_FEATURE
5780 }
5781
5782 /* Register TM level change handler function to the platform */
5783 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5784 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5785 {
5786 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5787 goto err_unregister_pmops;
5788 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005789
5790 /* register for riva power on lock to platform driver */
5791 if (req_riva_power_on_lock("wlan"))
5792 {
5793 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5794 __func__);
5795 goto err_unregister_pmops;
5796 }
5797
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 // register net device notifier for device change notification
5799 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5800
5801 if(ret < 0)
5802 {
5803 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5804 goto err_free_power_on_lock;
5805 }
5806
5807 //Initialize the nlink service
5808 if(nl_srv_init() != 0)
5809 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305810 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 goto err_reg_netdev;
5812 }
5813
5814 //Initialize the BTC service
5815 if(btc_activate_service(pHddCtx) != 0)
5816 {
5817 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5818 goto err_nl_srv;
5819 }
5820
5821#ifdef PTT_SOCK_SVC_ENABLE
5822 //Initialize the PTT service
5823 if(ptt_sock_activate_svc(pHddCtx) != 0)
5824 {
5825 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5826 goto err_nl_srv;
5827 }
5828#endif
5829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005833 /* Action frame registered in one adapter which will
5834 * applicable to all interfaces
5835 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005836 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005838
5839 mutex_init(&pHddCtx->sap_lock);
5840
5841 pHddCtx->isLoadUnloadInProgress = FALSE;
5842
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005843#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005844#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5845 /* Initialize the wake lcok */
5846 wake_lock_init(&pHddCtx->rx_wake_lock,
5847 WAKE_LOCK_SUSPEND,
5848 "qcom_rx_wakelock");
5849#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005850 /* Initialize the wake lcok */
5851 wake_lock_init(&pHddCtx->sap_wake_lock,
5852 WAKE_LOCK_SUSPEND,
5853 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005854#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005855
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005856 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5857 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005858
5859 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5860 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005861
5862 // Initialize the restart logic
5863 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305864
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 goto success;
5866
5867err_nl_srv:
5868 nl_srv_exit();
5869
5870err_reg_netdev:
5871 unregister_netdevice_notifier(&hdd_netdev_notifier);
5872
5873err_free_power_on_lock:
5874 free_riva_power_on_lock("wlan");
5875
5876err_unregister_pmops:
5877 hddDevTmUnregisterNotifyCallback(pHddCtx);
5878 hddDeregisterPmOps(pHddCtx);
5879
5880#ifdef WLAN_BTAMP_FEATURE
5881err_bap_stop:
5882 WLANBAP_Stop(pVosContext);
5883#endif
5884
5885#ifdef WLAN_BTAMP_FEATURE
5886err_bap_close:
5887 WLANBAP_Close(pVosContext);
5888#endif
5889
Jeff Johnson295189b2012-06-20 16:38:30 -07005890err_close_adapter:
5891 hdd_close_all_adapters( pHddCtx );
5892
5893err_vosstop:
5894 vos_stop(pVosContext);
5895
5896err_vosclose:
5897 status = vos_sched_close( pVosContext );
5898 if (!VOS_IS_STATUS_SUCCESS(status)) {
5899 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5900 "%s: Failed to close VOSS Scheduler", __func__);
5901 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5902 }
5903 vos_close(pVosContext );
5904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005906 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005907
5908err_wdclose:
5909 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5910 vos_watchdog_close(pVosContext);
5911
Jeff Johnson295189b2012-06-20 16:38:30 -07005912err_wiphy_reg:
5913 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005914
5915err_config:
5916 kfree(pHddCtx->cfg_ini);
5917 pHddCtx->cfg_ini= NULL;
5918
5919err_free_hdd_context:
5920 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 wiphy_free(wiphy) ;
5922 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005923 VOS_BUG(1);
5924
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005925 if (hdd_is_ssr_required())
5926 {
5927 /* WDI timeout had happened during load, so SSR is needed here */
5928 subsystem_restart("wcnss");
5929 msleep(5000);
5930 }
5931 hdd_set_ssr_required (VOS_FALSE);
5932
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005933 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005934
5935success:
5936 EXIT();
5937 return 0;
5938}
5939
5940/**---------------------------------------------------------------------------
5941
Jeff Johnson32d95a32012-09-10 13:15:23 -07005942 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005943
Jeff Johnson32d95a32012-09-10 13:15:23 -07005944 This is the driver entry point - called in different timeline depending
5945 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005946
5947 \param - None
5948
5949 \return - 0 for success, non zero for failure
5950
5951 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005952static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005953{
5954 VOS_STATUS status;
5955 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 struct device *dev = NULL;
5957 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005958#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5959 int max_retries = 0;
5960#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005961
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305962#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5963 vos_wconn_trace_init();
5964#endif
5965
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 ENTER();
5967
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005968#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005970#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005971
5972 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5973 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5974
5975 //Power Up Libra WLAN card first if not already powered up
5976 status = vos_chipPowerUp(NULL,NULL,NULL);
5977 if (!VOS_IS_STATUS_SUCCESS(status))
5978 {
5979 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5980 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005981 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005982 }
5983
Jeff Johnson295189b2012-06-20 16:38:30 -07005984#ifdef ANI_BUS_TYPE_PCI
5985
5986 dev = wcnss_wlan_get_device();
5987
5988#endif // ANI_BUS_TYPE_PCI
5989
5990#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005991
5992#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5993 /* wait until WCNSS driver downloads NV */
5994 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5995 msleep(1000);
5996 }
5997 if (max_retries >= 5) {
5998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5999 return -ENODEV;
6000 }
6001#endif
6002
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 dev = wcnss_wlan_get_device();
6004#endif // ANI_BUS_TYPE_PLATFORM
6005
6006
6007 do {
6008 if (NULL == dev) {
6009 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6010 ret_status = -1;
6011 break;
6012 }
6013
6014#ifdef MEMORY_DEBUG
6015 vos_mem_init();
6016#endif
6017
6018#ifdef TIMER_MANAGER
6019 vos_timer_manager_init();
6020#endif
6021
6022 /* Preopen VOSS so that it is ready to start at least SAL */
6023 status = vos_preOpen(&pVosContext);
6024
6025 if (!VOS_IS_STATUS_SUCCESS(status))
6026 {
6027 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6028 ret_status = -1;
6029 break;
6030 }
6031
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006032#ifndef MODULE
6033 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6034 */
6035 hdd_set_conparam((v_UINT_t)con_mode);
6036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006037
6038 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006039 if (hdd_wlan_startup(dev))
6040 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006041 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006042 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 vos_preClose( &pVosContext );
6044 ret_status = -1;
6045 break;
6046 }
6047
6048 /* Cancel the vote for XO Core ON
6049 * This is done here for safety purposes in case we re-initialize without turning
6050 * it OFF in any error scenario.
6051 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006052 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006054 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6056 {
6057 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6058 " Power consumed will be high\n");
6059 }
6060 } while (0);
6061
6062 if (0 != ret_status)
6063 {
6064 //Assert Deep sleep signal now to put Libra HW in lowest power state
6065 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6066 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6067
6068 //Vote off any PMIC voltage supplies
6069 vos_chipPowerDown(NULL, NULL, NULL);
6070#ifdef TIMER_MANAGER
6071 vos_timer_exit();
6072#endif
6073#ifdef MEMORY_DEBUG
6074 vos_mem_exit();
6075#endif
6076
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006077#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006078 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6081 }
6082 else
6083 {
6084 //Send WLAN UP indication to Nlink Service
6085 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6086
6087 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6088
6089 }
6090
6091 EXIT();
6092
6093 return ret_status;
6094}
6095
Jeff Johnson32d95a32012-09-10 13:15:23 -07006096/**---------------------------------------------------------------------------
6097
6098 \brief hdd_module_init() - Init Function
6099
6100 This is the driver entry point (invoked when module is loaded using insmod)
6101
6102 \param - None
6103
6104 \return - 0 for success, non zero for failure
6105
6106 --------------------------------------------------------------------------*/
6107#ifdef MODULE
6108static int __init hdd_module_init ( void)
6109{
6110 return hdd_driver_init();
6111}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006112#else /* #ifdef MODULE */
6113static int __init hdd_module_init ( void)
6114{
6115 /* Driver initialization is delayed to fwpath_changed_handler */
6116 return 0;
6117}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006118#endif /* #ifdef MODULE */
6119
Jeff Johnson295189b2012-06-20 16:38:30 -07006120
6121/**---------------------------------------------------------------------------
6122
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006123 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006124
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006125 This is the driver exit point (invoked when module is unloaded using rmmod
6126 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006127
6128 \param - None
6129
6130 \return - None
6131
6132 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006133static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006134{
6135 hdd_context_t *pHddCtx = NULL;
6136 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006137
6138 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6139
6140 //Get the global vos context
6141 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6142
6143 if(!pVosContext)
6144 {
6145 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6146 goto done;
6147 }
6148
6149 //Get the HDD context.
6150 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6151
6152 if(!pHddCtx)
6153 {
6154 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6155 }
6156 else
6157 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006158 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006160 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6161 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 }
6163
6164 pHddCtx->isLoadUnloadInProgress = TRUE;
6165 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6166
6167 //Do all the cleanup before deregistering the driver
6168 hdd_wlan_exit(pHddCtx);
6169 }
6170
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 vos_preClose( &pVosContext );
6172
6173#ifdef TIMER_MANAGER
6174 vos_timer_exit();
6175#endif
6176#ifdef MEMORY_DEBUG
6177 vos_mem_exit();
6178#endif
6179
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306180#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6181 vos_wconn_trace_exit();
6182#endif
6183
Jeff Johnson295189b2012-06-20 16:38:30 -07006184done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006185#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6189}
6190
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006191/**---------------------------------------------------------------------------
6192
6193 \brief hdd_module_exit() - Exit function
6194
6195 This is the driver exit point (invoked when module is unloaded using rmmod)
6196
6197 \param - None
6198
6199 \return - None
6200
6201 --------------------------------------------------------------------------*/
6202static void __exit hdd_module_exit(void)
6203{
6204 hdd_driver_exit();
6205}
6206
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006207#ifdef MODULE
6208static int fwpath_changed_handler(const char *kmessage,
6209 struct kernel_param *kp)
6210{
Jeff Johnson76052702013-04-16 13:55:05 -07006211 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006212}
6213
6214static int con_mode_handler(const char *kmessage,
6215 struct kernel_param *kp)
6216{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006217 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006218}
6219#else /* #ifdef MODULE */
6220/**---------------------------------------------------------------------------
6221
Jeff Johnson76052702013-04-16 13:55:05 -07006222 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006223
Jeff Johnson76052702013-04-16 13:55:05 -07006224 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006225 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006226 - invoked when module parameter fwpath is modified from userspace to signal
6227 initializing the WLAN driver or when con_mode is modified from userspace
6228 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006229
6230 \return - 0 for success, non zero for failure
6231
6232 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006233static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006234{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006235 int ret_status;
6236
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006237 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006238 ret_status = hdd_driver_init();
6239 wlan_hdd_inited = ret_status ? 0 : 1;
6240 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006241 }
6242
6243 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006244
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006245 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006246
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006247 ret_status = hdd_driver_init();
6248 wlan_hdd_inited = ret_status ? 0 : 1;
6249 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006250}
6251
Jeff Johnson295189b2012-06-20 16:38:30 -07006252/**---------------------------------------------------------------------------
6253
Jeff Johnson76052702013-04-16 13:55:05 -07006254 \brief fwpath_changed_handler() - Handler Function
6255
6256 Handle changes to the fwpath parameter
6257
6258 \return - 0 for success, non zero for failure
6259
6260 --------------------------------------------------------------------------*/
6261static int fwpath_changed_handler(const char *kmessage,
6262 struct kernel_param *kp)
6263{
6264 int ret;
6265
6266 ret = param_set_copystring(kmessage, kp);
6267 if (0 == ret)
6268 ret = kickstart_driver();
6269 return ret;
6270}
6271
6272/**---------------------------------------------------------------------------
6273
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006274 \brief con_mode_handler() -
6275
6276 Handler function for module param con_mode when it is changed by userspace
6277 Dynamically linked - do nothing
6278 Statically linked - exit and init driver, as in rmmod and insmod
6279
Jeff Johnson76052702013-04-16 13:55:05 -07006280 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006281
Jeff Johnson76052702013-04-16 13:55:05 -07006282 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006283
6284 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006285static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006286{
Jeff Johnson76052702013-04-16 13:55:05 -07006287 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006288
Jeff Johnson76052702013-04-16 13:55:05 -07006289 ret = param_set_int(kmessage, kp);
6290 if (0 == ret)
6291 ret = kickstart_driver();
6292 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006293}
6294#endif /* #ifdef MODULE */
6295
6296/**---------------------------------------------------------------------------
6297
Jeff Johnson295189b2012-06-20 16:38:30 -07006298 \brief hdd_get_conparam() -
6299
6300 This is the driver exit point (invoked when module is unloaded using rmmod)
6301
6302 \param - None
6303
6304 \return - tVOS_CON_MODE
6305
6306 --------------------------------------------------------------------------*/
6307tVOS_CON_MODE hdd_get_conparam ( void )
6308{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006309#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006310 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006311#else
6312 return (tVOS_CON_MODE)curr_con_mode;
6313#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006314}
6315void hdd_set_conparam ( v_UINT_t newParam )
6316{
6317 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006318#ifndef MODULE
6319 curr_con_mode = con_mode;
6320#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006321}
6322/**---------------------------------------------------------------------------
6323
6324 \brief hdd_softap_sta_deauth() - 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
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006336VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006337{
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006339 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006340
6341 ENTER();
6342
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306343 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006344
6345 //Ignore request to deauth bcmc station
6346 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006347 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006348
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006349 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006350
6351 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006352 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006353}
6354
6355/**---------------------------------------------------------------------------
6356
6357 \brief hdd_softap_sta_disassoc() - function
6358
6359 This to take counter measure to handle deauth req from HDD
6360
6361 \param - pAdapter - Pointer to the HDD
6362
6363 \param - enable - boolean value
6364
6365 \return - None
6366
6367 --------------------------------------------------------------------------*/
6368
6369void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6370{
6371 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6372
6373 ENTER();
6374
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306375 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006376
6377 //Ignore request to disassoc bcmc station
6378 if( pDestMacAddress[0] & 0x1 )
6379 return;
6380
6381 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6382}
6383
6384void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6385{
6386 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6387
6388 ENTER();
6389
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306390 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006391
6392 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6393}
6394
Jeff Johnson295189b2012-06-20 16:38:30 -07006395/**---------------------------------------------------------------------------
6396 *
6397 * \brief hdd_get__concurrency_mode() -
6398 *
6399 *
6400 * \param - None
6401 *
6402 * \return - CONCURRENCY MODE
6403 *
6404 * --------------------------------------------------------------------------*/
6405tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6406{
6407 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6408 hdd_context_t *pHddCtx;
6409
6410 if (NULL != pVosContext)
6411 {
6412 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6413 if (NULL != pHddCtx)
6414 {
6415 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6416 }
6417 }
6418
6419 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006420 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006421 return VOS_STA;
6422}
6423
6424/* Decide whether to allow/not the apps power collapse.
6425 * Allow apps power collapse if we are in connected state.
6426 * if not, allow only if we are in IMPS */
6427v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6428{
6429 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006430 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006431 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6433 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6434 hdd_adapter_t *pAdapter = NULL;
6435 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006436 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006437
Jeff Johnson295189b2012-06-20 16:38:30 -07006438 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6439 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006440
Yathish9f22e662012-12-10 14:21:35 -08006441 concurrent_state = hdd_get_concurrency_mode();
6442
6443#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6444 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6445 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6446 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6447 return TRUE;
6448#endif
6449
Jeff Johnson295189b2012-06-20 16:38:30 -07006450 /*loop through all adapters. TBD fix for Concurrency */
6451 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6452 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6453 {
6454 pAdapter = pAdapterNode->pAdapter;
6455 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6456 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6457 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006458 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006460 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006461 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6462 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006464 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006465 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6466 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 return FALSE;
6468 }
6469 }
6470 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6471 pAdapterNode = pNext;
6472 }
6473 return TRUE;
6474}
6475
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006476/* Decides whether to send suspend notification to Riva
6477 * if any adapter is in BMPS; then it is required */
6478v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6479{
6480 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6481 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6482
6483 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6484 {
6485 return TRUE;
6486 }
6487 return FALSE;
6488}
6489
Jeff Johnson295189b2012-06-20 16:38:30 -07006490void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6491{
6492 switch(mode)
6493 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006494 case VOS_STA_MODE:
6495 case VOS_P2P_CLIENT_MODE:
6496 case VOS_P2P_GO_MODE:
6497 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006498 pHddCtx->concurrency_mode |= (1 << mode);
6499 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006500 break;
6501 default:
6502 break;
6503
6504 }
6505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6506 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6507}
6508
6509
6510void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6511{
6512 switch(mode)
6513 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006514 case VOS_STA_MODE:
6515 case VOS_P2P_CLIENT_MODE:
6516 case VOS_P2P_GO_MODE:
6517 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006518 pHddCtx->no_of_sessions[mode]--;
6519 if (!(pHddCtx->no_of_sessions[mode]))
6520 pHddCtx->concurrency_mode &= (~(1 << mode));
6521 break;
6522 default:
6523 break;
6524 }
6525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6526 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6527}
6528
Jeff Johnsone7245742012-09-05 17:12:55 -07006529/**---------------------------------------------------------------------------
6530 *
6531 * \brief wlan_hdd_restart_init
6532 *
6533 * This function initalizes restart timer/flag. An internal function.
6534 *
6535 * \param - pHddCtx
6536 *
6537 * \return - None
6538 *
6539 * --------------------------------------------------------------------------*/
6540
6541static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6542{
6543 /* Initialize */
6544 pHddCtx->hdd_restart_retries = 0;
6545 atomic_set(&pHddCtx->isRestartInProgress, 0);
6546 vos_timer_init(&pHddCtx->hdd_restart_timer,
6547 VOS_TIMER_TYPE_SW,
6548 wlan_hdd_restart_timer_cb,
6549 pHddCtx);
6550}
6551/**---------------------------------------------------------------------------
6552 *
6553 * \brief wlan_hdd_restart_deinit
6554 *
6555 * This function cleans up the resources used. An internal function.
6556 *
6557 * \param - pHddCtx
6558 *
6559 * \return - None
6560 *
6561 * --------------------------------------------------------------------------*/
6562
6563static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6564{
6565
6566 VOS_STATUS vos_status;
6567 /* Block any further calls */
6568 atomic_set(&pHddCtx->isRestartInProgress, 1);
6569 /* Cleanup */
6570 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6571 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006572 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006573 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6574 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006575 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006576
6577}
6578
6579/**---------------------------------------------------------------------------
6580 *
6581 * \brief wlan_hdd_framework_restart
6582 *
6583 * This function uses a cfg80211 API to start a framework initiated WLAN
6584 * driver module unload/load.
6585 *
6586 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6587 *
6588 *
6589 * \param - pHddCtx
6590 *
6591 * \return - VOS_STATUS_SUCCESS: Success
6592 * VOS_STATUS_E_EMPTY: Adapter is Empty
6593 * VOS_STATUS_E_NOMEM: No memory
6594
6595 * --------------------------------------------------------------------------*/
6596
6597static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6598{
6599 VOS_STATUS status = VOS_STATUS_SUCCESS;
6600 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006601 int len = (sizeof (struct ieee80211_mgmt));
6602 struct ieee80211_mgmt *mgmt = NULL;
6603
6604 /* Prepare the DEAUTH managment frame with reason code */
6605 mgmt = kzalloc(len, GFP_KERNEL);
6606 if(mgmt == NULL)
6607 {
6608 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6609 "%s: memory allocation failed (%d bytes)", __func__, len);
6610 return VOS_STATUS_E_NOMEM;
6611 }
6612 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006613
6614 /* Iterate over all adapters/devices */
6615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6616 do
6617 {
6618 if( (status == VOS_STATUS_SUCCESS) &&
6619 pAdapterNode &&
6620 pAdapterNode->pAdapter)
6621 {
6622 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6623 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6624 pAdapterNode->pAdapter->dev->name,
6625 pAdapterNode->pAdapter->device_mode,
6626 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006627 /*
6628 * CFG80211 event to restart the driver
6629 *
6630 * 'cfg80211_send_unprot_deauth' sends a
6631 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6632 * of SME(Linux Kernel) state machine.
6633 *
6634 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6635 * the driver.
6636 *
6637 */
6638
6639 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006640 }
6641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6642 pAdapterNode = pNext;
6643 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6644
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006645
6646 /* Free the allocated management frame */
6647 kfree(mgmt);
6648
Jeff Johnsone7245742012-09-05 17:12:55 -07006649 /* Retry until we unload or reach max count */
6650 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6651 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6652
6653 return status;
6654
6655}
6656/**---------------------------------------------------------------------------
6657 *
6658 * \brief wlan_hdd_restart_timer_cb
6659 *
6660 * Restart timer callback. An internal function.
6661 *
6662 * \param - User data:
6663 *
6664 * \return - None
6665 *
6666 * --------------------------------------------------------------------------*/
6667
6668void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6669{
6670 hdd_context_t *pHddCtx = usrDataForCallback;
6671 wlan_hdd_framework_restart(pHddCtx);
6672 return;
6673
6674}
6675
6676
6677/**---------------------------------------------------------------------------
6678 *
6679 * \brief wlan_hdd_restart_driver
6680 *
6681 * This function sends an event to supplicant to restart the WLAN driver.
6682 *
6683 * This function is called from vos_wlanRestart.
6684 *
6685 * \param - pHddCtx
6686 *
6687 * \return - VOS_STATUS_SUCCESS: Success
6688 * VOS_STATUS_E_EMPTY: Adapter is Empty
6689 * VOS_STATUS_E_ALREADY: Request already in progress
6690
6691 * --------------------------------------------------------------------------*/
6692VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6693{
6694 VOS_STATUS status = VOS_STATUS_SUCCESS;
6695
6696 /* A tight check to make sure reentrancy */
6697 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6698 {
6699 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6700 "%s: WLAN restart is already in progress", __func__);
6701
6702 return VOS_STATUS_E_ALREADY;
6703 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006704 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006705#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006706 wcnss_reset_intr();
6707#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006708
Jeff Johnsone7245742012-09-05 17:12:55 -07006709 return status;
6710}
6711
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006712/*
6713 * API to find if there is any STA or P2P-Client is connected
6714 */
6715VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6716{
6717 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6718}
Jeff Johnsone7245742012-09-05 17:12:55 -07006719
Jeff Johnson295189b2012-06-20 16:38:30 -07006720//Register the module init/exit functions
6721module_init(hdd_module_init);
6722module_exit(hdd_module_exit);
6723
6724MODULE_LICENSE("Dual BSD/GPL");
6725MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6726MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6727
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006728module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6729 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006730
Jeff Johnson76052702013-04-16 13:55:05 -07006731module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006732 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);