blob: 7b353881b1b55a0c09d8684b895d93b91e2c2713 [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;
1371 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1372
1373 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1374 value = value + 19;
1375 /* Convert the value from ascii to integer */
1376 ret = kstrtou8(value, 10, &maxTime);
1377 if (ret < 0)
1378 {
1379 /* If the input value is greater than max value of datatype, then also
1380 kstrtou8 fails */
1381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1382 "%s: kstrtou8 failed range [%d - %d]", __func__,
1383 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1384 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1385 ret = -EINVAL;
1386 goto exit;
1387 }
1388
1389 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1390 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1391 {
1392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1393 "lfr mode value %d is out of range"
1394 " (Min: %d Max: %d)", maxTime,
1395 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1396 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1397 ret = -EINVAL;
1398 goto exit;
1399 }
1400
1401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1402 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1403
1404 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1405 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1406 }
1407 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1408 {
1409 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1410 char extra[32];
1411 tANI_U8 len = 0;
1412
1413 /* value is interms of msec */
1414 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1415 if (copy_to_user(priv_data.buf, &extra, len + 1))
1416 {
1417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1418 "%s: failed to copy data to user buffer", __func__);
1419 ret = -EFAULT;
1420 goto exit;
1421 }
1422 }
1423 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1424 {
1425 tANI_U8 *value = command;
1426 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1427
1428 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1429 value = value + 16;
1430 /* Convert the value from ascii to integer */
1431 ret = kstrtou16(value, 10, &val);
1432 if (ret < 0)
1433 {
1434 /* If the input value is greater than max value of datatype, then also
1435 kstrtou16 fails */
1436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1437 "%s: kstrtou16 failed range [%d - %d]", __func__,
1438 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1439 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1440 ret = -EINVAL;
1441 goto exit;
1442 }
1443
1444 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1445 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1446 {
1447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1448 "scan home time value %d is out of range"
1449 " (Min: %d Max: %d)", val,
1450 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1451 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1452 ret = -EINVAL;
1453 goto exit;
1454 }
1455
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1457 "%s: Received Command to change scan home time = %d", __func__, val);
1458
1459 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1460 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1461 }
1462 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1463 {
1464 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1465 char extra[32];
1466 tANI_U8 len = 0;
1467
1468 /* value is interms of msec */
1469 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1470 if (copy_to_user(priv_data.buf, &extra, len + 1))
1471 {
1472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1473 "%s: failed to copy data to user buffer", __func__);
1474 ret = -EFAULT;
1475 goto exit;
1476 }
1477 }
1478 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1479 {
1480 tANI_U8 *value = command;
1481 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1482
1483 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1484 value = value + 17;
1485 /* Convert the value from ascii to integer */
1486 ret = kstrtou8(value, 10, &val);
1487 if (ret < 0)
1488 {
1489 /* If the input value is greater than max value of datatype, then also
1490 kstrtou8 fails */
1491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1492 "%s: kstrtou8 failed range [%d - %d]", __func__,
1493 CFG_ROAM_INTRA_BAND_MIN,
1494 CFG_ROAM_INTRA_BAND_MAX);
1495 ret = -EINVAL;
1496 goto exit;
1497 }
1498
1499 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1500 (val > CFG_ROAM_INTRA_BAND_MAX))
1501 {
1502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1503 "intra band mode value %d is out of range"
1504 " (Min: %d Max: %d)", val,
1505 CFG_ROAM_INTRA_BAND_MIN,
1506 CFG_ROAM_INTRA_BAND_MAX);
1507 ret = -EINVAL;
1508 goto exit;
1509 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1511 "%s: Received Command to change intra band = %d", __func__, val);
1512
1513 pHddCtx->cfg_ini->nRoamIntraBand = val;
1514 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1515 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001516 else if (strncmp(command, "SETWESMODE", 10) == 0)
1517 {
1518 tANI_U8 *value = command;
1519 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1520
1521 /* Move pointer to ahead of SETWESMODE<delimiter> */
1522 value = value + 11;
1523 /* Convert the value from ascii to integer */
1524 ret = kstrtou8(value, 10, &wesMode);
1525 if (ret < 0)
1526 {
1527 /* If the input value is greater than max value of datatype, then also
1528 kstrtou8 fails */
1529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1530 "%s: kstrtou8 failed range [%d - %d]", __func__,
1531 CFG_ENABLE_WES_MODE_NAME_MIN,
1532 CFG_ENABLE_WES_MODE_NAME_MAX);
1533 ret = -EINVAL;
1534 goto exit;
1535 }
1536
1537 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1538 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1539 {
1540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1541 "WES Mode value %d is out of range"
1542 " (Min: %d Max: %d)", wesMode,
1543 CFG_ENABLE_WES_MODE_NAME_MIN,
1544 CFG_ENABLE_WES_MODE_NAME_MAX);
1545 ret = -EINVAL;
1546 goto exit;
1547 }
1548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1549 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1550
1551 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1552 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1553 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001554 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1555 {
1556 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1557 char extra[32];
1558 tANI_U8 len = 0;
1559
1560 /* value is interms of msec */
1561 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1562 if (copy_to_user(priv_data.buf, &extra, len + 1))
1563 {
1564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1565 "%s: failed to copy data to user buffer", __func__);
1566 ret = -EFAULT;
1567 goto exit;
1568 }
1569 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001570 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1571 {
1572 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1573 char extra[32];
1574 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001575
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001576 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1577 if (copy_to_user(priv_data.buf, &extra, len + 1))
1578 {
1579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1580 "%s: failed to copy data to user buffer", __func__);
1581 ret = -EFAULT;
1582 goto exit;
1583 }
1584 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001585 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1586 {
1587 tANI_U8 *value = command;
1588 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1589
1590 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1591 value = value + 15;
1592 /* Convert the value from ascii to integer */
1593 ret = kstrtou8(value, 10, &nProbes);
1594 if (ret < 0)
1595 {
1596 /* If the input value is greater than max value of datatype, then also
1597 kstrtou8 fails */
1598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1599 "%s: kstrtou8 failed range [%d - %d]", __func__,
1600 CFG_ROAM_SCAN_N_PROBES_MIN,
1601 CFG_ROAM_SCAN_N_PROBES_MAX);
1602 ret = -EINVAL;
1603 goto exit;
1604 }
1605
1606 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1607 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1610 "NProbes value %d is out of range"
1611 " (Min: %d Max: %d)", nProbes,
1612 CFG_ROAM_SCAN_N_PROBES_MIN,
1613 CFG_ROAM_SCAN_N_PROBES_MAX);
1614 ret = -EINVAL;
1615 goto exit;
1616 }
1617
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1619 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1620
1621 pHddCtx->cfg_ini->nProbes = nProbes;
1622 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1623 }
1624 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1625 {
1626 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1627 char extra[32];
1628 tANI_U8 len = 0;
1629
1630 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1631 if (copy_to_user(priv_data.buf, &extra, len + 1))
1632 {
1633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1634 "%s: failed to copy data to user buffer", __func__);
1635 ret = -EFAULT;
1636 goto exit;
1637 }
1638 }
1639 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1640 {
1641 tANI_U8 *value = command;
1642 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
1643
1644 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1645 /* input value is in units of msec */
1646 value = value + 20;
1647 /* Convert the value from ascii to integer */
1648 ret = kstrtou16(value, 10, &homeAwayTime);
1649 if (ret < 0)
1650 {
1651 /* If the input value is greater than max value of datatype, then also
1652 kstrtou8 fails */
1653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1654 "%s: kstrtou8 failed range [%d - %d]", __func__,
1655 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1656 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1657 ret = -EINVAL;
1658 goto exit;
1659 }
1660
1661 /*Currently Home Away Time has a MIN value of 3.
1662 * But, we sould allow the user to input Zero,
1663 * since we are using the value of Zero to disable
1664 * this and fallback to LFR1.5 behaviour.*/
1665 if (0 != homeAwayTime)
1666 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1667 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1668 {
1669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1670 "homeAwayTime value %d is out of range"
1671 " (Min: %d Max: %d)", homeAwayTime,
1672 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1673 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
1678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1679 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1680
1681 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1682 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime);
1683 }
1684 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1685 {
1686 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1687 char extra[32];
1688 tANI_U8 len = 0;
1689
1690 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1691 if (copy_to_user(priv_data.buf, &extra, len + 1))
1692 {
1693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1694 "%s: failed to copy data to user buffer", __func__);
1695 ret = -EFAULT;
1696 goto exit;
1697 }
1698 }
1699 else if (strncmp(command, "REASSOC", 7) == 0)
1700 {
1701 tANI_U8 *value = command;
1702 tANI_U8 channel = 0;
1703 tSirMacAddr targetApBssid;
1704 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001705#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1706 tCsrHandoffRequest handoffInfo;
1707#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001708 hdd_station_ctx_t *pHddStaCtx = NULL;
1709 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1710 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1711
1712 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1713
1714 /* Reassoc command is allowed only if WES mode is enabled */
1715 if (!wesMode)
1716 {
1717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1718 ret = -EINVAL;
1719 goto exit;
1720 }
1721
1722 /* if not associated, no need to proceed with reassoc */
1723 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1724 {
1725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1726 ret = -EINVAL;
1727 goto exit;
1728 }
1729
1730 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1731 if (eHAL_STATUS_SUCCESS != status)
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "%s: Failed to parse reassoc command data", __func__);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 /* if the target bssid is same as currently associated AP,
1740 then no need to proceed with reassoc */
1741 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1742 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1743 {
1744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1745 ret = -EINVAL;
1746 goto exit;
1747 }
1748
1749 /* Check channel number is a valid channel number */
1750 if(VOS_STATUS_SUCCESS !=
1751 wlan_hdd_validate_operation_channel(pAdapter, channel))
1752 {
1753 hddLog(VOS_TRACE_LEVEL_ERROR,
1754 "%s: Invalid Channel [%d] \n", __func__, channel);
1755 return -EINVAL;
1756 }
1757
1758 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001759#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1760 handoffInfo.channel = channel;
1761 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1762 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1763#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001764 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001765#endif
1766#ifdef FEATURE_WLAN_LFR
1767 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1768 {
1769 tANI_U8 *value = command;
1770 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1771
1772 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1773 value = value + 12;
1774 /* Convert the value from ascii to integer */
1775 ret = kstrtou8(value, 10, &lfrMode);
1776 if (ret < 0)
1777 {
1778 /* If the input value is greater than max value of datatype, then also
1779 kstrtou8 fails */
1780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1781 "%s: kstrtou8 failed range [%d - %d]", __func__,
1782 CFG_LFR_FEATURE_ENABLED_MIN,
1783 CFG_LFR_FEATURE_ENABLED_MAX);
1784 ret = -EINVAL;
1785 goto exit;
1786 }
1787
1788 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1789 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1790 {
1791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1792 "lfr mode value %d is out of range"
1793 " (Min: %d Max: %d)", lfrMode,
1794 CFG_LFR_FEATURE_ENABLED_MIN,
1795 CFG_LFR_FEATURE_ENABLED_MAX);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799
1800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1801 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1802
1803 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1804 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1805 }
1806#endif
1807#ifdef WLAN_FEATURE_VOWIFI_11R
1808 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1809 {
1810 tANI_U8 *value = command;
1811 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1812
1813 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1814 value = value + 18;
1815 /* Convert the value from ascii to integer */
1816 ret = kstrtou8(value, 10, &ft);
1817 if (ret < 0)
1818 {
1819 /* If the input value is greater than max value of datatype, then also
1820 kstrtou8 fails */
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1822 "%s: kstrtou8 failed range [%d - %d]", __func__,
1823 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1824 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1825 ret = -EINVAL;
1826 goto exit;
1827 }
1828
1829 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1830 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1831 {
1832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1833 "ft mode value %d is out of range"
1834 " (Min: %d Max: %d)", ft,
1835 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1836 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1837 ret = -EINVAL;
1838 goto exit;
1839 }
1840
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1842 "%s: Received Command to change ft mode = %d", __func__, ft);
1843
1844 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1845 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1846 }
1847#endif
1848#ifdef FEATURE_WLAN_CCX
1849 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1850 {
1851 tANI_U8 *value = command;
1852 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1853
1854 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1855 value = value + 11;
1856 /* Convert the value from ascii to integer */
1857 ret = kstrtou8(value, 10, &ccxMode);
1858 if (ret < 0)
1859 {
1860 /* If the input value is greater than max value of datatype, then also
1861 kstrtou8 fails */
1862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1863 "%s: kstrtou8 failed range [%d - %d]", __func__,
1864 CFG_CCX_FEATURE_ENABLED_MIN,
1865 CFG_CCX_FEATURE_ENABLED_MAX);
1866 ret = -EINVAL;
1867 goto exit;
1868 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001869 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1870 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1871 {
1872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1873 "Ccx mode value %d is out of range"
1874 " (Min: %d Max: %d)", ccxMode,
1875 CFG_CCX_FEATURE_ENABLED_MIN,
1876 CFG_CCX_FEATURE_ENABLED_MAX);
1877 ret = -EINVAL;
1878 goto exit;
1879 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1881 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1882
1883 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1884 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1885 }
1886#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001887 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1888 {
1889 tANI_U8 *value = command;
1890 tANI_BOOLEAN roamScanControl = 0;
1891
1892 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1893 value = value + 19;
1894 /* Convert the value from ascii to integer */
1895 ret = kstrtou8(value, 10, &roamScanControl);
1896 if (ret < 0)
1897 {
1898 /* If the input value is greater than max value of datatype, then also
1899 kstrtou8 fails */
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1901 "%s: kstrtou8 failed ", __func__);
1902 ret = -EINVAL;
1903 goto exit;
1904 }
1905
1906 if (0 != roamScanControl)
1907 {
1908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1909 "roam scan control invalid value = %d",
1910 roamScanControl);
1911 ret = -EINVAL;
1912 goto exit;
1913 }
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1915 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1916
1917 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1918 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919#ifdef FEATURE_WLAN_OKC
1920 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1921 {
1922 tANI_U8 *value = command;
1923 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1924
1925 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1926 value = value + 11;
1927 /* Convert the value from ascii to integer */
1928 ret = kstrtou8(value, 10, &okcMode);
1929 if (ret < 0)
1930 {
1931 /* If the input value is greater than max value of datatype, then also
1932 kstrtou8 fails */
1933 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1934 "%s: kstrtou8 failed range [%d - %d]", __func__,
1935 CFG_OKC_FEATURE_ENABLED_MIN,
1936 CFG_OKC_FEATURE_ENABLED_MAX);
1937 ret = -EINVAL;
1938 goto exit;
1939 }
1940
1941 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1942 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1943 {
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1945 "Okc mode value %d is out of range"
1946 " (Min: %d Max: %d)", okcMode,
1947 CFG_OKC_FEATURE_ENABLED_MIN,
1948 CFG_OKC_FEATURE_ENABLED_MAX);
1949 ret = -EINVAL;
1950 goto exit;
1951 }
1952
1953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1954 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1955
1956 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1957 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001958 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1959 {
1960 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1961 char extra[32];
1962 tANI_U8 len = 0;
1963
1964 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1965 if (copy_to_user(priv_data.buf, &extra, len + 1))
1966 {
1967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1968 "%s: failed to copy data to user buffer", __func__);
1969 ret = -EFAULT;
1970 goto exit;
1971 }
1972 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001973#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001974 else {
1975 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1976 __func__, command);
1977 }
1978
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 }
1980exit:
1981 if (command)
1982 {
1983 kfree(command);
1984 }
1985 return ret;
1986}
1987
Srinivas Girigowdade697412013-02-14 16:31:48 -08001988#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1989void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1990{
1991 eCsrBand band = -1;
1992 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1993 switch (band)
1994 {
1995 case eCSR_BAND_ALL:
1996 *pBand = WLAN_HDD_UI_BAND_AUTO;
1997 break;
1998
1999 case eCSR_BAND_24:
2000 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2001 break;
2002
2003 case eCSR_BAND_5G:
2004 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2005 break;
2006
2007 default:
2008 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2009 *pBand = -1;
2010 break;
2011 }
2012}
2013
2014/**---------------------------------------------------------------------------
2015
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002016 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2017
2018 This function parses the send action frame data passed in the format
2019 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2020
2021 \param - pValue Pointer to input country code revision
2022 \param - pTargetApBssid Pointer to target Ap bssid
2023 \param - pChannel Pointer to the Target AP channel
2024 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2025 \param - pBuf Pointer to data
2026 \param - pBufLen Pointer to data length
2027
2028 \return - 0 for success non-zero for failure
2029
2030 --------------------------------------------------------------------------*/
2031VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2032 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2033{
2034 tANI_U8 *inPtr = pValue;
2035 tANI_U8 *dataEnd;
2036 int tempInt;
2037 int j = 0;
2038 int i = 0;
2039 int v = 0;
2040 tANI_U8 tempBuf[32];
2041 tANI_U8 tempByte = 0;
2042
2043 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2044 /*no argument after the command*/
2045 if (NULL == inPtr)
2046 {
2047 return -EINVAL;
2048 }
2049
2050 /*no space after the command*/
2051 else if (SPACE_ASCII_VALUE != *inPtr)
2052 {
2053 return -EINVAL;
2054 }
2055
2056 /*removing empty spaces*/
2057 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2058
2059 /*no argument followed by spaces*/
2060 if ('\0' == *inPtr)
2061 {
2062 return -EINVAL;
2063 }
2064
2065 /*getting the first argument ie the target AP bssid */
2066 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2067 {
2068 return -EINVAL;
2069 }
2070 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2071 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2072 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2073
2074 /* point to the next argument */
2075 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2076 /*no argument after the command*/
2077 if (NULL == inPtr) return -EINVAL;
2078
2079 /*removing empty spaces*/
2080 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2081
2082 /*no argument followed by spaces*/
2083 if ('\0' == *inPtr)
2084 {
2085 return -EINVAL;
2086 }
2087
2088 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002089 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002090 v = kstrtos32(tempBuf, 10, &tempInt);
2091 if ( v < 0) return -EINVAL;
2092
2093 *pChannel = tempInt;
2094
2095 /* point to the next argument */
2096 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2097 /*no argument after the command*/
2098 if (NULL == inPtr) return -EINVAL;
2099 /*removing empty spaces*/
2100 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2101
2102 /*no argument followed by spaces*/
2103 if ('\0' == *inPtr)
2104 {
2105 return -EINVAL;
2106 }
2107
2108 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002109 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002110 v = kstrtos32(tempBuf, 10, &tempInt);
2111 if ( v < 0) return -EINVAL;
2112
2113 *pDwellTime = tempInt;
2114
2115 /* point to the next argument */
2116 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2117 /*no argument after the command*/
2118 if (NULL == inPtr) return -EINVAL;
2119 /*removing empty spaces*/
2120 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2121
2122 /*no argument followed by spaces*/
2123 if ('\0' == *inPtr)
2124 {
2125 return -EINVAL;
2126 }
2127
2128 /* find the length of data */
2129 dataEnd = inPtr;
2130 while(('\0' != *dataEnd) )
2131 {
2132 dataEnd++;
2133 ++(*pBufLen);
2134 }
2135 if ( *pBufLen <= 0) return -EINVAL;
2136
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002137 /* Allocate the number of bytes based on the number of input characters
2138 whether it is even or odd.
2139 if the number of input characters are even, then we need N/2 byte.
2140 if the number of input characters are odd, then we need do (N+1)/2 to
2141 compensate rounding off.
2142 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2143 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2144 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002145 if (NULL == *pBuf)
2146 {
2147 hddLog(VOS_TRACE_LEVEL_FATAL,
2148 "%s: vos_mem_alloc failed ", __func__);
2149 return -EINVAL;
2150 }
2151
2152 /* the buffer received from the upper layer is character buffer,
2153 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2154 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2155 and f0 in 3rd location */
2156 for (i = 0, j = 0; j < *pBufLen; j += 2)
2157 {
2158 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2159 (*pBuf)[i++] = tempByte;
2160 }
2161 *pBufLen = i;
2162 return VOS_STATUS_SUCCESS;
2163}
2164
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002165/**---------------------------------------------------------------------------
2166
Srinivas Girigowdade697412013-02-14 16:31:48 -08002167 \brief hdd_parse_countryrev() - HDD Parse country code revision
2168
2169 This function parses the country code revision passed in the format
2170 SETCOUNTRYREV<space><Country code><space>revision
2171
2172 \param - pValue Pointer to input country code revision
2173 \param - pCountryCode Pointer to local output array to record country code
2174 \param - pRevision Pointer to store revision integer number
2175
2176 \return - 0 for success non-zero for failure
2177
2178 --------------------------------------------------------------------------*/
2179VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2180{
2181 tANI_U8 *inPtr = pValue;
2182 int tempInt;
2183
2184 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2185 /*no argument after the command*/
2186 if (NULL == inPtr)
2187 {
2188 return -EINVAL;
2189 }
2190
2191 /*no space after the command*/
2192 else if (SPACE_ASCII_VALUE != *inPtr)
2193 {
2194 return -EINVAL;
2195 }
2196
2197 /*removing empty spaces*/
2198 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2199
2200 /*no argument followed by spaces*/
2201 if ('\0' == *inPtr)
2202 {
2203 return -EINVAL;
2204 }
2205
2206 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002207 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002208
2209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2210 "Country code is : %s", pCountryCode);
2211
2212 /*inPtr pointing to the beginning of first space after country code */
2213 inPtr = strpbrk( inPtr, " " );
2214 /*no revision number after the country code argument */
2215 if (NULL == inPtr)
2216 {
2217 return -EINVAL;
2218 }
2219
2220 inPtr++;
2221
2222 /*removing empty space*/
2223 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2224
2225 /*no channel list after the number of channels argument and spaces*/
2226 if (0 == strncmp(pCountryCode, "KR", 2))
2227 {
2228 if ('\0' == *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 sscanf(inPtr, "%d", &tempInt);
2234 *pRevision = tempInt;
2235 }
2236 else
2237 {
2238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2239 "Revision input is required only for Country KR");
2240 return -EINVAL;
2241 }
2242 return VOS_STATUS_SUCCESS;
2243}
2244
2245/**---------------------------------------------------------------------------
2246
2247 \brief hdd_parse_channellist() - HDD Parse channel list
2248
2249 This function parses the channel list passed in the format
2250 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002251 if the Number of channels (N) does not match with the actual number of channels passed
2252 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2253 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2254 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2255 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002256
2257 \param - pValue Pointer to input channel list
2258 \param - ChannelList Pointer to local output array to record channel list
2259 \param - pNumChannels Pointer to number of roam scan channels
2260
2261 \return - 0 for success non-zero for failure
2262
2263 --------------------------------------------------------------------------*/
2264VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2265{
2266 tANI_U8 *inPtr = pValue;
2267 int tempInt;
2268 int j = 0;
2269 int v = 0;
2270 char buf[32];
2271
2272 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2273 /*no argument after the command*/
2274 if (NULL == inPtr)
2275 {
2276 return -EINVAL;
2277 }
2278
2279 /*no space after the command*/
2280 else if (SPACE_ASCII_VALUE != *inPtr)
2281 {
2282 return -EINVAL;
2283 }
2284
2285 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002286 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002287
2288 /*no argument followed by spaces*/
2289 if ('\0' == *inPtr)
2290 {
2291 return -EINVAL;
2292 }
2293
2294 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002295 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002296 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002297 if ((v < 0) ||
2298 (tempInt <= 0) ||
2299 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2300 {
2301 return -EINVAL;
2302 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002303
2304 *pNumChannels = tempInt;
2305
2306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2307 "Number of channels are: %d", *pNumChannels);
2308
2309 for (j = 0; j < (*pNumChannels); j++)
2310 {
2311 /*inPtr pointing to the beginning of first space after number of channels*/
2312 inPtr = strpbrk( inPtr, " " );
2313 /*no channel list after the number of channels argument*/
2314 if (NULL == inPtr)
2315 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002316 if (0 != j)
2317 {
2318 *pNumChannels = j;
2319 return VOS_STATUS_SUCCESS;
2320 }
2321 else
2322 {
2323 return -EINVAL;
2324 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002325 }
2326
2327 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002328 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002329
2330 /*no channel list after the number of channels argument and spaces*/
2331 if ( '\0' == *inPtr )
2332 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002333 if (0 != j)
2334 {
2335 *pNumChannels = j;
2336 return VOS_STATUS_SUCCESS;
2337 }
2338 else
2339 {
2340 return -EINVAL;
2341 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002342 }
2343
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002344 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002346 if ((v < 0) ||
2347 (tempInt <= 0) ||
2348 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2349 {
2350 return -EINVAL;
2351 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002352 pChannelList[j] = tempInt;
2353
2354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2355 "Channel %d added to preferred channel list",
2356 pChannelList[j] );
2357 }
2358
Srinivas Girigowdade697412013-02-14 16:31:48 -08002359 return VOS_STATUS_SUCCESS;
2360}
2361
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002362
2363/**---------------------------------------------------------------------------
2364
2365 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2366
2367 This function parses the reasoc command data passed in the format
2368 REASSOC<space><bssid><space><channel>
2369
2370 \param - pValue Pointer to input country code revision
2371 \param - pTargetApBssid Pointer to target Ap bssid
2372 \param - pChannel Pointer to the Target AP channel
2373
2374 \return - 0 for success non-zero for failure
2375
2376 --------------------------------------------------------------------------*/
2377VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2378{
2379 tANI_U8 *inPtr = pValue;
2380 int tempInt;
2381 int v = 0;
2382 tANI_U8 tempBuf[32];
2383
2384 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2385 /*no argument after the command*/
2386 if (NULL == inPtr)
2387 {
2388 return -EINVAL;
2389 }
2390
2391 /*no space after the command*/
2392 else if (SPACE_ASCII_VALUE != *inPtr)
2393 {
2394 return -EINVAL;
2395 }
2396
2397 /*removing empty spaces*/
2398 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2399
2400 /*no argument followed by spaces*/
2401 if ('\0' == *inPtr)
2402 {
2403 return -EINVAL;
2404 }
2405
2406 /*getting the first argument ie the target AP bssid */
2407 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2408 {
2409 return -EINVAL;
2410 }
2411 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2412 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2413 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2414
2415 /* point to the next argument */
2416 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2417 /*no argument after the command*/
2418 if (NULL == inPtr) return -EINVAL;
2419
2420 /*removing empty spaces*/
2421 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2422
2423 /*no argument followed by spaces*/
2424 if ('\0' == *inPtr)
2425 {
2426 return -EINVAL;
2427 }
2428
2429 /*getting the next argument ie the channel number */
2430 sscanf(inPtr, "%s ", tempBuf);
2431 v = kstrtos32(tempBuf, 10, &tempInt);
2432 if ( v < 0) return -EINVAL;
2433
2434 *pChannel = tempInt;
2435 return VOS_STATUS_SUCCESS;
2436}
2437
2438#endif
2439
Jeff Johnson295189b2012-06-20 16:38:30 -07002440/**---------------------------------------------------------------------------
2441
2442 \brief hdd_open() - HDD Open function
2443
2444 This is called in response to ifconfig up
2445
2446 \param - dev Pointer to net_device structure
2447
2448 \return - 0 for success non-zero for failure
2449
2450 --------------------------------------------------------------------------*/
2451int hdd_open (struct net_device *dev)
2452{
2453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2454 hdd_context_t *pHddCtx;
2455 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2456 VOS_STATUS status;
2457 v_BOOL_t in_standby = TRUE;
2458
2459 if (NULL == pAdapter)
2460 {
2461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002462 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002463 return -ENODEV;
2464 }
2465
2466 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2467 if (NULL == pHddCtx)
2468 {
2469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002470 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 return -ENODEV;
2472 }
2473
2474 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2475 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2476 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002477 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2478 {
2479 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302480 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002481 in_standby = FALSE;
2482 break;
2483 }
2484 else
2485 {
2486 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2487 pAdapterNode = pNext;
2488 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002489 }
2490
2491 if (TRUE == in_standby)
2492 {
2493 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2494 {
2495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2496 "wlan out of power save", __func__);
2497 return -EINVAL;
2498 }
2499 }
2500
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002501 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002505 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002506 /* Enable TX queues only when we are connected */
2507 netif_tx_start_all_queues(dev);
2508 }
2509
2510 return 0;
2511}
2512
2513int hdd_mon_open (struct net_device *dev)
2514{
2515 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2516
2517 if(pAdapter == NULL) {
2518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002519 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002520 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 }
2522
2523 netif_start_queue(dev);
2524
2525 return 0;
2526}
2527/**---------------------------------------------------------------------------
2528
2529 \brief hdd_stop() - HDD stop function
2530
2531 This is called in response to ifconfig down
2532
2533 \param - dev Pointer to net_device structure
2534
2535 \return - 0 for success non-zero for failure
2536
2537 --------------------------------------------------------------------------*/
2538
2539int hdd_stop (struct net_device *dev)
2540{
2541 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2542 hdd_context_t *pHddCtx;
2543 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2544 VOS_STATUS status;
2545 v_BOOL_t enter_standby = TRUE;
2546
2547 ENTER();
2548
2549 if (NULL == pAdapter)
2550 {
2551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002552 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002553 return -ENODEV;
2554 }
2555
2556 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2557 if (NULL == pHddCtx)
2558 {
2559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002560 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002561 return -ENODEV;
2562 }
2563
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002564 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2566 netif_tx_disable(pAdapter->dev);
2567 netif_carrier_off(pAdapter->dev);
2568
2569
2570 /* SoftAP ifaces should never go in power save mode
2571 making sure same here. */
2572 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2573 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002574 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 )
2576 {
2577 /* SoftAP mode, so return from here */
2578 EXIT();
2579 return 0;
2580 }
2581
2582 /* Find if any iface is up then
2583 if any iface is up then can't put device to sleep/ power save mode. */
2584 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2585 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2586 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002587 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2588 {
2589 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302590 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002591 enter_standby = FALSE;
2592 break;
2593 }
2594 else
2595 {
2596 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2597 pAdapterNode = pNext;
2598 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 }
2600
2601 if (TRUE == enter_standby)
2602 {
2603 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2604 "entering standby", __func__);
2605 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2606 {
2607 /*log and return success*/
2608 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2609 "wlan in power save", __func__);
2610 }
2611 }
2612
2613 EXIT();
2614 return 0;
2615}
2616
2617/**---------------------------------------------------------------------------
2618
2619 \brief hdd_uninit() - HDD uninit function
2620
2621 This is called during the netdev unregister to uninitialize all data
2622associated with the device
2623
2624 \param - dev Pointer to net_device structure
2625
2626 \return - void
2627
2628 --------------------------------------------------------------------------*/
2629static void hdd_uninit (struct net_device *dev)
2630{
2631 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2632
2633 ENTER();
2634
2635 do
2636 {
2637 if (NULL == pAdapter)
2638 {
2639 hddLog(VOS_TRACE_LEVEL_FATAL,
2640 "%s: NULL pAdapter", __func__);
2641 break;
2642 }
2643
2644 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2645 {
2646 hddLog(VOS_TRACE_LEVEL_FATAL,
2647 "%s: Invalid magic", __func__);
2648 break;
2649 }
2650
2651 if (NULL == pAdapter->pHddCtx)
2652 {
2653 hddLog(VOS_TRACE_LEVEL_FATAL,
2654 "%s: NULL pHddCtx", __func__);
2655 break;
2656 }
2657
2658 if (dev != pAdapter->dev)
2659 {
2660 hddLog(VOS_TRACE_LEVEL_FATAL,
2661 "%s: Invalid device reference", __func__);
2662 /* we haven't validated all cases so let this go for now */
2663 }
2664
2665 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2666
2667 /* after uninit our adapter structure will no longer be valid */
2668 pAdapter->dev = NULL;
2669 pAdapter->magic = 0;
2670 } while (0);
2671
2672 EXIT();
2673}
2674
2675/**---------------------------------------------------------------------------
2676
2677 \brief hdd_release_firmware() -
2678
2679 This function calls the release firmware API to free the firmware buffer.
2680
2681 \param - pFileName Pointer to the File Name.
2682 pCtx - Pointer to the adapter .
2683
2684
2685 \return - 0 for success, non zero for failure
2686
2687 --------------------------------------------------------------------------*/
2688
2689VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2690{
2691 VOS_STATUS status = VOS_STATUS_SUCCESS;
2692 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2693 ENTER();
2694
2695
2696 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2697
2698 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2699
2700 if(pHddCtx->fw) {
2701 release_firmware(pHddCtx->fw);
2702 pHddCtx->fw = NULL;
2703 }
2704 else
2705 status = VOS_STATUS_E_FAILURE;
2706 }
2707 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2708 if(pHddCtx->nv) {
2709 release_firmware(pHddCtx->nv);
2710 pHddCtx->nv = NULL;
2711 }
2712 else
2713 status = VOS_STATUS_E_FAILURE;
2714
2715 }
2716
2717 EXIT();
2718 return status;
2719}
2720
2721/**---------------------------------------------------------------------------
2722
2723 \brief hdd_request_firmware() -
2724
2725 This function reads the firmware file using the request firmware
2726 API and returns the the firmware data and the firmware file size.
2727
2728 \param - pfileName - Pointer to the file name.
2729 - pCtx - Pointer to the adapter .
2730 - ppfw_data - Pointer to the pointer of the firmware data.
2731 - pSize - Pointer to the file size.
2732
2733 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2734
2735 --------------------------------------------------------------------------*/
2736
2737
2738VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2739{
2740 int status;
2741 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2742 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2743 ENTER();
2744
2745 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2746
2747 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2748
2749 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2750 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2751 __func__, pfileName);
2752 retval = VOS_STATUS_E_FAILURE;
2753 }
2754
2755 else {
2756 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2757 *pSize = pHddCtx->fw->size;
2758 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2759 __func__, *pSize);
2760 }
2761 }
2762 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2763
2764 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2765
2766 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2767 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2768 __func__, pfileName);
2769 retval = VOS_STATUS_E_FAILURE;
2770 }
2771
2772 else {
2773 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2774 *pSize = pHddCtx->nv->size;
2775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2776 __func__, *pSize);
2777 }
2778 }
2779
2780 EXIT();
2781 return retval;
2782}
2783/**---------------------------------------------------------------------------
2784 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2785
2786 This is the function invoked by SME to inform the result of a full power
2787 request issued by HDD
2788
2789 \param - callbackcontext - Pointer to cookie
2790 status - result of request
2791
2792 \return - None
2793
2794--------------------------------------------------------------------------*/
2795void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2796{
2797 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2798
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002799 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002800 if(&pHddCtx->full_pwr_comp_var)
2801 {
2802 complete(&pHddCtx->full_pwr_comp_var);
2803 }
2804}
2805
2806/**---------------------------------------------------------------------------
2807
2808 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2809
2810 This is the function invoked by SME to inform the result of BMPS
2811 request issued by HDD
2812
2813 \param - callbackcontext - Pointer to cookie
2814 status - result of request
2815
2816 \return - None
2817
2818--------------------------------------------------------------------------*/
2819void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2820{
2821
2822 struct completion *completion_var = (struct completion*) callbackContext;
2823
2824 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2825 if(completion_var != NULL)
2826 {
2827 complete(completion_var);
2828 }
2829}
2830
2831/**---------------------------------------------------------------------------
2832
2833 \brief hdd_get_cfg_file_size() -
2834
2835 This function reads the configuration file using the request firmware
2836 API and returns the configuration file size.
2837
2838 \param - pCtx - Pointer to the adapter .
2839 - pFileName - Pointer to the file name.
2840 - pBufSize - Pointer to the buffer size.
2841
2842 \return - 0 for success, non zero for failure
2843
2844 --------------------------------------------------------------------------*/
2845
2846VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2847{
2848 int status;
2849 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2850
2851 ENTER();
2852
2853 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2854
2855 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2857 status = VOS_STATUS_E_FAILURE;
2858 }
2859 else {
2860 *pBufSize = pHddCtx->fw->size;
2861 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2862 release_firmware(pHddCtx->fw);
2863 pHddCtx->fw = NULL;
2864 }
2865
2866 EXIT();
2867 return VOS_STATUS_SUCCESS;
2868}
2869
2870/**---------------------------------------------------------------------------
2871
2872 \brief hdd_read_cfg_file() -
2873
2874 This function reads the configuration file using the request firmware
2875 API and returns the cfg data and the buffer size of the configuration file.
2876
2877 \param - pCtx - Pointer to the adapter .
2878 - pFileName - Pointer to the file name.
2879 - pBuffer - Pointer to the data buffer.
2880 - pBufSize - Pointer to the buffer size.
2881
2882 \return - 0 for success, non zero for failure
2883
2884 --------------------------------------------------------------------------*/
2885
2886VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2887 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2888{
2889 int status;
2890 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2891
2892 ENTER();
2893
2894 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2895
2896 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2897 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2898 return VOS_STATUS_E_FAILURE;
2899 }
2900 else {
2901 if(*pBufSize != pHddCtx->fw->size) {
2902 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2903 "file size", __func__);
2904 release_firmware(pHddCtx->fw);
2905 pHddCtx->fw = NULL;
2906 return VOS_STATUS_E_FAILURE;
2907 }
2908 else {
2909 if(pBuffer) {
2910 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2911 }
2912 release_firmware(pHddCtx->fw);
2913 pHddCtx->fw = NULL;
2914 }
2915 }
2916
2917 EXIT();
2918
2919 return VOS_STATUS_SUCCESS;
2920}
2921
2922/**---------------------------------------------------------------------------
2923
Jeff Johnson295189b2012-06-20 16:38:30 -07002924 \brief hdd_set_mac_address() -
2925
2926 This function sets the user specified mac address using
2927 the command ifconfig wlanX hw ether <mac adress>.
2928
2929 \param - dev - Pointer to the net device.
2930 - addr - Pointer to the sockaddr.
2931 \return - 0 for success, non zero for failure
2932
2933 --------------------------------------------------------------------------*/
2934
2935static int hdd_set_mac_address(struct net_device *dev, void *addr)
2936{
2937 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2938 struct sockaddr *psta_mac_addr = addr;
2939 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2940
2941 ENTER();
2942
2943 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2944
2945#ifdef HDD_SESSIONIZE
2946 // set the MAC address though the STA ID CFG.
2947 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2948 (v_U8_t *)&pAdapter->macAddressCurrent,
2949 sizeof( pAdapter->macAddressCurrent ),
2950 hdd_set_mac_addr_cb, VOS_FALSE );
2951#endif
2952
2953 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2954
2955 EXIT();
2956 return halStatus;
2957}
2958
2959tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2960{
2961 int i;
2962 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2963 {
2964 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2965 break;
2966 }
2967
2968 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2969 return NULL;
2970
2971 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2972 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2973}
2974
2975void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2976{
2977 int i;
2978 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2979 {
2980 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2981 {
2982 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2983 break;
2984 }
2985 }
2986 return;
2987}
2988
2989#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2990 static struct net_device_ops wlan_drv_ops = {
2991 .ndo_open = hdd_open,
2992 .ndo_stop = hdd_stop,
2993 .ndo_uninit = hdd_uninit,
2994 .ndo_start_xmit = hdd_hard_start_xmit,
2995 .ndo_tx_timeout = hdd_tx_timeout,
2996 .ndo_get_stats = hdd_stats,
2997 .ndo_do_ioctl = hdd_ioctl,
2998 .ndo_set_mac_address = hdd_set_mac_address,
2999 .ndo_select_queue = hdd_select_queue,
3000#ifdef WLAN_FEATURE_PACKET_FILTERING
3001#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3002 .ndo_set_rx_mode = hdd_set_multicast_list,
3003#else
3004 .ndo_set_multicast_list = hdd_set_multicast_list,
3005#endif //LINUX_VERSION_CODE
3006#endif
3007 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003008 static struct net_device_ops wlan_mon_drv_ops = {
3009 .ndo_open = hdd_mon_open,
3010 .ndo_stop = hdd_stop,
3011 .ndo_uninit = hdd_uninit,
3012 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3013 .ndo_tx_timeout = hdd_tx_timeout,
3014 .ndo_get_stats = hdd_stats,
3015 .ndo_do_ioctl = hdd_ioctl,
3016 .ndo_set_mac_address = hdd_set_mac_address,
3017 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003018
3019#endif
3020
3021void hdd_set_station_ops( struct net_device *pWlanDev )
3022{
3023#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3024 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3025 pWlanDev->netdev_ops = &wlan_drv_ops;
3026#else
3027 pWlanDev->open = hdd_open;
3028 pWlanDev->stop = hdd_stop;
3029 pWlanDev->uninit = hdd_uninit;
3030 pWlanDev->hard_start_xmit = NULL;
3031 pWlanDev->tx_timeout = hdd_tx_timeout;
3032 pWlanDev->get_stats = hdd_stats;
3033 pWlanDev->do_ioctl = hdd_ioctl;
3034 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3035 pWlanDev->set_mac_address = hdd_set_mac_address;
3036#endif
3037}
3038
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003039static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003040{
3041 struct net_device *pWlanDev = NULL;
3042 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003043 /*
3044 * cfg80211 initialization and registration....
3045 */
3046 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3047
Jeff Johnson295189b2012-06-20 16:38:30 -07003048 if(pWlanDev != NULL)
3049 {
3050
3051 //Save the pointer to the net_device in the HDD adapter
3052 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3053
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3055
3056 pAdapter->dev = pWlanDev;
3057 pAdapter->pHddCtx = pHddCtx;
3058 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3059
3060 init_completion(&pAdapter->session_open_comp_var);
3061 init_completion(&pAdapter->session_close_comp_var);
3062 init_completion(&pAdapter->disconnect_comp_var);
3063 init_completion(&pAdapter->linkup_event_var);
3064 init_completion(&pAdapter->cancel_rem_on_chan_var);
3065 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003066#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3067 init_completion(&pAdapter->offchannel_tx_event);
3068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003070#ifdef FEATURE_WLAN_TDLS
3071 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003072 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003073 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003074#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003075 init_completion(&pHddCtx->mc_sus_event_var);
3076 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003077 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003078
Jeff Johnson295189b2012-06-20 16:38:30 -07003079 pAdapter->isLinkUpSvcNeeded = FALSE;
3080 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3081 //Init the net_device structure
3082 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3083
3084 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3085 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3086 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3087 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3088
3089 hdd_set_station_ops( pAdapter->dev );
3090
3091 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3093 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3094 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003095 /* set pWlanDev's parent to underlying device */
3096 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3097 }
3098
3099 return pAdapter;
3100}
3101
3102VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3103{
3104 struct net_device *pWlanDev = pAdapter->dev;
3105 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3106 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3107 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3108
3109 if( rtnl_lock_held )
3110 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003111 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003112 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3113 {
3114 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3115 return VOS_STATUS_E_FAILURE;
3116 }
3117 }
3118 if (register_netdevice(pWlanDev))
3119 {
3120 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3121 return VOS_STATUS_E_FAILURE;
3122 }
3123 }
3124 else
3125 {
3126 if(register_netdev(pWlanDev))
3127 {
3128 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3129 return VOS_STATUS_E_FAILURE;
3130 }
3131 }
3132 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3133
3134 return VOS_STATUS_SUCCESS;
3135}
3136
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003137static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003138{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003139 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003140
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003141 if (NULL == pAdapter)
3142 {
3143 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3144 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003146
3147 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3148 {
3149 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3150 return eHAL_STATUS_NOT_INITIALIZED;
3151 }
3152
3153 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3154
3155 /* need to make sure all of our scheduled work has completed.
3156 * This callback is called from MC thread context, so it is safe to
3157 * to call below flush workqueue API from here.
3158 */
3159 flush_scheduled_work();
3160
3161 /* We can be blocked while waiting for scheduled work to be
3162 * flushed, and the adapter structure can potentially be freed, in
3163 * which case the magic will have been reset. So make sure the
3164 * magic is still good, and hence the adapter structure is still
3165 * valid, before signaling completion */
3166 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3167 {
3168 complete(&pAdapter->session_close_comp_var);
3169 }
3170
Jeff Johnson295189b2012-06-20 16:38:30 -07003171 return eHAL_STATUS_SUCCESS;
3172}
3173
3174VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3175{
3176 struct net_device *pWlanDev = pAdapter->dev;
3177 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3178 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3179 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3180 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3181 int rc = 0;
3182
3183 INIT_COMPLETION(pAdapter->session_open_comp_var);
3184 //Open a SME session for future operation
3185 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3186 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3187 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3188 {
3189 hddLog(VOS_TRACE_LEVEL_FATAL,
3190 "sme_OpenSession() failed with status code %08d [x%08lx]",
3191 halStatus, halStatus );
3192 status = VOS_STATUS_E_FAILURE;
3193 goto error_sme_open;
3194 }
3195
3196 //Block on a completion variable. Can't wait forever though.
3197 rc = wait_for_completion_interruptible_timeout(
3198 &pAdapter->session_open_comp_var,
3199 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3200 if (!rc)
3201 {
3202 hddLog(VOS_TRACE_LEVEL_FATAL,
3203 "Session is not opened within timeout period code %08d", rc );
3204 status = VOS_STATUS_E_FAILURE;
3205 goto error_sme_open;
3206 }
3207
3208 // Register wireless extensions
3209 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3210 {
3211 hddLog(VOS_TRACE_LEVEL_FATAL,
3212 "hdd_register_wext() failed with status code %08d [x%08lx]",
3213 halStatus, halStatus );
3214 status = VOS_STATUS_E_FAILURE;
3215 goto error_register_wext;
3216 }
3217 //Safe to register the hard_start_xmit function again
3218#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3219 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3220#else
3221 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3222#endif
3223
3224 //Set the Connection State to Not Connected
3225 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3226
3227 //Set the default operation channel
3228 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3229
3230 /* Make the default Auth Type as OPEN*/
3231 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3232
3233 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3234 {
3235 hddLog(VOS_TRACE_LEVEL_FATAL,
3236 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3237 status, status );
3238 goto error_init_txrx;
3239 }
3240
3241 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3242
3243 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3244 {
3245 hddLog(VOS_TRACE_LEVEL_FATAL,
3246 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3247 status, status );
3248 goto error_wmm_init;
3249 }
3250
3251 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3252
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003253#ifdef FEATURE_WLAN_TDLS
3254 if(0 != wlan_hdd_tdls_init(pAdapter))
3255 {
3256 status = VOS_STATUS_E_FAILURE;
3257 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3258 goto error_tdls_init;
3259 }
3260 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3261#endif
3262
Jeff Johnson295189b2012-06-20 16:38:30 -07003263 return VOS_STATUS_SUCCESS;
3264
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003265#ifdef FEATURE_WLAN_TDLS
3266error_tdls_init:
3267 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3268 hdd_wmm_adapter_close(pAdapter);
3269#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003270error_wmm_init:
3271 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3272 hdd_deinit_tx_rx(pAdapter);
3273error_init_txrx:
3274 hdd_UnregisterWext(pWlanDev);
3275error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003276 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003277 {
3278 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003279 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003281 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003282 {
3283 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003284 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003286 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003287 }
3288}
3289error_sme_open:
3290 return status;
3291}
3292
Jeff Johnson295189b2012-06-20 16:38:30 -07003293void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3294{
3295 hdd_cfg80211_state_t *cfgState;
3296
3297 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3298
3299 if( NULL != cfgState->buf )
3300 {
3301 int rc;
3302 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3303 rc = wait_for_completion_interruptible_timeout(
3304 &pAdapter->tx_action_cnf_event,
3305 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3306 if(!rc)
3307 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003308 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003309 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3310 }
3311 }
3312 return;
3313}
Jeff Johnson295189b2012-06-20 16:38:30 -07003314
3315void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3316{
3317 ENTER();
3318 switch ( pAdapter->device_mode )
3319 {
3320 case WLAN_HDD_INFRA_STATION:
3321 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003322 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003323 {
3324 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3325 {
3326 hdd_deinit_tx_rx( pAdapter );
3327 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3328 }
3329
3330 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3331 {
3332 hdd_wmm_adapter_close( pAdapter );
3333 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3334 }
3335
Jeff Johnson295189b2012-06-20 16:38:30 -07003336 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003337#ifdef FEATURE_WLAN_TDLS
3338 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3339 {
3340 wlan_hdd_tdls_exit(pAdapter);
3341 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3342 }
3343#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003344
3345 break;
3346 }
3347
3348 case WLAN_HDD_SOFTAP:
3349 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003350 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003352
3353 hdd_unregister_hostapd(pAdapter);
3354 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003355 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003356 break;
3357 }
3358
3359 case WLAN_HDD_MONITOR:
3360 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003362 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3363 {
3364 hdd_deinit_tx_rx( pAdapter );
3365 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003367 if(NULL != pAdapterforTx)
3368 {
3369 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3370 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 break;
3372 }
3373
3374
3375 default:
3376 break;
3377 }
3378
3379 EXIT();
3380}
3381
3382void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3383{
3384 struct net_device *pWlanDev = pAdapter->dev;
3385
3386 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3387 if( rtnl_held )
3388 {
3389 unregister_netdevice(pWlanDev);
3390 }
3391 else
3392 {
3393 unregister_netdev(pWlanDev);
3394 }
3395 // note that the pAdapter is no longer valid at this point
3396 // since the memory has been reclaimed
3397 }
3398
3399}
3400
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003401void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3402{
3403 tSirSetPowerParamsReq powerRequest = { 0 };
3404
3405 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -07003406 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003407
3408 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3409 {
3410 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3411 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3412 }
3413 else
3414 {
3415 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3416 }
3417
3418 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3419 *specified during Enter/Exit BMPS when LCD off*/
3420 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3421 NULL, eANI_BOOLEAN_FALSE);
3422 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3423 NULL, eANI_BOOLEAN_FALSE);
3424
3425 /* switch to the DTIM specified in cfg.ini */
3426 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3427 "Switch to DTIM%d", powerRequest.uListenInterval);
3428 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3429
3430}
3431
3432void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3433{
3434 /*Switch back to DTIM 1*/
3435 tSirSetPowerParamsReq powerRequest = { 0 };
3436
3437 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3438 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003439 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003440
3441 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3442 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3443 NULL, eANI_BOOLEAN_FALSE);
3444 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3445 NULL, eANI_BOOLEAN_FALSE);
3446
3447 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3448 "Switch to DTIM%d",powerRequest.uListenInterval);
3449 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3450
3451}
3452
Jeff Johnson295189b2012-06-20 16:38:30 -07003453VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3454{
3455 VOS_STATUS status = VOS_STATUS_SUCCESS;
3456
3457 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3458 {
3459 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3460 }
3461
3462 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3463 {
3464 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3465 }
3466
3467 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3468 {
3469 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3470 }
3471
3472 return status;
3473}
3474
3475VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3476{
3477 hdd_adapter_t *pAdapter = NULL;
3478 eHalStatus halStatus;
3479 VOS_STATUS status = VOS_STATUS_E_INVAL;
3480 v_BOOL_t disableBmps = FALSE;
3481 v_BOOL_t disableImps = FALSE;
3482
3483 switch(session_type)
3484 {
3485 case WLAN_HDD_INFRA_STATION:
3486 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003487 case WLAN_HDD_P2P_CLIENT:
3488 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003489 //Exit BMPS -> Is Sta/P2P Client is already connected
3490 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3491 if((NULL != pAdapter)&&
3492 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3493 {
3494 disableBmps = TRUE;
3495 }
3496
3497 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3498 if((NULL != pAdapter)&&
3499 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3500 {
3501 disableBmps = TRUE;
3502 }
3503
3504 //Exit both Bmps and Imps incase of Go/SAP Mode
3505 if((WLAN_HDD_SOFTAP == session_type) ||
3506 (WLAN_HDD_P2P_GO == session_type))
3507 {
3508 disableBmps = TRUE;
3509 disableImps = TRUE;
3510 }
3511
3512 if(TRUE == disableImps)
3513 {
3514 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3515 {
3516 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3517 }
3518 }
3519
3520 if(TRUE == disableBmps)
3521 {
3522 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3523 {
3524 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3525
3526 if(eHAL_STATUS_SUCCESS != halStatus)
3527 {
3528 status = VOS_STATUS_E_FAILURE;
3529 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3530 VOS_ASSERT(0);
3531 return status;
3532 }
3533 }
3534
3535 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3536 {
3537 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3538
3539 if(eHAL_STATUS_SUCCESS != halStatus)
3540 {
3541 status = VOS_STATUS_E_FAILURE;
3542 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3543 VOS_ASSERT(0);
3544 return status;
3545 }
3546 }
3547 }
3548
3549 if((TRUE == disableBmps) ||
3550 (TRUE == disableImps))
3551 {
3552 /* Now, get the chip into Full Power now */
3553 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3554 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3555 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3556
3557 if(halStatus != eHAL_STATUS_SUCCESS)
3558 {
3559 if(halStatus == eHAL_STATUS_PMC_PENDING)
3560 {
3561 //Block on a completion variable. Can't wait forever though
3562 wait_for_completion_interruptible_timeout(
3563 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3564 }
3565 else
3566 {
3567 status = VOS_STATUS_E_FAILURE;
3568 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3569 VOS_ASSERT(0);
3570 return status;
3571 }
3572 }
3573
3574 status = VOS_STATUS_SUCCESS;
3575 }
3576
3577 break;
3578 }
3579 return status;
3580}
3581
3582hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003583 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 tANI_U8 rtnl_held )
3585{
3586 hdd_adapter_t *pAdapter = NULL;
3587 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3588 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3589 VOS_STATUS exitbmpsStatus;
3590
3591 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3592
3593 //Disable BMPS incase of Concurrency
3594 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3595
3596 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3597 {
3598 //Fail to Exit BMPS
3599 VOS_ASSERT(0);
3600 return NULL;
3601 }
3602
3603 switch(session_type)
3604 {
3605 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003606 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003607 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003608 {
3609 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3610
3611 if( NULL == pAdapter )
3612 return NULL;
3613
Jeff Johnsone7245742012-09-05 17:12:55 -07003614 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3615 NL80211_IFTYPE_P2P_CLIENT:
3616 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003617
Jeff Johnson295189b2012-06-20 16:38:30 -07003618 pAdapter->device_mode = session_type;
3619
3620 status = hdd_init_station_mode( pAdapter );
3621 if( VOS_STATUS_SUCCESS != status )
3622 goto err_free_netdev;
3623
3624 status = hdd_register_interface( pAdapter, rtnl_held );
3625 if( VOS_STATUS_SUCCESS != status )
3626 {
3627 hdd_deinit_adapter(pHddCtx, pAdapter);
3628 goto err_free_netdev;
3629 }
3630 //Stop the Interface TX queue.
3631 netif_tx_disable(pAdapter->dev);
3632 //netif_tx_disable(pWlanDev);
3633 netif_carrier_off(pAdapter->dev);
3634
3635 break;
3636 }
3637
Jeff Johnson295189b2012-06-20 16:38:30 -07003638 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003639 case WLAN_HDD_SOFTAP:
3640 {
3641 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3642 if( NULL == pAdapter )
3643 return NULL;
3644
Jeff Johnson295189b2012-06-20 16:38:30 -07003645 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3646 NL80211_IFTYPE_AP:
3647 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003648 pAdapter->device_mode = session_type;
3649
3650 status = hdd_init_ap_mode(pAdapter);
3651 if( VOS_STATUS_SUCCESS != status )
3652 goto err_free_netdev;
3653
3654 status = hdd_register_hostapd( pAdapter, rtnl_held );
3655 if( VOS_STATUS_SUCCESS != status )
3656 {
3657 hdd_deinit_adapter(pHddCtx, pAdapter);
3658 goto err_free_netdev;
3659 }
3660
3661 netif_tx_disable(pAdapter->dev);
3662 netif_carrier_off(pAdapter->dev);
3663
3664 hdd_set_conparam( 1 );
3665 break;
3666 }
3667 case WLAN_HDD_MONITOR:
3668 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3670 if( NULL == pAdapter )
3671 return NULL;
3672
3673 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3674 pAdapter->device_mode = session_type;
3675 status = hdd_register_interface( pAdapter, rtnl_held );
3676#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3677 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3678#else
3679 pAdapter->dev->open = hdd_mon_open;
3680 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3681#endif
3682 hdd_init_tx_rx( pAdapter );
3683 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3684 //Set adapter to be used for data tx. It will use either GO or softap.
3685 pAdapter->sessionCtx.monitor.pAdapterForTx =
3686 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003687 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3688 {
3689 pAdapter->sessionCtx.monitor.pAdapterForTx =
3690 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3691 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 /* This workqueue will be used to transmit management packet over
3693 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003694 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3695 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3696 return NULL;
3697 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003698
Jeff Johnson295189b2012-06-20 16:38:30 -07003699 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3700 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003701 }
3702 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 case WLAN_HDD_FTM:
3704 {
3705 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3706
3707 if( NULL == pAdapter )
3708 return NULL;
3709 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3710 * message while loading driver in FTM mode. */
3711 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3712 pAdapter->device_mode = session_type;
3713 status = hdd_register_interface( pAdapter, rtnl_held );
3714 }
3715 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003716 default:
3717 {
3718 VOS_ASSERT(0);
3719 return NULL;
3720 }
3721 }
3722
3723
3724 if( VOS_STATUS_SUCCESS == status )
3725 {
3726 //Add it to the hdd's session list.
3727 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3728 if( NULL == pHddAdapterNode )
3729 {
3730 status = VOS_STATUS_E_NOMEM;
3731 }
3732 else
3733 {
3734 pHddAdapterNode->pAdapter = pAdapter;
3735 status = hdd_add_adapter_back ( pHddCtx,
3736 pHddAdapterNode );
3737 }
3738 }
3739
3740 if( VOS_STATUS_SUCCESS != status )
3741 {
3742 if( NULL != pAdapter )
3743 {
3744 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3745 pAdapter = NULL;
3746 }
3747 if( NULL != pHddAdapterNode )
3748 {
3749 vos_mem_free( pHddAdapterNode );
3750 }
3751
3752 goto resume_bmps;
3753 }
3754
3755 if(VOS_STATUS_SUCCESS == status)
3756 {
3757 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3758
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003759 //Initialize the WoWL service
3760 if(!hdd_init_wowl(pAdapter))
3761 {
3762 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3763 goto err_free_netdev;
3764 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003765 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 return pAdapter;
3767
3768err_free_netdev:
3769 free_netdev(pAdapter->dev);
3770 wlan_hdd_release_intf_addr( pHddCtx,
3771 pAdapter->macAddressCurrent.bytes );
3772
3773resume_bmps:
3774 //If bmps disabled enable it
3775 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3776 {
3777 hdd_enable_bmps_imps(pHddCtx);
3778 }
3779 return NULL;
3780}
3781
3782VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3783 tANI_U8 rtnl_held )
3784{
3785 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3786 VOS_STATUS status;
3787
3788 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3789 if( VOS_STATUS_SUCCESS != status )
3790 return status;
3791
3792 while ( pCurrent->pAdapter != pAdapter )
3793 {
3794 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3795 if( VOS_STATUS_SUCCESS != status )
3796 break;
3797
3798 pCurrent = pNext;
3799 }
3800 pAdapterNode = pCurrent;
3801 if( VOS_STATUS_SUCCESS == status )
3802 {
3803 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3804 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3805 hdd_remove_adapter( pHddCtx, pAdapterNode );
3806 vos_mem_free( pAdapterNode );
3807
Jeff Johnson295189b2012-06-20 16:38:30 -07003808
3809 /* If there is a single session of STA/P2P client, re-enable BMPS */
3810 if ((!vos_concurrent_sessions_running()) &&
3811 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3812 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3813 {
3814 hdd_enable_bmps_imps(pHddCtx);
3815 }
3816
3817 return VOS_STATUS_SUCCESS;
3818 }
3819
3820 return VOS_STATUS_E_FAILURE;
3821}
3822
3823VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3824{
3825 hdd_adapter_list_node_t *pHddAdapterNode;
3826 VOS_STATUS status;
3827
3828 ENTER();
3829
3830 do
3831 {
3832 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3833 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3834 {
3835 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3836 vos_mem_free( pHddAdapterNode );
3837 }
3838 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3839
3840 EXIT();
3841
3842 return VOS_STATUS_SUCCESS;
3843}
3844
3845void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3846{
3847 v_U8_t addIE[1] = {0};
3848
3849 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3850 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3851 eANI_BOOLEAN_FALSE) )
3852 {
3853 hddLog(LOGE,
3854 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3855 }
3856
3857 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3858 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3859 eANI_BOOLEAN_FALSE) )
3860 {
3861 hddLog(LOGE,
3862 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3863 }
3864
3865 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3866 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3867 eANI_BOOLEAN_FALSE) )
3868 {
3869 hddLog(LOGE,
3870 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3871 }
3872}
3873
3874VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3875{
3876 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3877 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3878 union iwreq_data wrqu;
3879
3880 ENTER();
3881
3882 switch(pAdapter->device_mode)
3883 {
3884 case WLAN_HDD_INFRA_STATION:
3885 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003886 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3888 {
3889 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3890 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3891 pAdapter->sessionId,
3892 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3893 else
3894 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3895 pAdapter->sessionId,
3896 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3897 //success implies disconnect command got queued up successfully
3898 if(halStatus == eHAL_STATUS_SUCCESS)
3899 {
3900 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3901 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3902 }
3903 memset(&wrqu, '\0', sizeof(wrqu));
3904 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3905 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3906 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3907 }
3908 else
3909 {
3910 hdd_abort_mac_scan(pHddCtx);
3911 }
3912
3913 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3914 {
3915 INIT_COMPLETION(pAdapter->session_close_comp_var);
3916 if (eHAL_STATUS_SUCCESS ==
3917 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3918 hdd_smeCloseSessionCallback, pAdapter))
3919 {
3920 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003921 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 &pAdapter->session_close_comp_var,
3923 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3924 }
3925 }
3926
3927 break;
3928
3929 case WLAN_HDD_SOFTAP:
3930 case WLAN_HDD_P2P_GO:
3931 //Any softap specific cleanup here...
3932 mutex_lock(&pHddCtx->sap_lock);
3933 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3934 {
3935 VOS_STATUS status;
3936 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3937
3938 //Stop Bss.
3939 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3940 if (VOS_IS_STATUS_SUCCESS(status))
3941 {
3942 hdd_hostapd_state_t *pHostapdState =
3943 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3944
3945 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3946
3947 if (!VOS_IS_STATUS_SUCCESS(status))
3948 {
3949 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003950 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003951 }
3952 }
3953 else
3954 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003955 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003956 }
3957 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3958
3959 if (eHAL_STATUS_FAILURE ==
3960 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3961 0, NULL, eANI_BOOLEAN_FALSE))
3962 {
3963 hddLog(LOGE,
3964 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003965 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003966 }
3967
3968 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3969 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3970 eANI_BOOLEAN_FALSE) )
3971 {
3972 hddLog(LOGE,
3973 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3974 }
3975
3976 // Reset WNI_CFG_PROBE_RSP Flags
3977 wlan_hdd_reset_prob_rspies(pAdapter);
3978 kfree(pAdapter->sessionCtx.ap.beacon);
3979 pAdapter->sessionCtx.ap.beacon = NULL;
3980 }
3981 mutex_unlock(&pHddCtx->sap_lock);
3982 break;
3983 case WLAN_HDD_MONITOR:
3984 break;
3985 default:
3986 break;
3987 }
3988
3989 EXIT();
3990 return VOS_STATUS_SUCCESS;
3991}
3992
3993VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3994{
3995 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3996 VOS_STATUS status;
3997 hdd_adapter_t *pAdapter;
3998
3999 ENTER();
4000
4001 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4002
4003 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4004 {
4005 pAdapter = pAdapterNode->pAdapter;
4006 netif_tx_disable(pAdapter->dev);
4007 netif_carrier_off(pAdapter->dev);
4008
4009 hdd_stop_adapter( pHddCtx, pAdapter );
4010
4011 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4012 pAdapterNode = pNext;
4013 }
4014
4015 EXIT();
4016
4017 return VOS_STATUS_SUCCESS;
4018}
4019
4020VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4021{
4022 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4023 VOS_STATUS status;
4024 hdd_adapter_t *pAdapter;
4025
4026 ENTER();
4027
4028 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4029
4030 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4031 {
4032 pAdapter = pAdapterNode->pAdapter;
4033 netif_tx_disable(pAdapter->dev);
4034 netif_carrier_off(pAdapter->dev);
4035
4036 //Record whether STA is associated
4037 pAdapter->sessionCtx.station.bSendDisconnect =
4038 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
4039 VOS_TRUE : VOS_FALSE;
4040
4041 hdd_deinit_tx_rx(pAdapter);
4042 hdd_wmm_adapter_close(pAdapter);
4043
4044 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4045 pAdapterNode = pNext;
4046 }
4047
4048 EXIT();
4049
4050 return VOS_STATUS_SUCCESS;
4051}
4052
4053VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4054{
4055 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4056 VOS_STATUS status;
4057 hdd_adapter_t *pAdapter;
4058 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
4059
4060 ENTER();
4061
4062 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4063
4064 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4065 {
4066 pAdapter = pAdapterNode->pAdapter;
4067
4068 switch(pAdapter->device_mode)
4069 {
4070 case WLAN_HDD_INFRA_STATION:
4071 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004072 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 hdd_init_station_mode(pAdapter);
4074 /* Open the gates for HDD to receive Wext commands */
4075 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004076 pHddCtx->scan_info.mScanPending = FALSE;
4077 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004078
4079 //Trigger the initial scan
4080 hdd_wlan_initial_scan(pAdapter);
4081
4082 //Indicate disconnect event to supplicant if associated previously
4083 if(pAdapter->sessionCtx.station.bSendDisconnect)
4084 {
4085 union iwreq_data wrqu;
4086 memset(&wrqu, '\0', sizeof(wrqu));
4087 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4088 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4089 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4090 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
4091
Jeff Johnson295189b2012-06-20 16:38:30 -07004092 /* indicate disconnected event to nl80211 */
4093 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4094 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 }
4096 break;
4097
4098 case WLAN_HDD_SOFTAP:
4099 /* softAP can handle SSR */
4100 break;
4101
4102 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004103 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4104 __func__);
4105 /* event supplicant to restart */
4106 cfg80211_del_sta(pAdapter->dev,
4107 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 break;
4109
4110 case WLAN_HDD_MONITOR:
4111 /* monitor interface start */
4112 break;
4113 default:
4114 break;
4115 }
4116
4117 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4118 pAdapterNode = pNext;
4119 }
4120
4121 EXIT();
4122
4123 return VOS_STATUS_SUCCESS;
4124}
4125
4126VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4127{
4128 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4129 hdd_adapter_t *pAdapter;
4130 VOS_STATUS status;
4131 v_U32_t roamId;
4132
4133 ENTER();
4134
4135 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4136
4137 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4138 {
4139 pAdapter = pAdapterNode->pAdapter;
4140
4141 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4142 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4143 {
4144 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4145 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4146
4147 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4148 init_completion(&pAdapter->disconnect_comp_var);
4149 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4150 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4151
4152 wait_for_completion_interruptible_timeout(
4153 &pAdapter->disconnect_comp_var,
4154 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4155
4156 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4157 pHddCtx->isAmpAllowed = VOS_FALSE;
4158 sme_RoamConnect(pHddCtx->hHal,
4159 pAdapter->sessionId, &(pWextState->roamProfile),
4160 &roamId);
4161 }
4162
4163 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4164 pAdapterNode = pNext;
4165 }
4166
4167 EXIT();
4168
4169 return VOS_STATUS_SUCCESS;
4170}
4171
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004172void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4173{
4174 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4175 VOS_STATUS status;
4176 hdd_adapter_t *pAdapter;
4177 hdd_station_ctx_t *pHddStaCtx;
4178 hdd_ap_ctx_t *pHddApCtx;
4179 hdd_hostapd_state_t * pHostapdState;
4180 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4181 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4182 const char *p2pMode = "DEV";
4183 const char *ccMode = "Standalone";
4184 int n;
4185
4186 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4187 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4188 {
4189 pAdapter = pAdapterNode->pAdapter;
4190 switch (pAdapter->device_mode) {
4191 case WLAN_HDD_INFRA_STATION:
4192 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4193 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4194 staChannel = pHddStaCtx->conn_info.operationChannel;
4195 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4196 }
4197 break;
4198 case WLAN_HDD_P2P_CLIENT:
4199 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4200 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4201 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4202 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4203 p2pMode = "CLI";
4204 }
4205 break;
4206 case WLAN_HDD_P2P_GO:
4207 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4208 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4209 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4210 p2pChannel = pHddApCtx->operatingChannel;
4211 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4212 }
4213 p2pMode = "GO";
4214 break;
4215 case WLAN_HDD_SOFTAP:
4216 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4217 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4218 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4219 apChannel = pHddApCtx->operatingChannel;
4220 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4221 }
4222 break;
4223 default:
4224 break;
4225 }
4226 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4227 pAdapterNode = pNext;
4228 }
4229 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4230 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4231 }
4232 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4233 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4234 if (p2pChannel > 0) {
4235 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4236 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4237 }
4238 if (apChannel > 0) {
4239 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4240 apChannel, MAC_ADDR_ARRAY(apBssid));
4241 }
4242
4243 if (p2pChannel > 0 && apChannel > 0) {
4244 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4245 }
4246}
4247
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004248bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004249{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004250 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004251}
4252
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004253/* Once SSR is disabled then it cannot be set. */
4254void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004255{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004256 if (HDD_SSR_DISABLED == isSsrRequired)
4257 return;
4258
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 isSsrRequired = value;
4260}
4261
4262VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4263 hdd_adapter_list_node_t** ppAdapterNode)
4264{
4265 VOS_STATUS status;
4266 spin_lock(&pHddCtx->hddAdapters.lock);
4267 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4268 (hdd_list_node_t**) ppAdapterNode );
4269 spin_unlock(&pHddCtx->hddAdapters.lock);
4270 return status;
4271}
4272
4273VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4274 hdd_adapter_list_node_t* pAdapterNode,
4275 hdd_adapter_list_node_t** pNextAdapterNode)
4276{
4277 VOS_STATUS status;
4278 spin_lock(&pHddCtx->hddAdapters.lock);
4279 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4280 (hdd_list_node_t*) pAdapterNode,
4281 (hdd_list_node_t**)pNextAdapterNode );
4282
4283 spin_unlock(&pHddCtx->hddAdapters.lock);
4284 return status;
4285}
4286
4287VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4288 hdd_adapter_list_node_t* pAdapterNode)
4289{
4290 VOS_STATUS status;
4291 spin_lock(&pHddCtx->hddAdapters.lock);
4292 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4293 &pAdapterNode->node );
4294 spin_unlock(&pHddCtx->hddAdapters.lock);
4295 return status;
4296}
4297
4298VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4299 hdd_adapter_list_node_t** ppAdapterNode)
4300{
4301 VOS_STATUS status;
4302 spin_lock(&pHddCtx->hddAdapters.lock);
4303 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4304 (hdd_list_node_t**) ppAdapterNode );
4305 spin_unlock(&pHddCtx->hddAdapters.lock);
4306 return status;
4307}
4308
4309VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4310 hdd_adapter_list_node_t* pAdapterNode)
4311{
4312 VOS_STATUS status;
4313 spin_lock(&pHddCtx->hddAdapters.lock);
4314 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4315 (hdd_list_node_t*) pAdapterNode );
4316 spin_unlock(&pHddCtx->hddAdapters.lock);
4317 return status;
4318}
4319
4320VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4321 hdd_adapter_list_node_t* pAdapterNode)
4322{
4323 VOS_STATUS status;
4324 spin_lock(&pHddCtx->hddAdapters.lock);
4325 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4326 (hdd_list_node_t*) pAdapterNode );
4327 spin_unlock(&pHddCtx->hddAdapters.lock);
4328 return status;
4329}
4330
4331hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4332 tSirMacAddr macAddr )
4333{
4334 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4335 hdd_adapter_t *pAdapter;
4336 VOS_STATUS status;
4337
4338 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4339
4340 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4341 {
4342 pAdapter = pAdapterNode->pAdapter;
4343
4344 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4345 macAddr, sizeof(tSirMacAddr) ) )
4346 {
4347 return pAdapter;
4348 }
4349 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4350 pAdapterNode = pNext;
4351 }
4352
4353 return NULL;
4354
4355}
4356
4357hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4358{
4359 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4360 hdd_adapter_t *pAdapter;
4361 VOS_STATUS status;
4362
4363 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4364
4365 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4366 {
4367 pAdapter = pAdapterNode->pAdapter;
4368
4369 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4370 IFNAMSIZ ) )
4371 {
4372 return pAdapter;
4373 }
4374 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4375 pAdapterNode = pNext;
4376 }
4377
4378 return NULL;
4379
4380}
4381
4382hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4383{
4384 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4385 hdd_adapter_t *pAdapter;
4386 VOS_STATUS status;
4387
4388 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4389
4390 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4391 {
4392 pAdapter = pAdapterNode->pAdapter;
4393
4394 if( pAdapter && (mode == pAdapter->device_mode) )
4395 {
4396 return pAdapter;
4397 }
4398 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4399 pAdapterNode = pNext;
4400 }
4401
4402 return NULL;
4403
4404}
4405
4406//Remove this function later
4407hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4408{
4409 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4410 hdd_adapter_t *pAdapter;
4411 VOS_STATUS status;
4412
4413 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4414
4415 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4416 {
4417 pAdapter = pAdapterNode->pAdapter;
4418
4419 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4420 {
4421 return pAdapter;
4422 }
4423
4424 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4425 pAdapterNode = pNext;
4426 }
4427
4428 return NULL;
4429
4430}
4431
Jeff Johnson295189b2012-06-20 16:38:30 -07004432/**---------------------------------------------------------------------------
4433
4434 \brief hdd_set_monitor_tx_adapter() -
4435
4436 This API initializes the adapter to be used while transmitting on monitor
4437 adapter.
4438
4439 \param - pHddCtx - Pointer to the HDD context.
4440 pAdapter - Adapter that will used for TX. This can be NULL.
4441 \return - None.
4442 --------------------------------------------------------------------------*/
4443void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4444{
4445 hdd_adapter_t *pMonAdapter;
4446
4447 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4448
4449 if( NULL != pMonAdapter )
4450 {
4451 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4452 }
4453}
Jeff Johnson295189b2012-06-20 16:38:30 -07004454/**---------------------------------------------------------------------------
4455
4456 \brief hdd_select_queue() -
4457
4458 This API returns the operating channel of the requested device mode
4459
4460 \param - pHddCtx - Pointer to the HDD context.
4461 - mode - Device mode for which operating channel is required
4462 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4463 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4464 \return - channel number. "0" id the requested device is not found OR it is not connected.
4465 --------------------------------------------------------------------------*/
4466v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4467{
4468 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4469 VOS_STATUS status;
4470 hdd_adapter_t *pAdapter;
4471 v_U8_t operatingChannel = 0;
4472
4473 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4474
4475 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4476 {
4477 pAdapter = pAdapterNode->pAdapter;
4478
4479 if( mode == pAdapter->device_mode )
4480 {
4481 switch(pAdapter->device_mode)
4482 {
4483 case WLAN_HDD_INFRA_STATION:
4484 case WLAN_HDD_P2P_CLIENT:
4485 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4486 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4487 break;
4488 case WLAN_HDD_SOFTAP:
4489 case WLAN_HDD_P2P_GO:
4490 /*softap connection info */
4491 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4492 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4493 break;
4494 default:
4495 break;
4496 }
4497
4498 break; //Found the device of interest. break the loop
4499 }
4500
4501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4502 pAdapterNode = pNext;
4503 }
4504 return operatingChannel;
4505}
4506
4507#ifdef WLAN_FEATURE_PACKET_FILTERING
4508/**---------------------------------------------------------------------------
4509
4510 \brief hdd_set_multicast_list() -
4511
4512 This used to set the multicast address list.
4513
4514 \param - dev - Pointer to the WLAN device.
4515 - skb - Pointer to OS packet (sk_buff).
4516 \return - success/fail
4517
4518 --------------------------------------------------------------------------*/
4519static void hdd_set_multicast_list(struct net_device *dev)
4520{
4521 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 int mc_count;
4523 int i = 0;
4524 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304525
4526 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 {
4528 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304529 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 return;
4531 }
4532
4533 if (dev->flags & IFF_ALLMULTI)
4534 {
4535 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004536 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304537 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004538 }
4539 else
4540 {
4541 mc_count = netdev_mc_count(dev);
4542 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004543 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004544 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4545 {
4546 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004547 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304548 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004549 return;
4550 }
4551
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304552 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004553
4554 netdev_for_each_mc_addr(ha, dev) {
4555 if (i == mc_count)
4556 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304557 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4558 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4559 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304561 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 i++;
4563 }
4564 }
4565 return;
4566}
4567#endif
4568
4569/**---------------------------------------------------------------------------
4570
4571 \brief hdd_select_queue() -
4572
4573 This function is registered with the Linux OS for network
4574 core to decide which queue to use first.
4575
4576 \param - dev - Pointer to the WLAN device.
4577 - skb - Pointer to OS packet (sk_buff).
4578 \return - ac, Queue Index/access category corresponding to UP in IP header
4579
4580 --------------------------------------------------------------------------*/
4581v_U16_t hdd_select_queue(struct net_device *dev,
4582 struct sk_buff *skb)
4583{
4584 return hdd_wmm_select_queue(dev, skb);
4585}
4586
4587
4588/**---------------------------------------------------------------------------
4589
4590 \brief hdd_wlan_initial_scan() -
4591
4592 This function triggers the initial scan
4593
4594 \param - pAdapter - Pointer to the HDD adapter.
4595
4596 --------------------------------------------------------------------------*/
4597void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4598{
4599 tCsrScanRequest scanReq;
4600 tCsrChannelInfo channelInfo;
4601 eHalStatus halStatus;
4602 unsigned long scanId;
4603 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4604
4605 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4606 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4607 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4608
4609 if(sme_Is11dSupported(pHddCtx->hHal))
4610 {
4611 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4612 if ( HAL_STATUS_SUCCESS( halStatus ) )
4613 {
4614 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4615 if( !scanReq.ChannelInfo.ChannelList )
4616 {
4617 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4618 vos_mem_free(channelInfo.ChannelList);
4619 return;
4620 }
4621 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4622 channelInfo.numOfChannels);
4623 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4624 vos_mem_free(channelInfo.ChannelList);
4625 }
4626
4627 scanReq.scanType = eSIR_PASSIVE_SCAN;
4628 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4629 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4630 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4631 }
4632 else
4633 {
4634 scanReq.scanType = eSIR_ACTIVE_SCAN;
4635 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4636 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4637 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4638 }
4639
4640 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4641 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4642 {
4643 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4644 __func__, halStatus );
4645 }
4646
4647 if(sme_Is11dSupported(pHddCtx->hHal))
4648 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4649}
4650
4651struct fullPowerContext
4652{
4653 struct completion completion;
4654 unsigned int magic;
4655};
4656#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4657
4658/**---------------------------------------------------------------------------
4659
4660 \brief hdd_full_power_callback() - HDD full power callback function
4661
4662 This is the function invoked by SME to inform the result of a full power
4663 request issued by HDD
4664
4665 \param - callbackcontext - Pointer to cookie
4666 \param - status - result of request
4667
4668 \return - None
4669
4670 --------------------------------------------------------------------------*/
4671static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4672{
4673 struct fullPowerContext *pContext = callbackContext;
4674
4675 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304676 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004677
4678 if (NULL == callbackContext)
4679 {
4680 hddLog(VOS_TRACE_LEVEL_ERROR,
4681 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004682 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004683 return;
4684 }
4685
4686 /* there is a race condition that exists between this callback function
4687 and the caller since the caller could time out either before or
4688 while this code is executing. we'll assume the timeout hasn't
4689 occurred, but we'll verify that right before we save our work */
4690
4691 if (POWER_CONTEXT_MAGIC != pContext->magic)
4692 {
4693 /* the caller presumably timed out so there is nothing we can do */
4694 hddLog(VOS_TRACE_LEVEL_WARN,
4695 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004696 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004697 return;
4698 }
4699
4700 /* the race is on. caller could have timed out immediately after
4701 we verified the magic, but if so, caller will wait a short time
4702 for us to notify the caller, so the context will stay valid */
4703 complete(&pContext->completion);
4704}
4705
4706/**---------------------------------------------------------------------------
4707
4708 \brief hdd_wlan_exit() - HDD WLAN exit function
4709
4710 This is the driver exit point (invoked during rmmod)
4711
4712 \param - pHddCtx - Pointer to the HDD Context
4713
4714 \return - None
4715
4716 --------------------------------------------------------------------------*/
4717void hdd_wlan_exit(hdd_context_t *pHddCtx)
4718{
4719 eHalStatus halStatus;
4720 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4721 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304722 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004724 struct fullPowerContext powerContext;
4725 long lrc;
4726
4727 ENTER();
4728
Jeff Johnson88ba7742013-02-27 14:36:02 -08004729 if (VOS_FTM_MODE != hdd_get_conparam())
4730 {
4731 // Unloading, restart logic is no more required.
4732 wlan_hdd_restart_deinit(pHddCtx);
4733 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004734
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004736 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004737 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004738 {
4739 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4740 WLAN_HDD_INFRA_STATION);
4741 if (pAdapter == NULL)
4742 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4743
4744 if (pAdapter != NULL)
4745 {
4746 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4747 hdd_UnregisterWext(pAdapter->dev);
4748 }
4749 }
4750 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004751
Jeff Johnson295189b2012-06-20 16:38:30 -07004752 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004753 {
4754 wlan_hdd_ftm_close(pHddCtx);
4755 goto free_hdd_ctx;
4756 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 //Stop the Interface TX queue.
4758 //netif_tx_disable(pWlanDev);
4759 //netif_carrier_off(pWlanDev);
4760
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4762 {
4763 pAdapter = hdd_get_adapter(pHddCtx,
4764 WLAN_HDD_SOFTAP);
4765 }
4766 else
4767 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 {
4770 pAdapter = hdd_get_adapter(pHddCtx,
4771 WLAN_HDD_INFRA_STATION);
4772 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004773 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 /* DeRegister with platform driver as client for Suspend/Resume */
4775 vosStatus = hddDeregisterPmOps(pHddCtx);
4776 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4777 {
4778 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4779 VOS_ASSERT(0);
4780 }
4781
4782 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4783 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4784 {
4785 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4786 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004787
4788 // Cancel any outstanding scan requests. We are about to close all
4789 // of our adapters, but an adapter structure is what SME passes back
4790 // to our callback function. Hence if there are any outstanding scan
4791 // requests then there is a race condition between when the adapter
4792 // is closed and when the callback is invoked. We try to resolve that
4793 // race condition here by canceling any outstanding scans before we
4794 // close the adapters.
4795 // Note that the scans may be cancelled in an asynchronous manner, so
4796 // ideally there needs to be some kind of synchronization. Rather than
4797 // introduce a new synchronization here, we will utilize the fact that
4798 // we are about to Request Full Power, and since that is synchronized,
4799 // the expectation is that by the time Request Full Power has completed,
4800 // all scans will be cancelled.
4801 hdd_abort_mac_scan( pHddCtx );
4802
4803 //Disable IMPS/BMPS as we do not want the device to enter any power
4804 //save mode during shutdown
4805 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4806 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4807 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4808
4809 //Ensure that device is in full power as we will touch H/W during vos_Stop
4810 init_completion(&powerContext.completion);
4811 powerContext.magic = POWER_CONTEXT_MAGIC;
4812
4813 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4814 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4815
4816 if (eHAL_STATUS_SUCCESS != halStatus)
4817 {
4818 if (eHAL_STATUS_PMC_PENDING == halStatus)
4819 {
4820 /* request was sent -- wait for the response */
4821 lrc = wait_for_completion_interruptible_timeout(
4822 &powerContext.completion,
4823 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4824 /* either we have a response or we timed out
4825 either way, first invalidate our magic */
4826 powerContext.magic = 0;
4827 if (lrc <= 0)
4828 {
4829 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004830 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004831 /* there is a race condition such that the callback
4832 function could be executing at the same time we are. of
4833 primary concern is if the callback function had already
4834 verified the "magic" but hasn't yet set the completion
4835 variable. Since the completion variable is on our
4836 stack, we'll delay just a bit to make sure the data is
4837 still valid if that is the case */
4838 msleep(50);
4839 }
4840 }
4841 else
4842 {
4843 hddLog(VOS_TRACE_LEVEL_ERROR,
4844 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004845 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004846 VOS_ASSERT(0);
4847 /* continue -- need to clean up as much as possible */
4848 }
4849 }
4850
4851 // Unregister the Net Device Notifier
4852 unregister_netdevice_notifier(&hdd_netdev_notifier);
4853
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 hdd_stop_all_adapters( pHddCtx );
4855
Jeff Johnson295189b2012-06-20 16:38:30 -07004856#ifdef WLAN_BTAMP_FEATURE
4857 vosStatus = WLANBAP_Stop(pVosContext);
4858 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4859 {
4860 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4861 "%s: Failed to stop BAP",__func__);
4862 }
4863#endif //WLAN_BTAMP_FEATURE
4864
4865 //Stop all the modules
4866 vosStatus = vos_stop( pVosContext );
4867 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4868 {
4869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4870 "%s: Failed to stop VOSS",__func__);
4871 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4872 }
4873
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 //Assert Deep sleep signal now to put Libra HW in lowest power state
4875 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4876 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4877
4878 //Vote off any PMIC voltage supplies
4879 vos_chipPowerDown(NULL, NULL, NULL);
4880
4881 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4882
4883 //Clean up HDD Nlink Service
4884 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4885 nl_srv_exit();
4886
4887 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004889
4890 //Close the scheduler before calling vos_close to make sure no thread is
4891 // scheduled after the each module close is called i.e after all the data
4892 // structures are freed.
4893 vosStatus = vos_sched_close( pVosContext );
4894 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4895 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4896 "%s: Failed to close VOSS Scheduler",__func__);
4897 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4898 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004899#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004900#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4901 /* Destroy the wake lock */
4902 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4903#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004904 /* Destroy the wake lock */
4905 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004906#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004907
4908 //Close VOSS
4909 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4910 vos_close(pVosContext);
4911
Jeff Johnson295189b2012-06-20 16:38:30 -07004912 //Close Watchdog
4913 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4914 vos_watchdog_close(pVosContext);
4915
4916 /* Cancel the vote for XO Core ON.
4917 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4918 * exited at this point
4919 */
4920 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4921 " when WLAN is turned OFF\n");
4922 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4923 {
4924 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4925 " Not returning failure."
4926 " Power consumed will be high\n");
4927 }
4928
4929 hdd_close_all_adapters( pHddCtx );
4930
4931
4932 //Free up dynamically allocated members inside HDD Adapter
4933 kfree(pHddCtx->cfg_ini);
4934 pHddCtx->cfg_ini= NULL;
4935
4936 /* free the power on lock from platform driver */
4937 if (free_riva_power_on_lock("wlan"))
4938 {
4939 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4940 __func__);
4941 }
4942
Jeff Johnson88ba7742013-02-27 14:36:02 -08004943free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004944 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004945 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004946 if (hdd_is_ssr_required())
4947 {
4948 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004949 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004950 msleep(5000);
4951 }
4952 hdd_set_ssr_required (VOS_FALSE);
4953}
4954
4955
4956/**---------------------------------------------------------------------------
4957
4958 \brief hdd_update_config_from_nv() - Function to update the contents of
4959 the running configuration with parameters taken from NV storage
4960
4961 \param - pHddCtx - Pointer to the HDD global context
4962
4963 \return - VOS_STATUS_SUCCESS if successful
4964
4965 --------------------------------------------------------------------------*/
4966static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4967{
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 v_BOOL_t itemIsValid = VOS_FALSE;
4969 VOS_STATUS status;
4970 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4971 v_U8_t macLoop;
4972
4973 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4974 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4975 if(status != VOS_STATUS_SUCCESS)
4976 {
4977 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4978 return VOS_STATUS_E_FAILURE;
4979 }
4980
4981 if (itemIsValid == VOS_TRUE)
4982 {
4983 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4984 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4985 VOS_MAX_CONCURRENCY_PERSONA);
4986 if(status != VOS_STATUS_SUCCESS)
4987 {
4988 /* Get MAC from NV fail, not update CFG info
4989 * INI MAC value will be used for MAC setting */
4990 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4991 return VOS_STATUS_E_FAILURE;
4992 }
4993
4994 /* If first MAC is not valid, treat all others are not valid
4995 * Then all MACs will be got from ini file */
4996 if(vos_is_macaddr_zero(&macFromNV[0]))
4997 {
4998 /* MAC address in NV file is not configured yet */
4999 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5000 return VOS_STATUS_E_INVAL;
5001 }
5002
5003 /* Get MAC address from NV, update CFG info */
5004 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5005 {
5006 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5007 {
5008 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5009 /* This MAC is not valid, skip it
5010 * This MAC will be got from ini file */
5011 }
5012 else
5013 {
5014 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5015 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5016 VOS_MAC_ADDR_SIZE);
5017 }
5018 }
5019 }
5020 else
5021 {
5022 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5023 return VOS_STATUS_E_FAILURE;
5024 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005025
Jeff Johnson295189b2012-06-20 16:38:30 -07005026
5027 return VOS_STATUS_SUCCESS;
5028}
5029
5030/**---------------------------------------------------------------------------
5031
5032 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5033
5034 \param - pAdapter - Pointer to the HDD
5035
5036 \return - None
5037
5038 --------------------------------------------------------------------------*/
5039VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5040{
5041 eHalStatus halStatus;
5042 v_U32_t listenInterval;
5043
Jeff Johnson295189b2012-06-20 16:38:30 -07005044
5045 // Send ready indication to the HDD. This will kick off the MAC
5046 // into a 'running' state and should kick off an initial scan.
5047 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5048 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5049 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305050 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 "code %08d [x%08x]",__func__, halStatus, halStatus );
5052 return VOS_STATUS_E_FAILURE;
5053 }
5054
5055 // Set default LI into HDD context,
5056 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5057 // And RIVA will crash
5058 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5059 pHddCtx->hdd_actual_LI_value = listenInterval;
5060
5061 return VOS_STATUS_SUCCESS;
5062}
5063
Jeff Johnson295189b2012-06-20 16:38:30 -07005064/* wake lock APIs for HDD */
5065void hdd_prevent_suspend(void)
5066{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005067#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005068 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005069#else
5070 wcnss_prevent_suspend();
5071#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005072}
5073
5074void hdd_allow_suspend(void)
5075{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005076#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005078#else
5079 wcnss_allow_suspend();
5080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005081}
5082
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005083void hdd_allow_suspend_timeout(v_U32_t timeout)
5084{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005085#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005086 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005087#else
5088 /* Do nothing as there is no API in wcnss for timeout*/
5089#endif
5090}
5091
Jeff Johnson295189b2012-06-20 16:38:30 -07005092/**---------------------------------------------------------------------------
5093
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005094 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5095 information between Host and Riva
5096
5097 This function gets reported version of FW
5098 It also finds the version of Riva headers used to compile the host
5099 It compares the above two and prints a warning if they are different
5100 It gets the SW and HW version string
5101 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5102 indicating the features they support through a bitmap
5103
5104 \param - pHddCtx - Pointer to HDD context
5105
5106 \return - void
5107
5108 --------------------------------------------------------------------------*/
5109
5110void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5111{
5112
5113 tSirVersionType versionCompiled;
5114 tSirVersionType versionReported;
5115 tSirVersionString versionString;
5116 tANI_U8 fwFeatCapsMsgSupported = 0;
5117 VOS_STATUS vstatus;
5118
5119 /* retrieve and display WCNSS version information */
5120 do {
5121
5122 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5123 &versionCompiled);
5124 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5125 {
5126 hddLog(VOS_TRACE_LEVEL_FATAL,
5127 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005128 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005129 break;
5130 }
5131
5132 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5133 &versionReported);
5134 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5135 {
5136 hddLog(VOS_TRACE_LEVEL_FATAL,
5137 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005138 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005139 break;
5140 }
5141
5142 if ((versionCompiled.major != versionReported.major) ||
5143 (versionCompiled.minor != versionReported.minor) ||
5144 (versionCompiled.version != versionReported.version) ||
5145 (versionCompiled.revision != versionReported.revision))
5146 {
5147 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5148 "Host expected %u.%u.%u.%u\n",
5149 WLAN_MODULE_NAME,
5150 (int)versionReported.major,
5151 (int)versionReported.minor,
5152 (int)versionReported.version,
5153 (int)versionReported.revision,
5154 (int)versionCompiled.major,
5155 (int)versionCompiled.minor,
5156 (int)versionCompiled.version,
5157 (int)versionCompiled.revision);
5158 }
5159 else
5160 {
5161 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5162 WLAN_MODULE_NAME,
5163 (int)versionReported.major,
5164 (int)versionReported.minor,
5165 (int)versionReported.version,
5166 (int)versionReported.revision);
5167 }
5168
5169 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5170 versionString,
5171 sizeof(versionString));
5172 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5173 {
5174 hddLog(VOS_TRACE_LEVEL_FATAL,
5175 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005176 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005177 break;
5178 }
5179
5180 pr_info("%s: WCNSS software version %s\n",
5181 WLAN_MODULE_NAME, versionString);
5182
5183 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5184 versionString,
5185 sizeof(versionString));
5186 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5187 {
5188 hddLog(VOS_TRACE_LEVEL_FATAL,
5189 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005190 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005191 break;
5192 }
5193
5194 pr_info("%s: WCNSS hardware version %s\n",
5195 WLAN_MODULE_NAME, versionString);
5196
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005197 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5198 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005199 send the message only if it the riva is 1.1
5200 minor numbers for different riva branches:
5201 0 -> (1.0)Mainline Build
5202 1 -> (1.1)Mainline Build
5203 2->(1.04) Stability Build
5204 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005205 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005206 ((versionReported.minor>=1) && (versionReported.version>=1)))
5207 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5208 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005209
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005210 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005211 {
5212#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5213 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5214 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5215#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005216 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005217 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005218
5219 } while (0);
5220
5221}
5222
5223/**---------------------------------------------------------------------------
5224
Jeff Johnson295189b2012-06-20 16:38:30 -07005225 \brief hdd_wlan_startup() - HDD init function
5226
5227 This is the driver startup code executed once a WLAN device has been detected
5228
5229 \param - dev - Pointer to the underlying device
5230
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005231 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005232
5233 --------------------------------------------------------------------------*/
5234
5235int hdd_wlan_startup(struct device *dev )
5236{
5237 VOS_STATUS status;
5238 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005239 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005240 hdd_context_t *pHddCtx = NULL;
5241 v_CONTEXT_t pVosContext= NULL;
5242#ifdef WLAN_BTAMP_FEATURE
5243 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5244 WLANBAP_ConfigType btAmpConfig;
5245 hdd_config_t *pConfig;
5246#endif
5247 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005248 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005249
5250 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 /*
5252 * cfg80211: wiphy allocation
5253 */
5254 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5255
5256 if(wiphy == NULL)
5257 {
5258 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005259 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 }
5261
5262 pHddCtx = wiphy_priv(wiphy);
5263
Jeff Johnson295189b2012-06-20 16:38:30 -07005264 //Initialize the adapter context to zeros.
5265 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5266
Jeff Johnson295189b2012-06-20 16:38:30 -07005267 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 hdd_prevent_suspend();
5269 pHddCtx->isLoadUnloadInProgress = TRUE;
5270
5271 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5272
5273 /*Get vos context here bcoz vos_open requires it*/
5274 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5275
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005276 if(pVosContext == NULL)
5277 {
5278 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5279 goto err_free_hdd_context;
5280 }
5281
Jeff Johnson295189b2012-06-20 16:38:30 -07005282 //Save the Global VOSS context in adapter context for future.
5283 pHddCtx->pvosContext = pVosContext;
5284
5285 //Save the adapter context in global context for future.
5286 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5287
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 pHddCtx->parent_dev = dev;
5289
5290 init_completion(&pHddCtx->full_pwr_comp_var);
5291 init_completion(&pHddCtx->standby_comp_var);
5292 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005293 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005294 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005295
5296 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5297
5298 // Load all config first as TL config is needed during vos_open
5299 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5300 if(pHddCtx->cfg_ini == NULL)
5301 {
5302 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5303 goto err_free_hdd_context;
5304 }
5305
5306 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5307
5308 // Read and parse the qcom_cfg.ini file
5309 status = hdd_parse_config_ini( pHddCtx );
5310 if ( VOS_STATUS_SUCCESS != status )
5311 {
5312 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5313 __func__, WLAN_INI_FILE);
5314 goto err_config;
5315 }
5316
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 /*
5318 * cfg80211: Initialization and registration ...
5319 */
5320 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5321 {
5322 hddLog(VOS_TRACE_LEVEL_FATAL,
5323 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5324 goto err_wiphy_reg;
5325 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005326
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005327 // Update VOS trace levels based upon the cfg.ini
5328 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5329 pHddCtx->cfg_ini->vosTraceEnableBAP);
5330 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5331 pHddCtx->cfg_ini->vosTraceEnableTL);
5332 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5333 pHddCtx->cfg_ini->vosTraceEnableWDI);
5334 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5335 pHddCtx->cfg_ini->vosTraceEnableHDD);
5336 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5337 pHddCtx->cfg_ini->vosTraceEnableSME);
5338 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5339 pHddCtx->cfg_ini->vosTraceEnablePE);
5340 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5341 pHddCtx->cfg_ini->vosTraceEnableWDA);
5342 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5343 pHddCtx->cfg_ini->vosTraceEnableSYS);
5344 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5345 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005346 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5347 pHddCtx->cfg_ini->vosTraceEnableSAP);
5348 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5349 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005350
Jeff Johnson295189b2012-06-20 16:38:30 -07005351 // Update WDI trace levels based upon the cfg.ini
5352 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5353 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5354 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5355 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5356 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5357 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5358 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5359 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005360
Jeff Johnson88ba7742013-02-27 14:36:02 -08005361 if (VOS_FTM_MODE == hdd_get_conparam())
5362 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005363 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5364 {
5365 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5366 goto err_free_hdd_context;
5367 }
5368 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5369 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005370 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005371
Jeff Johnson88ba7742013-02-27 14:36:02 -08005372 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5374 {
5375 status = vos_watchdog_open(pVosContext,
5376 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5377
5378 if(!VOS_IS_STATUS_SUCCESS( status ))
5379 {
5380 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 }
5383 }
5384
5385 pHddCtx->isLogpInProgress = FALSE;
5386 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5387
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5389 if(!VOS_IS_STATUS_SUCCESS(status))
5390 {
5391 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 }
5394
Jeff Johnson295189b2012-06-20 16:38:30 -07005395 status = vos_open( &pVosContext, 0);
5396 if ( !VOS_IS_STATUS_SUCCESS( status ))
5397 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005398 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5399 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 }
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5403
5404 if ( NULL == pHddCtx->hHal )
5405 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005406 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005407 goto err_vosclose;
5408 }
5409
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005410 status = vos_preStart( pHddCtx->pvosContext );
5411 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5412 {
5413 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5414 goto err_vosclose;
5415 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005416
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005417 /* Note that the vos_preStart() sequence triggers the cfg download.
5418 The cfg download must occur before we update the SME config
5419 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005420 status = hdd_set_sme_config( pHddCtx );
5421
5422 if ( VOS_STATUS_SUCCESS != status )
5423 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005424 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5425 goto err_vosclose;
5426 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005427
5428 //Initialize the WMM module
5429 status = hdd_wmm_init(pHddCtx);
5430 if (!VOS_IS_STATUS_SUCCESS(status))
5431 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005432 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005433 goto err_vosclose;
5434 }
5435
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 /* In the integrated architecture we update the configuration from
5437 the INI file and from NV before vOSS has been started so that
5438 the final contents are available to send down to the cCPU */
5439
5440 // Apply the cfg.ini to cfg.dat
5441 if (FALSE == hdd_update_config_dat(pHddCtx))
5442 {
5443 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5444 goto err_vosclose;
5445 }
5446
5447 // Apply the NV to cfg.dat
5448 /* Prima Update MAC address only at here */
5449 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5450 {
5451#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5452 /* There was not a valid set of MAC Addresses in NV. See if the
5453 default addresses were modified by the cfg.ini settings. If so,
5454 we'll use them, but if not, we'll autogenerate a set of MAC
5455 addresses based upon the device serial number */
5456
5457 static const v_MACADDR_t default_address =
5458 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5459 unsigned int serialno;
5460 int i;
5461
5462 serialno = wcnss_get_serial_number();
5463 if ((0 != serialno) &&
5464 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5465 sizeof(default_address))))
5466 {
5467 /* cfg.ini has the default address, invoke autogen logic */
5468
5469 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5470 bytes of the serial number that can be used to generate
5471 the other 3 bytes of the MAC address. Mask off all but
5472 the lower 3 bytes (this will also make sure we don't
5473 overflow in the next step) */
5474 serialno &= 0x00FFFFFF;
5475
5476 /* we need a unique address for each session */
5477 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5478
5479 /* autogen all addresses */
5480 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5481 {
5482 /* start with the entire default address */
5483 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5484 /* then replace the lower 3 bytes */
5485 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5486 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5487 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5488
5489 serialno++;
5490 }
5491
5492 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5493 MAC_ADDRESS_STR,
5494 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5495 }
5496 else
5497#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5498 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005499 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005500 "%s: Invalid MAC address in NV, using MAC from ini file "
5501 MAC_ADDRESS_STR, __func__,
5502 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5503 }
5504 }
5505 {
5506 eHalStatus halStatus;
5507 // Set the MAC Address
5508 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5509 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5510 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5511 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5512
5513 if (!HAL_STATUS_SUCCESS( halStatus ))
5514 {
5515 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5516 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005517 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 }
5519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005520
5521 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5522 Note: Firmware image will be read and downloaded inside vos_start API */
5523 status = vos_start( pHddCtx->pvosContext );
5524 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5525 {
5526 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5527 goto err_vosclose;
5528 }
5529
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005530 /* Exchange capability info between Host and FW and also get versioning info from FW */
5531 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005532
5533 status = hdd_post_voss_start_config( pHddCtx );
5534 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5535 {
5536 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5537 __func__);
5538 goto err_vosstop;
5539 }
5540
Jeff Johnson295189b2012-06-20 16:38:30 -07005541 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5542 {
5543 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5544 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5545 }
5546 else
5547 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005548 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5549 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5550 if (pAdapter != NULL)
5551 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305552 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305554 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5555 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5556 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005557
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305558 /* Generate the P2P Device Address. This consists of the device's
5559 * primary MAC address with the locally administered bit set.
5560 */
5561 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005562 }
5563 else
5564 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305565 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5566 if (p2p_dev_addr != NULL)
5567 {
5568 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5569 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5570 }
5571 else
5572 {
5573 hddLog(VOS_TRACE_LEVEL_FATAL,
5574 "%s: Failed to allocate mac_address for p2p_device",
5575 __func__);
5576 goto err_close_adapter;
5577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005579
5580 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5581 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5582 if ( NULL == pP2pAdapter )
5583 {
5584 hddLog(VOS_TRACE_LEVEL_FATAL,
5585 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005586 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005587 goto err_close_adapter;
5588 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005589 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005591
5592 if( pAdapter == NULL )
5593 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005594 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5595 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598#ifdef WLAN_BTAMP_FEATURE
5599 vStatus = WLANBAP_Open(pVosContext);
5600 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5601 {
5602 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5603 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005604 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 }
5606
5607 vStatus = BSL_Init(pVosContext);
5608 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5609 {
5610 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5611 "%s: Failed to Init BSL",__func__);
5612 goto err_bap_close;
5613 }
5614 vStatus = WLANBAP_Start(pVosContext);
5615 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5616 {
5617 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5618 "%s: Failed to start TL",__func__);
5619 goto err_bap_close;
5620 }
5621
5622 pConfig = pHddCtx->cfg_ini;
5623 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5624 status = WLANBAP_SetConfig(&btAmpConfig);
5625
5626#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005627
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005628#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5629 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5630 {
5631 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5632 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5633 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5634 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5635 }
5636#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005637#ifdef FEATURE_WLAN_SCAN_PNO
5638 /*SME must send channel update configuration to RIVA*/
5639 sme_UpdateChannelConfig(pHddCtx->hHal);
5640#endif
5641
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 /* Register with platform driver as client for Suspend/Resume */
5643 status = hddRegisterPmOps(pHddCtx);
5644 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5645 {
5646 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5647#ifdef WLAN_BTAMP_FEATURE
5648 goto err_bap_stop;
5649#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005650 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005651#endif //WLAN_BTAMP_FEATURE
5652 }
5653
5654 /* Register TM level change handler function to the platform */
5655 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5656 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5657 {
5658 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5659 goto err_unregister_pmops;
5660 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005661
5662 /* register for riva power on lock to platform driver */
5663 if (req_riva_power_on_lock("wlan"))
5664 {
5665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5666 __func__);
5667 goto err_unregister_pmops;
5668 }
5669
Jeff Johnson295189b2012-06-20 16:38:30 -07005670 // register net device notifier for device change notification
5671 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5672
5673 if(ret < 0)
5674 {
5675 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5676 goto err_free_power_on_lock;
5677 }
5678
5679 //Initialize the nlink service
5680 if(nl_srv_init() != 0)
5681 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305682 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 goto err_reg_netdev;
5684 }
5685
5686 //Initialize the BTC service
5687 if(btc_activate_service(pHddCtx) != 0)
5688 {
5689 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5690 goto err_nl_srv;
5691 }
5692
5693#ifdef PTT_SOCK_SVC_ENABLE
5694 //Initialize the PTT service
5695 if(ptt_sock_activate_svc(pHddCtx) != 0)
5696 {
5697 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5698 goto err_nl_srv;
5699 }
5700#endif
5701
Jeff Johnson295189b2012-06-20 16:38:30 -07005702 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005704 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005705 /* Action frame registered in one adapter which will
5706 * applicable to all interfaces
5707 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005708 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005709 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005710
5711 mutex_init(&pHddCtx->sap_lock);
5712
5713 pHddCtx->isLoadUnloadInProgress = FALSE;
5714
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005715#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005716#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5717 /* Initialize the wake lcok */
5718 wake_lock_init(&pHddCtx->rx_wake_lock,
5719 WAKE_LOCK_SUSPEND,
5720 "qcom_rx_wakelock");
5721#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005722 /* Initialize the wake lcok */
5723 wake_lock_init(&pHddCtx->sap_wake_lock,
5724 WAKE_LOCK_SUSPEND,
5725 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005726#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005727
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005728 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5729 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005730
5731 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5732 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005733
5734 // Initialize the restart logic
5735 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305736
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 goto success;
5738
5739err_nl_srv:
5740 nl_srv_exit();
5741
5742err_reg_netdev:
5743 unregister_netdevice_notifier(&hdd_netdev_notifier);
5744
5745err_free_power_on_lock:
5746 free_riva_power_on_lock("wlan");
5747
5748err_unregister_pmops:
5749 hddDevTmUnregisterNotifyCallback(pHddCtx);
5750 hddDeregisterPmOps(pHddCtx);
5751
5752#ifdef WLAN_BTAMP_FEATURE
5753err_bap_stop:
5754 WLANBAP_Stop(pVosContext);
5755#endif
5756
5757#ifdef WLAN_BTAMP_FEATURE
5758err_bap_close:
5759 WLANBAP_Close(pVosContext);
5760#endif
5761
Jeff Johnson295189b2012-06-20 16:38:30 -07005762err_close_adapter:
5763 hdd_close_all_adapters( pHddCtx );
5764
5765err_vosstop:
5766 vos_stop(pVosContext);
5767
5768err_vosclose:
5769 status = vos_sched_close( pVosContext );
5770 if (!VOS_IS_STATUS_SUCCESS(status)) {
5771 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5772 "%s: Failed to close VOSS Scheduler", __func__);
5773 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5774 }
5775 vos_close(pVosContext );
5776
Jeff Johnson295189b2012-06-20 16:38:30 -07005777err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005778 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005779
5780err_wdclose:
5781 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5782 vos_watchdog_close(pVosContext);
5783
Jeff Johnson295189b2012-06-20 16:38:30 -07005784err_wiphy_reg:
5785 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005786
5787err_config:
5788 kfree(pHddCtx->cfg_ini);
5789 pHddCtx->cfg_ini= NULL;
5790
5791err_free_hdd_context:
5792 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 wiphy_free(wiphy) ;
5794 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 VOS_BUG(1);
5796
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005797 if (hdd_is_ssr_required())
5798 {
5799 /* WDI timeout had happened during load, so SSR is needed here */
5800 subsystem_restart("wcnss");
5801 msleep(5000);
5802 }
5803 hdd_set_ssr_required (VOS_FALSE);
5804
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005805 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005806
5807success:
5808 EXIT();
5809 return 0;
5810}
5811
5812/**---------------------------------------------------------------------------
5813
Jeff Johnson32d95a32012-09-10 13:15:23 -07005814 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005815
Jeff Johnson32d95a32012-09-10 13:15:23 -07005816 This is the driver entry point - called in different timeline depending
5817 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005818
5819 \param - None
5820
5821 \return - 0 for success, non zero for failure
5822
5823 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005824static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005825{
5826 VOS_STATUS status;
5827 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 struct device *dev = NULL;
5829 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005830#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5831 int max_retries = 0;
5832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005833
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305834#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5835 vos_wconn_trace_init();
5836#endif
5837
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 ENTER();
5839
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005840#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005841 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005842#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005843
5844 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5845 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5846
5847 //Power Up Libra WLAN card first if not already powered up
5848 status = vos_chipPowerUp(NULL,NULL,NULL);
5849 if (!VOS_IS_STATUS_SUCCESS(status))
5850 {
5851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5852 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005853 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 }
5855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856#ifdef ANI_BUS_TYPE_PCI
5857
5858 dev = wcnss_wlan_get_device();
5859
5860#endif // ANI_BUS_TYPE_PCI
5861
5862#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005863
5864#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5865 /* wait until WCNSS driver downloads NV */
5866 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5867 msleep(1000);
5868 }
5869 if (max_retries >= 5) {
5870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5871 return -ENODEV;
5872 }
5873#endif
5874
Jeff Johnson295189b2012-06-20 16:38:30 -07005875 dev = wcnss_wlan_get_device();
5876#endif // ANI_BUS_TYPE_PLATFORM
5877
5878
5879 do {
5880 if (NULL == dev) {
5881 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5882 ret_status = -1;
5883 break;
5884 }
5885
5886#ifdef MEMORY_DEBUG
5887 vos_mem_init();
5888#endif
5889
5890#ifdef TIMER_MANAGER
5891 vos_timer_manager_init();
5892#endif
5893
5894 /* Preopen VOSS so that it is ready to start at least SAL */
5895 status = vos_preOpen(&pVosContext);
5896
5897 if (!VOS_IS_STATUS_SUCCESS(status))
5898 {
5899 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5900 ret_status = -1;
5901 break;
5902 }
5903
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005904#ifndef MODULE
5905 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5906 */
5907 hdd_set_conparam((v_UINT_t)con_mode);
5908#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005909
5910 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005911 if (hdd_wlan_startup(dev))
5912 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005914 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 vos_preClose( &pVosContext );
5916 ret_status = -1;
5917 break;
5918 }
5919
5920 /* Cancel the vote for XO Core ON
5921 * This is done here for safety purposes in case we re-initialize without turning
5922 * it OFF in any error scenario.
5923 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005924 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005926 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005927 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5928 {
5929 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5930 " Power consumed will be high\n");
5931 }
5932 } while (0);
5933
5934 if (0 != ret_status)
5935 {
5936 //Assert Deep sleep signal now to put Libra HW in lowest power state
5937 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5938 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5939
5940 //Vote off any PMIC voltage supplies
5941 vos_chipPowerDown(NULL, NULL, NULL);
5942#ifdef TIMER_MANAGER
5943 vos_timer_exit();
5944#endif
5945#ifdef MEMORY_DEBUG
5946 vos_mem_exit();
5947#endif
5948
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005949#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005951#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5953 }
5954 else
5955 {
5956 //Send WLAN UP indication to Nlink Service
5957 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5958
5959 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5960
5961 }
5962
5963 EXIT();
5964
5965 return ret_status;
5966}
5967
Jeff Johnson32d95a32012-09-10 13:15:23 -07005968/**---------------------------------------------------------------------------
5969
5970 \brief hdd_module_init() - Init Function
5971
5972 This is the driver entry point (invoked when module is loaded using insmod)
5973
5974 \param - None
5975
5976 \return - 0 for success, non zero for failure
5977
5978 --------------------------------------------------------------------------*/
5979#ifdef MODULE
5980static int __init hdd_module_init ( void)
5981{
5982 return hdd_driver_init();
5983}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005984#else /* #ifdef MODULE */
5985static int __init hdd_module_init ( void)
5986{
5987 /* Driver initialization is delayed to fwpath_changed_handler */
5988 return 0;
5989}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005990#endif /* #ifdef MODULE */
5991
Jeff Johnson295189b2012-06-20 16:38:30 -07005992
5993/**---------------------------------------------------------------------------
5994
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005995 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005996
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005997 This is the driver exit point (invoked when module is unloaded using rmmod
5998 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005999
6000 \param - None
6001
6002 \return - None
6003
6004 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006005static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006006{
6007 hdd_context_t *pHddCtx = NULL;
6008 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006009
6010 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6011
6012 //Get the global vos context
6013 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6014
6015 if(!pVosContext)
6016 {
6017 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6018 goto done;
6019 }
6020
6021 //Get the HDD context.
6022 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6023
6024 if(!pHddCtx)
6025 {
6026 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6027 }
6028 else
6029 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006030 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006031 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6033 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 }
6035
6036 pHddCtx->isLoadUnloadInProgress = TRUE;
6037 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6038
6039 //Do all the cleanup before deregistering the driver
6040 hdd_wlan_exit(pHddCtx);
6041 }
6042
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 vos_preClose( &pVosContext );
6044
6045#ifdef TIMER_MANAGER
6046 vos_timer_exit();
6047#endif
6048#ifdef MEMORY_DEBUG
6049 vos_mem_exit();
6050#endif
6051
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306052#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6053 vos_wconn_trace_exit();
6054#endif
6055
Jeff Johnson295189b2012-06-20 16:38:30 -07006056done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006057#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006058 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006059#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6061}
6062
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006063/**---------------------------------------------------------------------------
6064
6065 \brief hdd_module_exit() - Exit function
6066
6067 This is the driver exit point (invoked when module is unloaded using rmmod)
6068
6069 \param - None
6070
6071 \return - None
6072
6073 --------------------------------------------------------------------------*/
6074static void __exit hdd_module_exit(void)
6075{
6076 hdd_driver_exit();
6077}
6078
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006079#ifdef MODULE
6080static int fwpath_changed_handler(const char *kmessage,
6081 struct kernel_param *kp)
6082{
Jeff Johnson76052702013-04-16 13:55:05 -07006083 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006084}
6085
6086static int con_mode_handler(const char *kmessage,
6087 struct kernel_param *kp)
6088{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006089 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006090}
6091#else /* #ifdef MODULE */
6092/**---------------------------------------------------------------------------
6093
Jeff Johnson76052702013-04-16 13:55:05 -07006094 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006095
Jeff Johnson76052702013-04-16 13:55:05 -07006096 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006097 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006098 - invoked when module parameter fwpath is modified from userspace to signal
6099 initializing the WLAN driver or when con_mode is modified from userspace
6100 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006101
6102 \return - 0 for success, non zero for failure
6103
6104 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006105static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006106{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006107 int ret_status;
6108
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006109 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006110 ret_status = hdd_driver_init();
6111 wlan_hdd_inited = ret_status ? 0 : 1;
6112 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006113 }
6114
6115 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006116
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006117 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006118
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006119 ret_status = hdd_driver_init();
6120 wlan_hdd_inited = ret_status ? 0 : 1;
6121 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006122}
6123
Jeff Johnson295189b2012-06-20 16:38:30 -07006124/**---------------------------------------------------------------------------
6125
Jeff Johnson76052702013-04-16 13:55:05 -07006126 \brief fwpath_changed_handler() - Handler Function
6127
6128 Handle changes to the fwpath parameter
6129
6130 \return - 0 for success, non zero for failure
6131
6132 --------------------------------------------------------------------------*/
6133static int fwpath_changed_handler(const char *kmessage,
6134 struct kernel_param *kp)
6135{
6136 int ret;
6137
6138 ret = param_set_copystring(kmessage, kp);
6139 if (0 == ret)
6140 ret = kickstart_driver();
6141 return ret;
6142}
6143
6144/**---------------------------------------------------------------------------
6145
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006146 \brief con_mode_handler() -
6147
6148 Handler function for module param con_mode when it is changed by userspace
6149 Dynamically linked - do nothing
6150 Statically linked - exit and init driver, as in rmmod and insmod
6151
Jeff Johnson76052702013-04-16 13:55:05 -07006152 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006153
Jeff Johnson76052702013-04-16 13:55:05 -07006154 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006155
6156 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006157static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006158{
Jeff Johnson76052702013-04-16 13:55:05 -07006159 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006160
Jeff Johnson76052702013-04-16 13:55:05 -07006161 ret = param_set_int(kmessage, kp);
6162 if (0 == ret)
6163 ret = kickstart_driver();
6164 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006165}
6166#endif /* #ifdef MODULE */
6167
6168/**---------------------------------------------------------------------------
6169
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 \brief hdd_get_conparam() -
6171
6172 This is the driver exit point (invoked when module is unloaded using rmmod)
6173
6174 \param - None
6175
6176 \return - tVOS_CON_MODE
6177
6178 --------------------------------------------------------------------------*/
6179tVOS_CON_MODE hdd_get_conparam ( void )
6180{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006181#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006182 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006183#else
6184 return (tVOS_CON_MODE)curr_con_mode;
6185#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006186}
6187void hdd_set_conparam ( v_UINT_t newParam )
6188{
6189 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006190#ifndef MODULE
6191 curr_con_mode = con_mode;
6192#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006193}
6194/**---------------------------------------------------------------------------
6195
6196 \brief hdd_softap_sta_deauth() - function
6197
6198 This to take counter measure to handle deauth req from HDD
6199
6200 \param - pAdapter - Pointer to the HDD
6201
6202 \param - enable - boolean value
6203
6204 \return - None
6205
6206 --------------------------------------------------------------------------*/
6207
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006208VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006209{
Jeff Johnson295189b2012-06-20 16:38:30 -07006210 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006211 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006212
6213 ENTER();
6214
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306215 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006216
6217 //Ignore request to deauth bcmc station
6218 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006219 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006220
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006221 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006222
6223 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006224 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006225}
6226
6227/**---------------------------------------------------------------------------
6228
6229 \brief hdd_softap_sta_disassoc() - function
6230
6231 This to take counter measure to handle deauth req from HDD
6232
6233 \param - pAdapter - Pointer to the HDD
6234
6235 \param - enable - boolean value
6236
6237 \return - None
6238
6239 --------------------------------------------------------------------------*/
6240
6241void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6242{
6243 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6244
6245 ENTER();
6246
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306247 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006248
6249 //Ignore request to disassoc bcmc station
6250 if( pDestMacAddress[0] & 0x1 )
6251 return;
6252
6253 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6254}
6255
6256void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6257{
6258 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6259
6260 ENTER();
6261
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306262 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006263
6264 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6265}
6266
Jeff Johnson295189b2012-06-20 16:38:30 -07006267/**---------------------------------------------------------------------------
6268 *
6269 * \brief hdd_get__concurrency_mode() -
6270 *
6271 *
6272 * \param - None
6273 *
6274 * \return - CONCURRENCY MODE
6275 *
6276 * --------------------------------------------------------------------------*/
6277tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6278{
6279 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6280 hdd_context_t *pHddCtx;
6281
6282 if (NULL != pVosContext)
6283 {
6284 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6285 if (NULL != pHddCtx)
6286 {
6287 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6288 }
6289 }
6290
6291 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006292 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 return VOS_STA;
6294}
6295
6296/* Decide whether to allow/not the apps power collapse.
6297 * Allow apps power collapse if we are in connected state.
6298 * if not, allow only if we are in IMPS */
6299v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6300{
6301 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006302 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006303 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006304 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6305 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6306 hdd_adapter_t *pAdapter = NULL;
6307 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006308 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006309
Jeff Johnson295189b2012-06-20 16:38:30 -07006310 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6311 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006312
Yathish9f22e662012-12-10 14:21:35 -08006313 concurrent_state = hdd_get_concurrency_mode();
6314
6315#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6316 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6317 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6318 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6319 return TRUE;
6320#endif
6321
Jeff Johnson295189b2012-06-20 16:38:30 -07006322 /*loop through all adapters. TBD fix for Concurrency */
6323 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6324 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6325 {
6326 pAdapter = pAdapterNode->pAdapter;
6327 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6328 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6329 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006330 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006332 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006333 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6334 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006336 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006337 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6338 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006339 return FALSE;
6340 }
6341 }
6342 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6343 pAdapterNode = pNext;
6344 }
6345 return TRUE;
6346}
6347
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006348/* Decides whether to send suspend notification to Riva
6349 * if any adapter is in BMPS; then it is required */
6350v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6351{
6352 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6353 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6354
6355 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6356 {
6357 return TRUE;
6358 }
6359 return FALSE;
6360}
6361
Jeff Johnson295189b2012-06-20 16:38:30 -07006362void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6363{
6364 switch(mode)
6365 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006366 case VOS_STA_MODE:
6367 case VOS_P2P_CLIENT_MODE:
6368 case VOS_P2P_GO_MODE:
6369 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006370 pHddCtx->concurrency_mode |= (1 << mode);
6371 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 break;
6373 default:
6374 break;
6375
6376 }
6377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6378 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6379}
6380
6381
6382void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6383{
6384 switch(mode)
6385 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006386 case VOS_STA_MODE:
6387 case VOS_P2P_CLIENT_MODE:
6388 case VOS_P2P_GO_MODE:
6389 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006390 pHddCtx->no_of_sessions[mode]--;
6391 if (!(pHddCtx->no_of_sessions[mode]))
6392 pHddCtx->concurrency_mode &= (~(1 << mode));
6393 break;
6394 default:
6395 break;
6396 }
6397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6398 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6399}
6400
Jeff Johnsone7245742012-09-05 17:12:55 -07006401/**---------------------------------------------------------------------------
6402 *
6403 * \brief wlan_hdd_restart_init
6404 *
6405 * This function initalizes restart timer/flag. An internal function.
6406 *
6407 * \param - pHddCtx
6408 *
6409 * \return - None
6410 *
6411 * --------------------------------------------------------------------------*/
6412
6413static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6414{
6415 /* Initialize */
6416 pHddCtx->hdd_restart_retries = 0;
6417 atomic_set(&pHddCtx->isRestartInProgress, 0);
6418 vos_timer_init(&pHddCtx->hdd_restart_timer,
6419 VOS_TIMER_TYPE_SW,
6420 wlan_hdd_restart_timer_cb,
6421 pHddCtx);
6422}
6423/**---------------------------------------------------------------------------
6424 *
6425 * \brief wlan_hdd_restart_deinit
6426 *
6427 * This function cleans up the resources used. An internal function.
6428 *
6429 * \param - pHddCtx
6430 *
6431 * \return - None
6432 *
6433 * --------------------------------------------------------------------------*/
6434
6435static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6436{
6437
6438 VOS_STATUS vos_status;
6439 /* Block any further calls */
6440 atomic_set(&pHddCtx->isRestartInProgress, 1);
6441 /* Cleanup */
6442 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6443 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006444 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006445 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6446 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006447 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006448
6449}
6450
6451/**---------------------------------------------------------------------------
6452 *
6453 * \brief wlan_hdd_framework_restart
6454 *
6455 * This function uses a cfg80211 API to start a framework initiated WLAN
6456 * driver module unload/load.
6457 *
6458 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6459 *
6460 *
6461 * \param - pHddCtx
6462 *
6463 * \return - VOS_STATUS_SUCCESS: Success
6464 * VOS_STATUS_E_EMPTY: Adapter is Empty
6465 * VOS_STATUS_E_NOMEM: No memory
6466
6467 * --------------------------------------------------------------------------*/
6468
6469static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6470{
6471 VOS_STATUS status = VOS_STATUS_SUCCESS;
6472 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006473 int len = (sizeof (struct ieee80211_mgmt));
6474 struct ieee80211_mgmt *mgmt = NULL;
6475
6476 /* Prepare the DEAUTH managment frame with reason code */
6477 mgmt = kzalloc(len, GFP_KERNEL);
6478 if(mgmt == NULL)
6479 {
6480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6481 "%s: memory allocation failed (%d bytes)", __func__, len);
6482 return VOS_STATUS_E_NOMEM;
6483 }
6484 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006485
6486 /* Iterate over all adapters/devices */
6487 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6488 do
6489 {
6490 if( (status == VOS_STATUS_SUCCESS) &&
6491 pAdapterNode &&
6492 pAdapterNode->pAdapter)
6493 {
6494 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6495 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6496 pAdapterNode->pAdapter->dev->name,
6497 pAdapterNode->pAdapter->device_mode,
6498 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006499 /*
6500 * CFG80211 event to restart the driver
6501 *
6502 * 'cfg80211_send_unprot_deauth' sends a
6503 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6504 * of SME(Linux Kernel) state machine.
6505 *
6506 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6507 * the driver.
6508 *
6509 */
6510
6511 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006512 }
6513 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6514 pAdapterNode = pNext;
6515 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6516
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006517
6518 /* Free the allocated management frame */
6519 kfree(mgmt);
6520
Jeff Johnsone7245742012-09-05 17:12:55 -07006521 /* Retry until we unload or reach max count */
6522 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6523 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6524
6525 return status;
6526
6527}
6528/**---------------------------------------------------------------------------
6529 *
6530 * \brief wlan_hdd_restart_timer_cb
6531 *
6532 * Restart timer callback. An internal function.
6533 *
6534 * \param - User data:
6535 *
6536 * \return - None
6537 *
6538 * --------------------------------------------------------------------------*/
6539
6540void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6541{
6542 hdd_context_t *pHddCtx = usrDataForCallback;
6543 wlan_hdd_framework_restart(pHddCtx);
6544 return;
6545
6546}
6547
6548
6549/**---------------------------------------------------------------------------
6550 *
6551 * \brief wlan_hdd_restart_driver
6552 *
6553 * This function sends an event to supplicant to restart the WLAN driver.
6554 *
6555 * This function is called from vos_wlanRestart.
6556 *
6557 * \param - pHddCtx
6558 *
6559 * \return - VOS_STATUS_SUCCESS: Success
6560 * VOS_STATUS_E_EMPTY: Adapter is Empty
6561 * VOS_STATUS_E_ALREADY: Request already in progress
6562
6563 * --------------------------------------------------------------------------*/
6564VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6565{
6566 VOS_STATUS status = VOS_STATUS_SUCCESS;
6567
6568 /* A tight check to make sure reentrancy */
6569 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6570 {
6571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6572 "%s: WLAN restart is already in progress", __func__);
6573
6574 return VOS_STATUS_E_ALREADY;
6575 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006576 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006577#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006578 wcnss_reset_intr();
6579#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006580
Jeff Johnsone7245742012-09-05 17:12:55 -07006581 return status;
6582}
6583
6584
Jeff Johnson295189b2012-06-20 16:38:30 -07006585//Register the module init/exit functions
6586module_init(hdd_module_init);
6587module_exit(hdd_module_exit);
6588
6589MODULE_LICENSE("Dual BSD/GPL");
6590MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6591MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6592
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006593module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6594 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006595
Jeff Johnson76052702013-04-16 13:55:05 -07006596module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006597 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);