blob: a6dd988c2ae193c3e9f2d25420ef0df7d3ee93c6 [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
2137 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
2138 if (NULL == *pBuf)
2139 {
2140 hddLog(VOS_TRACE_LEVEL_FATAL,
2141 "%s: vos_mem_alloc failed ", __func__);
2142 return -EINVAL;
2143 }
2144
2145 /* the buffer received from the upper layer is character buffer,
2146 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2147 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2148 and f0 in 3rd location */
2149 for (i = 0, j = 0; j < *pBufLen; j += 2)
2150 {
2151 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2152 (*pBuf)[i++] = tempByte;
2153 }
2154 *pBufLen = i;
2155 return VOS_STATUS_SUCCESS;
2156}
2157
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002158/**---------------------------------------------------------------------------
2159
Srinivas Girigowdade697412013-02-14 16:31:48 -08002160 \brief hdd_parse_countryrev() - HDD Parse country code revision
2161
2162 This function parses the country code revision passed in the format
2163 SETCOUNTRYREV<space><Country code><space>revision
2164
2165 \param - pValue Pointer to input country code revision
2166 \param - pCountryCode Pointer to local output array to record country code
2167 \param - pRevision Pointer to store revision integer number
2168
2169 \return - 0 for success non-zero for failure
2170
2171 --------------------------------------------------------------------------*/
2172VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2173{
2174 tANI_U8 *inPtr = pValue;
2175 int tempInt;
2176
2177 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2178 /*no argument after the command*/
2179 if (NULL == inPtr)
2180 {
2181 return -EINVAL;
2182 }
2183
2184 /*no space after the command*/
2185 else if (SPACE_ASCII_VALUE != *inPtr)
2186 {
2187 return -EINVAL;
2188 }
2189
2190 /*removing empty spaces*/
2191 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2192
2193 /*no argument followed by spaces*/
2194 if ('\0' == *inPtr)
2195 {
2196 return -EINVAL;
2197 }
2198
2199 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002200 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002201
2202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2203 "Country code is : %s", pCountryCode);
2204
2205 /*inPtr pointing to the beginning of first space after country code */
2206 inPtr = strpbrk( inPtr, " " );
2207 /*no revision number after the country code argument */
2208 if (NULL == inPtr)
2209 {
2210 return -EINVAL;
2211 }
2212
2213 inPtr++;
2214
2215 /*removing empty space*/
2216 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2217
2218 /*no channel list after the number of channels argument and spaces*/
2219 if (0 == strncmp(pCountryCode, "KR", 2))
2220 {
2221 if ('\0' == *inPtr)
2222 {
2223 return -EINVAL;
2224 }
2225
2226 sscanf(inPtr, "%d", &tempInt);
2227 *pRevision = tempInt;
2228 }
2229 else
2230 {
2231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2232 "Revision input is required only for Country KR");
2233 return -EINVAL;
2234 }
2235 return VOS_STATUS_SUCCESS;
2236}
2237
2238/**---------------------------------------------------------------------------
2239
2240 \brief hdd_parse_channellist() - HDD Parse channel list
2241
2242 This function parses the channel list passed in the format
2243 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002244 if the Number of channels (N) does not match with the actual number of channels passed
2245 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2246 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2247 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2248 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002249
2250 \param - pValue Pointer to input channel list
2251 \param - ChannelList Pointer to local output array to record channel list
2252 \param - pNumChannels Pointer to number of roam scan channels
2253
2254 \return - 0 for success non-zero for failure
2255
2256 --------------------------------------------------------------------------*/
2257VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2258{
2259 tANI_U8 *inPtr = pValue;
2260 int tempInt;
2261 int j = 0;
2262 int v = 0;
2263 char buf[32];
2264
2265 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2266 /*no argument after the command*/
2267 if (NULL == inPtr)
2268 {
2269 return -EINVAL;
2270 }
2271
2272 /*no space after the command*/
2273 else if (SPACE_ASCII_VALUE != *inPtr)
2274 {
2275 return -EINVAL;
2276 }
2277
2278 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002279 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002280
2281 /*no argument followed by spaces*/
2282 if ('\0' == *inPtr)
2283 {
2284 return -EINVAL;
2285 }
2286
2287 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002288 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002289 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002290 if ((v < 0) ||
2291 (tempInt <= 0) ||
2292 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2293 {
2294 return -EINVAL;
2295 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002296
2297 *pNumChannels = tempInt;
2298
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2300 "Number of channels are: %d", *pNumChannels);
2301
2302 for (j = 0; j < (*pNumChannels); j++)
2303 {
2304 /*inPtr pointing to the beginning of first space after number of channels*/
2305 inPtr = strpbrk( inPtr, " " );
2306 /*no channel list after the number of channels argument*/
2307 if (NULL == inPtr)
2308 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002309 if (0 != j)
2310 {
2311 *pNumChannels = j;
2312 return VOS_STATUS_SUCCESS;
2313 }
2314 else
2315 {
2316 return -EINVAL;
2317 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002318 }
2319
2320 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002321 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002322
2323 /*no channel list after the number of channels argument and spaces*/
2324 if ( '\0' == *inPtr )
2325 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002326 if (0 != j)
2327 {
2328 *pNumChannels = j;
2329 return VOS_STATUS_SUCCESS;
2330 }
2331 else
2332 {
2333 return -EINVAL;
2334 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002335 }
2336
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002337 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002338 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002339 if ((v < 0) ||
2340 (tempInt <= 0) ||
2341 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2342 {
2343 return -EINVAL;
2344 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345 pChannelList[j] = tempInt;
2346
2347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2348 "Channel %d added to preferred channel list",
2349 pChannelList[j] );
2350 }
2351
Srinivas Girigowdade697412013-02-14 16:31:48 -08002352 return VOS_STATUS_SUCCESS;
2353}
2354
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002355
2356/**---------------------------------------------------------------------------
2357
2358 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2359
2360 This function parses the reasoc command data passed in the format
2361 REASSOC<space><bssid><space><channel>
2362
2363 \param - pValue Pointer to input country code revision
2364 \param - pTargetApBssid Pointer to target Ap bssid
2365 \param - pChannel Pointer to the Target AP channel
2366
2367 \return - 0 for success non-zero for failure
2368
2369 --------------------------------------------------------------------------*/
2370VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2371{
2372 tANI_U8 *inPtr = pValue;
2373 int tempInt;
2374 int v = 0;
2375 tANI_U8 tempBuf[32];
2376
2377 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2378 /*no argument after the command*/
2379 if (NULL == inPtr)
2380 {
2381 return -EINVAL;
2382 }
2383
2384 /*no space after the command*/
2385 else if (SPACE_ASCII_VALUE != *inPtr)
2386 {
2387 return -EINVAL;
2388 }
2389
2390 /*removing empty spaces*/
2391 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2392
2393 /*no argument followed by spaces*/
2394 if ('\0' == *inPtr)
2395 {
2396 return -EINVAL;
2397 }
2398
2399 /*getting the first argument ie the target AP bssid */
2400 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2401 {
2402 return -EINVAL;
2403 }
2404 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2405 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2406 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2407
2408 /* point to the next argument */
2409 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2410 /*no argument after the command*/
2411 if (NULL == inPtr) return -EINVAL;
2412
2413 /*removing empty spaces*/
2414 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2415
2416 /*no argument followed by spaces*/
2417 if ('\0' == *inPtr)
2418 {
2419 return -EINVAL;
2420 }
2421
2422 /*getting the next argument ie the channel number */
2423 sscanf(inPtr, "%s ", tempBuf);
2424 v = kstrtos32(tempBuf, 10, &tempInt);
2425 if ( v < 0) return -EINVAL;
2426
2427 *pChannel = tempInt;
2428 return VOS_STATUS_SUCCESS;
2429}
2430
2431#endif
2432
Jeff Johnson295189b2012-06-20 16:38:30 -07002433/**---------------------------------------------------------------------------
2434
2435 \brief hdd_open() - HDD Open function
2436
2437 This is called in response to ifconfig up
2438
2439 \param - dev Pointer to net_device structure
2440
2441 \return - 0 for success non-zero for failure
2442
2443 --------------------------------------------------------------------------*/
2444int hdd_open (struct net_device *dev)
2445{
2446 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2447 hdd_context_t *pHddCtx;
2448 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2449 VOS_STATUS status;
2450 v_BOOL_t in_standby = TRUE;
2451
2452 if (NULL == pAdapter)
2453 {
2454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002455 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002456 return -ENODEV;
2457 }
2458
2459 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2460 if (NULL == pHddCtx)
2461 {
2462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002463 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002464 return -ENODEV;
2465 }
2466
2467 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2468 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2469 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002470 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2471 {
2472 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302473 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002474 in_standby = FALSE;
2475 break;
2476 }
2477 else
2478 {
2479 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2480 pAdapterNode = pNext;
2481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002482 }
2483
2484 if (TRUE == in_standby)
2485 {
2486 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2487 {
2488 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2489 "wlan out of power save", __func__);
2490 return -EINVAL;
2491 }
2492 }
2493
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002494 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002495 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2496 {
2497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002498 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002499 /* Enable TX queues only when we are connected */
2500 netif_tx_start_all_queues(dev);
2501 }
2502
2503 return 0;
2504}
2505
2506int hdd_mon_open (struct net_device *dev)
2507{
2508 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2509
2510 if(pAdapter == NULL) {
2511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002512 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002513 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 }
2515
2516 netif_start_queue(dev);
2517
2518 return 0;
2519}
2520/**---------------------------------------------------------------------------
2521
2522 \brief hdd_stop() - HDD stop function
2523
2524 This is called in response to ifconfig down
2525
2526 \param - dev Pointer to net_device structure
2527
2528 \return - 0 for success non-zero for failure
2529
2530 --------------------------------------------------------------------------*/
2531
2532int hdd_stop (struct net_device *dev)
2533{
2534 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2535 hdd_context_t *pHddCtx;
2536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2537 VOS_STATUS status;
2538 v_BOOL_t enter_standby = TRUE;
2539
2540 ENTER();
2541
2542 if (NULL == pAdapter)
2543 {
2544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002545 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002546 return -ENODEV;
2547 }
2548
2549 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2550 if (NULL == pHddCtx)
2551 {
2552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002553 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 return -ENODEV;
2555 }
2556
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002557 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002558 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2559 netif_tx_disable(pAdapter->dev);
2560 netif_carrier_off(pAdapter->dev);
2561
2562
2563 /* SoftAP ifaces should never go in power save mode
2564 making sure same here. */
2565 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2566 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002568 )
2569 {
2570 /* SoftAP mode, so return from here */
2571 EXIT();
2572 return 0;
2573 }
2574
2575 /* Find if any iface is up then
2576 if any iface is up then can't put device to sleep/ power save mode. */
2577 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2578 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2579 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002580 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2581 {
2582 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302583 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002584 enter_standby = FALSE;
2585 break;
2586 }
2587 else
2588 {
2589 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2590 pAdapterNode = pNext;
2591 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 }
2593
2594 if (TRUE == enter_standby)
2595 {
2596 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2597 "entering standby", __func__);
2598 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2599 {
2600 /*log and return success*/
2601 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2602 "wlan in power save", __func__);
2603 }
2604 }
2605
2606 EXIT();
2607 return 0;
2608}
2609
2610/**---------------------------------------------------------------------------
2611
2612 \brief hdd_uninit() - HDD uninit function
2613
2614 This is called during the netdev unregister to uninitialize all data
2615associated with the device
2616
2617 \param - dev Pointer to net_device structure
2618
2619 \return - void
2620
2621 --------------------------------------------------------------------------*/
2622static void hdd_uninit (struct net_device *dev)
2623{
2624 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2625
2626 ENTER();
2627
2628 do
2629 {
2630 if (NULL == pAdapter)
2631 {
2632 hddLog(VOS_TRACE_LEVEL_FATAL,
2633 "%s: NULL pAdapter", __func__);
2634 break;
2635 }
2636
2637 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2638 {
2639 hddLog(VOS_TRACE_LEVEL_FATAL,
2640 "%s: Invalid magic", __func__);
2641 break;
2642 }
2643
2644 if (NULL == pAdapter->pHddCtx)
2645 {
2646 hddLog(VOS_TRACE_LEVEL_FATAL,
2647 "%s: NULL pHddCtx", __func__);
2648 break;
2649 }
2650
2651 if (dev != pAdapter->dev)
2652 {
2653 hddLog(VOS_TRACE_LEVEL_FATAL,
2654 "%s: Invalid device reference", __func__);
2655 /* we haven't validated all cases so let this go for now */
2656 }
2657
2658 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2659
2660 /* after uninit our adapter structure will no longer be valid */
2661 pAdapter->dev = NULL;
2662 pAdapter->magic = 0;
2663 } while (0);
2664
2665 EXIT();
2666}
2667
2668/**---------------------------------------------------------------------------
2669
2670 \brief hdd_release_firmware() -
2671
2672 This function calls the release firmware API to free the firmware buffer.
2673
2674 \param - pFileName Pointer to the File Name.
2675 pCtx - Pointer to the adapter .
2676
2677
2678 \return - 0 for success, non zero for failure
2679
2680 --------------------------------------------------------------------------*/
2681
2682VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2683{
2684 VOS_STATUS status = VOS_STATUS_SUCCESS;
2685 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2686 ENTER();
2687
2688
2689 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2690
2691 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2692
2693 if(pHddCtx->fw) {
2694 release_firmware(pHddCtx->fw);
2695 pHddCtx->fw = NULL;
2696 }
2697 else
2698 status = VOS_STATUS_E_FAILURE;
2699 }
2700 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2701 if(pHddCtx->nv) {
2702 release_firmware(pHddCtx->nv);
2703 pHddCtx->nv = NULL;
2704 }
2705 else
2706 status = VOS_STATUS_E_FAILURE;
2707
2708 }
2709
2710 EXIT();
2711 return status;
2712}
2713
2714/**---------------------------------------------------------------------------
2715
2716 \brief hdd_request_firmware() -
2717
2718 This function reads the firmware file using the request firmware
2719 API and returns the the firmware data and the firmware file size.
2720
2721 \param - pfileName - Pointer to the file name.
2722 - pCtx - Pointer to the adapter .
2723 - ppfw_data - Pointer to the pointer of the firmware data.
2724 - pSize - Pointer to the file size.
2725
2726 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2727
2728 --------------------------------------------------------------------------*/
2729
2730
2731VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2732{
2733 int status;
2734 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2735 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2736 ENTER();
2737
2738 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2739
2740 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2741
2742 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2743 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2744 __func__, pfileName);
2745 retval = VOS_STATUS_E_FAILURE;
2746 }
2747
2748 else {
2749 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2750 *pSize = pHddCtx->fw->size;
2751 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2752 __func__, *pSize);
2753 }
2754 }
2755 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2756
2757 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2758
2759 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2760 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2761 __func__, pfileName);
2762 retval = VOS_STATUS_E_FAILURE;
2763 }
2764
2765 else {
2766 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2767 *pSize = pHddCtx->nv->size;
2768 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2769 __func__, *pSize);
2770 }
2771 }
2772
2773 EXIT();
2774 return retval;
2775}
2776/**---------------------------------------------------------------------------
2777 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2778
2779 This is the function invoked by SME to inform the result of a full power
2780 request issued by HDD
2781
2782 \param - callbackcontext - Pointer to cookie
2783 status - result of request
2784
2785 \return - None
2786
2787--------------------------------------------------------------------------*/
2788void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2789{
2790 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2791
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002792 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002793 if(&pHddCtx->full_pwr_comp_var)
2794 {
2795 complete(&pHddCtx->full_pwr_comp_var);
2796 }
2797}
2798
2799/**---------------------------------------------------------------------------
2800
2801 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2802
2803 This is the function invoked by SME to inform the result of BMPS
2804 request issued by HDD
2805
2806 \param - callbackcontext - Pointer to cookie
2807 status - result of request
2808
2809 \return - None
2810
2811--------------------------------------------------------------------------*/
2812void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2813{
2814
2815 struct completion *completion_var = (struct completion*) callbackContext;
2816
2817 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2818 if(completion_var != NULL)
2819 {
2820 complete(completion_var);
2821 }
2822}
2823
2824/**---------------------------------------------------------------------------
2825
2826 \brief hdd_get_cfg_file_size() -
2827
2828 This function reads the configuration file using the request firmware
2829 API and returns the configuration file size.
2830
2831 \param - pCtx - Pointer to the adapter .
2832 - pFileName - Pointer to the file name.
2833 - pBufSize - Pointer to the buffer size.
2834
2835 \return - 0 for success, non zero for failure
2836
2837 --------------------------------------------------------------------------*/
2838
2839VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2840{
2841 int status;
2842 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2843
2844 ENTER();
2845
2846 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2847
2848 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2849 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2850 status = VOS_STATUS_E_FAILURE;
2851 }
2852 else {
2853 *pBufSize = pHddCtx->fw->size;
2854 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2855 release_firmware(pHddCtx->fw);
2856 pHddCtx->fw = NULL;
2857 }
2858
2859 EXIT();
2860 return VOS_STATUS_SUCCESS;
2861}
2862
2863/**---------------------------------------------------------------------------
2864
2865 \brief hdd_read_cfg_file() -
2866
2867 This function reads the configuration file using the request firmware
2868 API and returns the cfg data and the buffer size of the configuration file.
2869
2870 \param - pCtx - Pointer to the adapter .
2871 - pFileName - Pointer to the file name.
2872 - pBuffer - Pointer to the data buffer.
2873 - pBufSize - Pointer to the buffer size.
2874
2875 \return - 0 for success, non zero for failure
2876
2877 --------------------------------------------------------------------------*/
2878
2879VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2880 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2881{
2882 int status;
2883 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2884
2885 ENTER();
2886
2887 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2888
2889 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2890 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2891 return VOS_STATUS_E_FAILURE;
2892 }
2893 else {
2894 if(*pBufSize != pHddCtx->fw->size) {
2895 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2896 "file size", __func__);
2897 release_firmware(pHddCtx->fw);
2898 pHddCtx->fw = NULL;
2899 return VOS_STATUS_E_FAILURE;
2900 }
2901 else {
2902 if(pBuffer) {
2903 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2904 }
2905 release_firmware(pHddCtx->fw);
2906 pHddCtx->fw = NULL;
2907 }
2908 }
2909
2910 EXIT();
2911
2912 return VOS_STATUS_SUCCESS;
2913}
2914
2915/**---------------------------------------------------------------------------
2916
Jeff Johnson295189b2012-06-20 16:38:30 -07002917 \brief hdd_set_mac_address() -
2918
2919 This function sets the user specified mac address using
2920 the command ifconfig wlanX hw ether <mac adress>.
2921
2922 \param - dev - Pointer to the net device.
2923 - addr - Pointer to the sockaddr.
2924 \return - 0 for success, non zero for failure
2925
2926 --------------------------------------------------------------------------*/
2927
2928static int hdd_set_mac_address(struct net_device *dev, void *addr)
2929{
2930 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2931 struct sockaddr *psta_mac_addr = addr;
2932 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2933
2934 ENTER();
2935
2936 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2937
2938#ifdef HDD_SESSIONIZE
2939 // set the MAC address though the STA ID CFG.
2940 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2941 (v_U8_t *)&pAdapter->macAddressCurrent,
2942 sizeof( pAdapter->macAddressCurrent ),
2943 hdd_set_mac_addr_cb, VOS_FALSE );
2944#endif
2945
2946 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2947
2948 EXIT();
2949 return halStatus;
2950}
2951
2952tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2953{
2954 int i;
2955 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2956 {
2957 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2958 break;
2959 }
2960
2961 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2962 return NULL;
2963
2964 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2965 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2966}
2967
2968void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2969{
2970 int i;
2971 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2972 {
2973 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2974 {
2975 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2976 break;
2977 }
2978 }
2979 return;
2980}
2981
2982#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2983 static struct net_device_ops wlan_drv_ops = {
2984 .ndo_open = hdd_open,
2985 .ndo_stop = hdd_stop,
2986 .ndo_uninit = hdd_uninit,
2987 .ndo_start_xmit = hdd_hard_start_xmit,
2988 .ndo_tx_timeout = hdd_tx_timeout,
2989 .ndo_get_stats = hdd_stats,
2990 .ndo_do_ioctl = hdd_ioctl,
2991 .ndo_set_mac_address = hdd_set_mac_address,
2992 .ndo_select_queue = hdd_select_queue,
2993#ifdef WLAN_FEATURE_PACKET_FILTERING
2994#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2995 .ndo_set_rx_mode = hdd_set_multicast_list,
2996#else
2997 .ndo_set_multicast_list = hdd_set_multicast_list,
2998#endif //LINUX_VERSION_CODE
2999#endif
3000 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003001 static struct net_device_ops wlan_mon_drv_ops = {
3002 .ndo_open = hdd_mon_open,
3003 .ndo_stop = hdd_stop,
3004 .ndo_uninit = hdd_uninit,
3005 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3006 .ndo_tx_timeout = hdd_tx_timeout,
3007 .ndo_get_stats = hdd_stats,
3008 .ndo_do_ioctl = hdd_ioctl,
3009 .ndo_set_mac_address = hdd_set_mac_address,
3010 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003011
3012#endif
3013
3014void hdd_set_station_ops( struct net_device *pWlanDev )
3015{
3016#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3017 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3018 pWlanDev->netdev_ops = &wlan_drv_ops;
3019#else
3020 pWlanDev->open = hdd_open;
3021 pWlanDev->stop = hdd_stop;
3022 pWlanDev->uninit = hdd_uninit;
3023 pWlanDev->hard_start_xmit = NULL;
3024 pWlanDev->tx_timeout = hdd_tx_timeout;
3025 pWlanDev->get_stats = hdd_stats;
3026 pWlanDev->do_ioctl = hdd_ioctl;
3027 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3028 pWlanDev->set_mac_address = hdd_set_mac_address;
3029#endif
3030}
3031
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003032static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003033{
3034 struct net_device *pWlanDev = NULL;
3035 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003036 /*
3037 * cfg80211 initialization and registration....
3038 */
3039 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3040
Jeff Johnson295189b2012-06-20 16:38:30 -07003041 if(pWlanDev != NULL)
3042 {
3043
3044 //Save the pointer to the net_device in the HDD adapter
3045 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3046
Jeff Johnson295189b2012-06-20 16:38:30 -07003047 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3048
3049 pAdapter->dev = pWlanDev;
3050 pAdapter->pHddCtx = pHddCtx;
3051 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3052
3053 init_completion(&pAdapter->session_open_comp_var);
3054 init_completion(&pAdapter->session_close_comp_var);
3055 init_completion(&pAdapter->disconnect_comp_var);
3056 init_completion(&pAdapter->linkup_event_var);
3057 init_completion(&pAdapter->cancel_rem_on_chan_var);
3058 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003059#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3060 init_completion(&pAdapter->offchannel_tx_event);
3061#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003063#ifdef FEATURE_WLAN_TDLS
3064 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003065 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003066 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003067#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 init_completion(&pHddCtx->mc_sus_event_var);
3069 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003070 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003071
Jeff Johnson295189b2012-06-20 16:38:30 -07003072 pAdapter->isLinkUpSvcNeeded = FALSE;
3073 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3074 //Init the net_device structure
3075 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3076
3077 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3078 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3079 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3080 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3081
3082 hdd_set_station_ops( pAdapter->dev );
3083
3084 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003085 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3086 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3087 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003088 /* set pWlanDev's parent to underlying device */
3089 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3090 }
3091
3092 return pAdapter;
3093}
3094
3095VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3096{
3097 struct net_device *pWlanDev = pAdapter->dev;
3098 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3099 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3100 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3101
3102 if( rtnl_lock_held )
3103 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003104 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003105 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3106 {
3107 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3108 return VOS_STATUS_E_FAILURE;
3109 }
3110 }
3111 if (register_netdevice(pWlanDev))
3112 {
3113 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3114 return VOS_STATUS_E_FAILURE;
3115 }
3116 }
3117 else
3118 {
3119 if(register_netdev(pWlanDev))
3120 {
3121 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3122 return VOS_STATUS_E_FAILURE;
3123 }
3124 }
3125 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3126
3127 return VOS_STATUS_SUCCESS;
3128}
3129
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003130static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003131{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003132 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003133
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003134 if (NULL == pAdapter)
3135 {
3136 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3137 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003138 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003139
3140 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3141 {
3142 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3143 return eHAL_STATUS_NOT_INITIALIZED;
3144 }
3145
3146 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3147
3148 /* need to make sure all of our scheduled work has completed.
3149 * This callback is called from MC thread context, so it is safe to
3150 * to call below flush workqueue API from here.
3151 */
3152 flush_scheduled_work();
3153
3154 /* We can be blocked while waiting for scheduled work to be
3155 * flushed, and the adapter structure can potentially be freed, in
3156 * which case the magic will have been reset. So make sure the
3157 * magic is still good, and hence the adapter structure is still
3158 * valid, before signaling completion */
3159 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3160 {
3161 complete(&pAdapter->session_close_comp_var);
3162 }
3163
Jeff Johnson295189b2012-06-20 16:38:30 -07003164 return eHAL_STATUS_SUCCESS;
3165}
3166
3167VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3168{
3169 struct net_device *pWlanDev = pAdapter->dev;
3170 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3171 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3172 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3173 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3174 int rc = 0;
3175
3176 INIT_COMPLETION(pAdapter->session_open_comp_var);
3177 //Open a SME session for future operation
3178 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3179 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3180 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3181 {
3182 hddLog(VOS_TRACE_LEVEL_FATAL,
3183 "sme_OpenSession() failed with status code %08d [x%08lx]",
3184 halStatus, halStatus );
3185 status = VOS_STATUS_E_FAILURE;
3186 goto error_sme_open;
3187 }
3188
3189 //Block on a completion variable. Can't wait forever though.
3190 rc = wait_for_completion_interruptible_timeout(
3191 &pAdapter->session_open_comp_var,
3192 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3193 if (!rc)
3194 {
3195 hddLog(VOS_TRACE_LEVEL_FATAL,
3196 "Session is not opened within timeout period code %08d", rc );
3197 status = VOS_STATUS_E_FAILURE;
3198 goto error_sme_open;
3199 }
3200
3201 // Register wireless extensions
3202 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3203 {
3204 hddLog(VOS_TRACE_LEVEL_FATAL,
3205 "hdd_register_wext() failed with status code %08d [x%08lx]",
3206 halStatus, halStatus );
3207 status = VOS_STATUS_E_FAILURE;
3208 goto error_register_wext;
3209 }
3210 //Safe to register the hard_start_xmit function again
3211#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3212 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3213#else
3214 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3215#endif
3216
3217 //Set the Connection State to Not Connected
3218 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3219
3220 //Set the default operation channel
3221 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3222
3223 /* Make the default Auth Type as OPEN*/
3224 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3225
3226 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3227 {
3228 hddLog(VOS_TRACE_LEVEL_FATAL,
3229 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3230 status, status );
3231 goto error_init_txrx;
3232 }
3233
3234 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3235
3236 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3237 {
3238 hddLog(VOS_TRACE_LEVEL_FATAL,
3239 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3240 status, status );
3241 goto error_wmm_init;
3242 }
3243
3244 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3245
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003246#ifdef FEATURE_WLAN_TDLS
3247 if(0 != wlan_hdd_tdls_init(pAdapter))
3248 {
3249 status = VOS_STATUS_E_FAILURE;
3250 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3251 goto error_tdls_init;
3252 }
3253 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3254#endif
3255
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 return VOS_STATUS_SUCCESS;
3257
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003258#ifdef FEATURE_WLAN_TDLS
3259error_tdls_init:
3260 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3261 hdd_wmm_adapter_close(pAdapter);
3262#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003263error_wmm_init:
3264 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3265 hdd_deinit_tx_rx(pAdapter);
3266error_init_txrx:
3267 hdd_UnregisterWext(pWlanDev);
3268error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003269 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003270 {
3271 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003272 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003273 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003274 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003275 {
3276 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003277 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003278 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003279 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 }
3281}
3282error_sme_open:
3283 return status;
3284}
3285
Jeff Johnson295189b2012-06-20 16:38:30 -07003286void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3287{
3288 hdd_cfg80211_state_t *cfgState;
3289
3290 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3291
3292 if( NULL != cfgState->buf )
3293 {
3294 int rc;
3295 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3296 rc = wait_for_completion_interruptible_timeout(
3297 &pAdapter->tx_action_cnf_event,
3298 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3299 if(!rc)
3300 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003302 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3303 }
3304 }
3305 return;
3306}
Jeff Johnson295189b2012-06-20 16:38:30 -07003307
3308void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3309{
3310 ENTER();
3311 switch ( pAdapter->device_mode )
3312 {
3313 case WLAN_HDD_INFRA_STATION:
3314 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003315 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003316 {
3317 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3318 {
3319 hdd_deinit_tx_rx( pAdapter );
3320 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3321 }
3322
3323 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3324 {
3325 hdd_wmm_adapter_close( pAdapter );
3326 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3327 }
3328
Jeff Johnson295189b2012-06-20 16:38:30 -07003329 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003330#ifdef FEATURE_WLAN_TDLS
3331 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3332 {
3333 wlan_hdd_tdls_exit(pAdapter);
3334 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3335 }
3336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003337
3338 break;
3339 }
3340
3341 case WLAN_HDD_SOFTAP:
3342 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003343 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003344 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003345
3346 hdd_unregister_hostapd(pAdapter);
3347 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003349 break;
3350 }
3351
3352 case WLAN_HDD_MONITOR:
3353 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003354 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003355 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3356 {
3357 hdd_deinit_tx_rx( pAdapter );
3358 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3359 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003360 if(NULL != pAdapterforTx)
3361 {
3362 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3363 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 break;
3365 }
3366
3367
3368 default:
3369 break;
3370 }
3371
3372 EXIT();
3373}
3374
3375void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3376{
3377 struct net_device *pWlanDev = pAdapter->dev;
3378
3379 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3380 if( rtnl_held )
3381 {
3382 unregister_netdevice(pWlanDev);
3383 }
3384 else
3385 {
3386 unregister_netdev(pWlanDev);
3387 }
3388 // note that the pAdapter is no longer valid at this point
3389 // since the memory has been reclaimed
3390 }
3391
3392}
3393
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003394void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3395{
3396 tSirSetPowerParamsReq powerRequest = { 0 };
3397
3398 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -07003399 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003400
3401 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3402 {
3403 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3404 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3405 }
3406 else
3407 {
3408 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3409 }
3410
3411 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3412 *specified during Enter/Exit BMPS when LCD off*/
3413 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3414 NULL, eANI_BOOLEAN_FALSE);
3415 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3416 NULL, eANI_BOOLEAN_FALSE);
3417
3418 /* switch to the DTIM specified in cfg.ini */
3419 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3420 "Switch to DTIM%d", powerRequest.uListenInterval);
3421 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3422
3423}
3424
3425void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3426{
3427 /*Switch back to DTIM 1*/
3428 tSirSetPowerParamsReq powerRequest = { 0 };
3429
3430 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3431 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003432 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003433
3434 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3435 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3436 NULL, eANI_BOOLEAN_FALSE);
3437 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3438 NULL, eANI_BOOLEAN_FALSE);
3439
3440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3441 "Switch to DTIM%d",powerRequest.uListenInterval);
3442 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3443
3444}
3445
Jeff Johnson295189b2012-06-20 16:38:30 -07003446VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3447{
3448 VOS_STATUS status = VOS_STATUS_SUCCESS;
3449
3450 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3451 {
3452 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3453 }
3454
3455 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3456 {
3457 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3458 }
3459
3460 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3461 {
3462 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3463 }
3464
3465 return status;
3466}
3467
3468VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3469{
3470 hdd_adapter_t *pAdapter = NULL;
3471 eHalStatus halStatus;
3472 VOS_STATUS status = VOS_STATUS_E_INVAL;
3473 v_BOOL_t disableBmps = FALSE;
3474 v_BOOL_t disableImps = FALSE;
3475
3476 switch(session_type)
3477 {
3478 case WLAN_HDD_INFRA_STATION:
3479 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003480 case WLAN_HDD_P2P_CLIENT:
3481 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003482 //Exit BMPS -> Is Sta/P2P Client is already connected
3483 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3484 if((NULL != pAdapter)&&
3485 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3486 {
3487 disableBmps = TRUE;
3488 }
3489
3490 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3491 if((NULL != pAdapter)&&
3492 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3493 {
3494 disableBmps = TRUE;
3495 }
3496
3497 //Exit both Bmps and Imps incase of Go/SAP Mode
3498 if((WLAN_HDD_SOFTAP == session_type) ||
3499 (WLAN_HDD_P2P_GO == session_type))
3500 {
3501 disableBmps = TRUE;
3502 disableImps = TRUE;
3503 }
3504
3505 if(TRUE == disableImps)
3506 {
3507 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3508 {
3509 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3510 }
3511 }
3512
3513 if(TRUE == disableBmps)
3514 {
3515 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3516 {
3517 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3518
3519 if(eHAL_STATUS_SUCCESS != halStatus)
3520 {
3521 status = VOS_STATUS_E_FAILURE;
3522 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3523 VOS_ASSERT(0);
3524 return status;
3525 }
3526 }
3527
3528 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3529 {
3530 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3531
3532 if(eHAL_STATUS_SUCCESS != halStatus)
3533 {
3534 status = VOS_STATUS_E_FAILURE;
3535 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3536 VOS_ASSERT(0);
3537 return status;
3538 }
3539 }
3540 }
3541
3542 if((TRUE == disableBmps) ||
3543 (TRUE == disableImps))
3544 {
3545 /* Now, get the chip into Full Power now */
3546 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3547 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3548 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3549
3550 if(halStatus != eHAL_STATUS_SUCCESS)
3551 {
3552 if(halStatus == eHAL_STATUS_PMC_PENDING)
3553 {
3554 //Block on a completion variable. Can't wait forever though
3555 wait_for_completion_interruptible_timeout(
3556 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3557 }
3558 else
3559 {
3560 status = VOS_STATUS_E_FAILURE;
3561 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3562 VOS_ASSERT(0);
3563 return status;
3564 }
3565 }
3566
3567 status = VOS_STATUS_SUCCESS;
3568 }
3569
3570 break;
3571 }
3572 return status;
3573}
3574
3575hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003576 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003577 tANI_U8 rtnl_held )
3578{
3579 hdd_adapter_t *pAdapter = NULL;
3580 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3581 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3582 VOS_STATUS exitbmpsStatus;
3583
3584 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3585
3586 //Disable BMPS incase of Concurrency
3587 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3588
3589 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3590 {
3591 //Fail to Exit BMPS
3592 VOS_ASSERT(0);
3593 return NULL;
3594 }
3595
3596 switch(session_type)
3597 {
3598 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003599 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003600 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003601 {
3602 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3603
3604 if( NULL == pAdapter )
3605 return NULL;
3606
Jeff Johnsone7245742012-09-05 17:12:55 -07003607 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3608 NL80211_IFTYPE_P2P_CLIENT:
3609 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003610
Jeff Johnson295189b2012-06-20 16:38:30 -07003611 pAdapter->device_mode = session_type;
3612
3613 status = hdd_init_station_mode( pAdapter );
3614 if( VOS_STATUS_SUCCESS != status )
3615 goto err_free_netdev;
3616
3617 status = hdd_register_interface( pAdapter, rtnl_held );
3618 if( VOS_STATUS_SUCCESS != status )
3619 {
3620 hdd_deinit_adapter(pHddCtx, pAdapter);
3621 goto err_free_netdev;
3622 }
3623 //Stop the Interface TX queue.
3624 netif_tx_disable(pAdapter->dev);
3625 //netif_tx_disable(pWlanDev);
3626 netif_carrier_off(pAdapter->dev);
3627
3628 break;
3629 }
3630
Jeff Johnson295189b2012-06-20 16:38:30 -07003631 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003632 case WLAN_HDD_SOFTAP:
3633 {
3634 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3635 if( NULL == pAdapter )
3636 return NULL;
3637
Jeff Johnson295189b2012-06-20 16:38:30 -07003638 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3639 NL80211_IFTYPE_AP:
3640 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003641 pAdapter->device_mode = session_type;
3642
3643 status = hdd_init_ap_mode(pAdapter);
3644 if( VOS_STATUS_SUCCESS != status )
3645 goto err_free_netdev;
3646
3647 status = hdd_register_hostapd( pAdapter, rtnl_held );
3648 if( VOS_STATUS_SUCCESS != status )
3649 {
3650 hdd_deinit_adapter(pHddCtx, pAdapter);
3651 goto err_free_netdev;
3652 }
3653
3654 netif_tx_disable(pAdapter->dev);
3655 netif_carrier_off(pAdapter->dev);
3656
3657 hdd_set_conparam( 1 );
3658 break;
3659 }
3660 case WLAN_HDD_MONITOR:
3661 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003662 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3663 if( NULL == pAdapter )
3664 return NULL;
3665
3666 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3667 pAdapter->device_mode = session_type;
3668 status = hdd_register_interface( pAdapter, rtnl_held );
3669#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3670 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3671#else
3672 pAdapter->dev->open = hdd_mon_open;
3673 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3674#endif
3675 hdd_init_tx_rx( pAdapter );
3676 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3677 //Set adapter to be used for data tx. It will use either GO or softap.
3678 pAdapter->sessionCtx.monitor.pAdapterForTx =
3679 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003680 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3681 {
3682 pAdapter->sessionCtx.monitor.pAdapterForTx =
3683 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3684 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 /* This workqueue will be used to transmit management packet over
3686 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003687 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3688 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3689 return NULL;
3690 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003691
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3693 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003694 }
3695 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003696 case WLAN_HDD_FTM:
3697 {
3698 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3699
3700 if( NULL == pAdapter )
3701 return NULL;
3702 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3703 * message while loading driver in FTM mode. */
3704 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3705 pAdapter->device_mode = session_type;
3706 status = hdd_register_interface( pAdapter, rtnl_held );
3707 }
3708 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003709 default:
3710 {
3711 VOS_ASSERT(0);
3712 return NULL;
3713 }
3714 }
3715
3716
3717 if( VOS_STATUS_SUCCESS == status )
3718 {
3719 //Add it to the hdd's session list.
3720 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3721 if( NULL == pHddAdapterNode )
3722 {
3723 status = VOS_STATUS_E_NOMEM;
3724 }
3725 else
3726 {
3727 pHddAdapterNode->pAdapter = pAdapter;
3728 status = hdd_add_adapter_back ( pHddCtx,
3729 pHddAdapterNode );
3730 }
3731 }
3732
3733 if( VOS_STATUS_SUCCESS != status )
3734 {
3735 if( NULL != pAdapter )
3736 {
3737 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3738 pAdapter = NULL;
3739 }
3740 if( NULL != pHddAdapterNode )
3741 {
3742 vos_mem_free( pHddAdapterNode );
3743 }
3744
3745 goto resume_bmps;
3746 }
3747
3748 if(VOS_STATUS_SUCCESS == status)
3749 {
3750 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3751
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003752 //Initialize the WoWL service
3753 if(!hdd_init_wowl(pAdapter))
3754 {
3755 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3756 goto err_free_netdev;
3757 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003758 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003759 return pAdapter;
3760
3761err_free_netdev:
3762 free_netdev(pAdapter->dev);
3763 wlan_hdd_release_intf_addr( pHddCtx,
3764 pAdapter->macAddressCurrent.bytes );
3765
3766resume_bmps:
3767 //If bmps disabled enable it
3768 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3769 {
3770 hdd_enable_bmps_imps(pHddCtx);
3771 }
3772 return NULL;
3773}
3774
3775VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3776 tANI_U8 rtnl_held )
3777{
3778 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3779 VOS_STATUS status;
3780
3781 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3782 if( VOS_STATUS_SUCCESS != status )
3783 return status;
3784
3785 while ( pCurrent->pAdapter != pAdapter )
3786 {
3787 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3788 if( VOS_STATUS_SUCCESS != status )
3789 break;
3790
3791 pCurrent = pNext;
3792 }
3793 pAdapterNode = pCurrent;
3794 if( VOS_STATUS_SUCCESS == status )
3795 {
3796 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3797 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3798 hdd_remove_adapter( pHddCtx, pAdapterNode );
3799 vos_mem_free( pAdapterNode );
3800
Jeff Johnson295189b2012-06-20 16:38:30 -07003801
3802 /* If there is a single session of STA/P2P client, re-enable BMPS */
3803 if ((!vos_concurrent_sessions_running()) &&
3804 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3805 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3806 {
3807 hdd_enable_bmps_imps(pHddCtx);
3808 }
3809
3810 return VOS_STATUS_SUCCESS;
3811 }
3812
3813 return VOS_STATUS_E_FAILURE;
3814}
3815
3816VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3817{
3818 hdd_adapter_list_node_t *pHddAdapterNode;
3819 VOS_STATUS status;
3820
3821 ENTER();
3822
3823 do
3824 {
3825 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3826 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3827 {
3828 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3829 vos_mem_free( pHddAdapterNode );
3830 }
3831 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3832
3833 EXIT();
3834
3835 return VOS_STATUS_SUCCESS;
3836}
3837
3838void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3839{
3840 v_U8_t addIE[1] = {0};
3841
3842 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3843 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3844 eANI_BOOLEAN_FALSE) )
3845 {
3846 hddLog(LOGE,
3847 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3848 }
3849
3850 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3851 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3852 eANI_BOOLEAN_FALSE) )
3853 {
3854 hddLog(LOGE,
3855 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3856 }
3857
3858 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3859 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3860 eANI_BOOLEAN_FALSE) )
3861 {
3862 hddLog(LOGE,
3863 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3864 }
3865}
3866
3867VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3868{
3869 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3870 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3871 union iwreq_data wrqu;
3872
3873 ENTER();
3874
3875 switch(pAdapter->device_mode)
3876 {
3877 case WLAN_HDD_INFRA_STATION:
3878 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003879 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003880 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3881 {
3882 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3883 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3884 pAdapter->sessionId,
3885 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3886 else
3887 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3888 pAdapter->sessionId,
3889 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3890 //success implies disconnect command got queued up successfully
3891 if(halStatus == eHAL_STATUS_SUCCESS)
3892 {
3893 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3894 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3895 }
3896 memset(&wrqu, '\0', sizeof(wrqu));
3897 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3898 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3899 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3900 }
3901 else
3902 {
3903 hdd_abort_mac_scan(pHddCtx);
3904 }
3905
3906 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3907 {
3908 INIT_COMPLETION(pAdapter->session_close_comp_var);
3909 if (eHAL_STATUS_SUCCESS ==
3910 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3911 hdd_smeCloseSessionCallback, pAdapter))
3912 {
3913 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003914 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003915 &pAdapter->session_close_comp_var,
3916 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3917 }
3918 }
3919
3920 break;
3921
3922 case WLAN_HDD_SOFTAP:
3923 case WLAN_HDD_P2P_GO:
3924 //Any softap specific cleanup here...
3925 mutex_lock(&pHddCtx->sap_lock);
3926 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3927 {
3928 VOS_STATUS status;
3929 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3930
3931 //Stop Bss.
3932 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3933 if (VOS_IS_STATUS_SUCCESS(status))
3934 {
3935 hdd_hostapd_state_t *pHostapdState =
3936 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3937
3938 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3939
3940 if (!VOS_IS_STATUS_SUCCESS(status))
3941 {
3942 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003943 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003944 }
3945 }
3946 else
3947 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003948 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003949 }
3950 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3951
3952 if (eHAL_STATUS_FAILURE ==
3953 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3954 0, NULL, eANI_BOOLEAN_FALSE))
3955 {
3956 hddLog(LOGE,
3957 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003958 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003959 }
3960
3961 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3962 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3963 eANI_BOOLEAN_FALSE) )
3964 {
3965 hddLog(LOGE,
3966 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3967 }
3968
3969 // Reset WNI_CFG_PROBE_RSP Flags
3970 wlan_hdd_reset_prob_rspies(pAdapter);
3971 kfree(pAdapter->sessionCtx.ap.beacon);
3972 pAdapter->sessionCtx.ap.beacon = NULL;
3973 }
3974 mutex_unlock(&pHddCtx->sap_lock);
3975 break;
3976 case WLAN_HDD_MONITOR:
3977 break;
3978 default:
3979 break;
3980 }
3981
3982 EXIT();
3983 return VOS_STATUS_SUCCESS;
3984}
3985
3986VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3987{
3988 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3989 VOS_STATUS status;
3990 hdd_adapter_t *pAdapter;
3991
3992 ENTER();
3993
3994 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3995
3996 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3997 {
3998 pAdapter = pAdapterNode->pAdapter;
3999 netif_tx_disable(pAdapter->dev);
4000 netif_carrier_off(pAdapter->dev);
4001
4002 hdd_stop_adapter( pHddCtx, pAdapter );
4003
4004 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4005 pAdapterNode = pNext;
4006 }
4007
4008 EXIT();
4009
4010 return VOS_STATUS_SUCCESS;
4011}
4012
4013VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4014{
4015 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4016 VOS_STATUS status;
4017 hdd_adapter_t *pAdapter;
4018
4019 ENTER();
4020
4021 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4022
4023 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4024 {
4025 pAdapter = pAdapterNode->pAdapter;
4026 netif_tx_disable(pAdapter->dev);
4027 netif_carrier_off(pAdapter->dev);
4028
4029 //Record whether STA is associated
4030 pAdapter->sessionCtx.station.bSendDisconnect =
4031 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
4032 VOS_TRUE : VOS_FALSE;
4033
4034 hdd_deinit_tx_rx(pAdapter);
4035 hdd_wmm_adapter_close(pAdapter);
4036
4037 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4038 pAdapterNode = pNext;
4039 }
4040
4041 EXIT();
4042
4043 return VOS_STATUS_SUCCESS;
4044}
4045
4046VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4047{
4048 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4049 VOS_STATUS status;
4050 hdd_adapter_t *pAdapter;
4051 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
4052
4053 ENTER();
4054
4055 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4056
4057 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4058 {
4059 pAdapter = pAdapterNode->pAdapter;
4060
4061 switch(pAdapter->device_mode)
4062 {
4063 case WLAN_HDD_INFRA_STATION:
4064 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004065 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004066 hdd_init_station_mode(pAdapter);
4067 /* Open the gates for HDD to receive Wext commands */
4068 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004069 pHddCtx->scan_info.mScanPending = FALSE;
4070 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004071
4072 //Trigger the initial scan
4073 hdd_wlan_initial_scan(pAdapter);
4074
4075 //Indicate disconnect event to supplicant if associated previously
4076 if(pAdapter->sessionCtx.station.bSendDisconnect)
4077 {
4078 union iwreq_data wrqu;
4079 memset(&wrqu, '\0', sizeof(wrqu));
4080 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4081 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4082 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4083 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
4084
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 /* indicate disconnected event to nl80211 */
4086 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4087 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004088 }
4089 break;
4090
4091 case WLAN_HDD_SOFTAP:
4092 /* softAP can handle SSR */
4093 break;
4094
4095 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4097 __func__);
4098 /* event supplicant to restart */
4099 cfg80211_del_sta(pAdapter->dev,
4100 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004101 break;
4102
4103 case WLAN_HDD_MONITOR:
4104 /* monitor interface start */
4105 break;
4106 default:
4107 break;
4108 }
4109
4110 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4111 pAdapterNode = pNext;
4112 }
4113
4114 EXIT();
4115
4116 return VOS_STATUS_SUCCESS;
4117}
4118
4119VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4120{
4121 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4122 hdd_adapter_t *pAdapter;
4123 VOS_STATUS status;
4124 v_U32_t roamId;
4125
4126 ENTER();
4127
4128 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4129
4130 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4131 {
4132 pAdapter = pAdapterNode->pAdapter;
4133
4134 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4135 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4136 {
4137 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4138 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4139
4140 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4141 init_completion(&pAdapter->disconnect_comp_var);
4142 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4143 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4144
4145 wait_for_completion_interruptible_timeout(
4146 &pAdapter->disconnect_comp_var,
4147 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4148
4149 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4150 pHddCtx->isAmpAllowed = VOS_FALSE;
4151 sme_RoamConnect(pHddCtx->hHal,
4152 pAdapter->sessionId, &(pWextState->roamProfile),
4153 &roamId);
4154 }
4155
4156 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4157 pAdapterNode = pNext;
4158 }
4159
4160 EXIT();
4161
4162 return VOS_STATUS_SUCCESS;
4163}
4164
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004165void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4166{
4167 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4168 VOS_STATUS status;
4169 hdd_adapter_t *pAdapter;
4170 hdd_station_ctx_t *pHddStaCtx;
4171 hdd_ap_ctx_t *pHddApCtx;
4172 hdd_hostapd_state_t * pHostapdState;
4173 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4174 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4175 const char *p2pMode = "DEV";
4176 const char *ccMode = "Standalone";
4177 int n;
4178
4179 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4180 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4181 {
4182 pAdapter = pAdapterNode->pAdapter;
4183 switch (pAdapter->device_mode) {
4184 case WLAN_HDD_INFRA_STATION:
4185 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4186 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4187 staChannel = pHddStaCtx->conn_info.operationChannel;
4188 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4189 }
4190 break;
4191 case WLAN_HDD_P2P_CLIENT:
4192 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4193 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4194 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4195 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4196 p2pMode = "CLI";
4197 }
4198 break;
4199 case WLAN_HDD_P2P_GO:
4200 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4201 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4202 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4203 p2pChannel = pHddApCtx->operatingChannel;
4204 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4205 }
4206 p2pMode = "GO";
4207 break;
4208 case WLAN_HDD_SOFTAP:
4209 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4210 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4211 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4212 apChannel = pHddApCtx->operatingChannel;
4213 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4214 }
4215 break;
4216 default:
4217 break;
4218 }
4219 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4220 pAdapterNode = pNext;
4221 }
4222 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4223 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4224 }
4225 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4226 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4227 if (p2pChannel > 0) {
4228 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4229 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4230 }
4231 if (apChannel > 0) {
4232 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4233 apChannel, MAC_ADDR_ARRAY(apBssid));
4234 }
4235
4236 if (p2pChannel > 0 && apChannel > 0) {
4237 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4238 }
4239}
4240
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004241bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004242{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004243 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004244}
4245
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004246/* Once SSR is disabled then it cannot be set. */
4247void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004248{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004249 if (HDD_SSR_DISABLED == isSsrRequired)
4250 return;
4251
Jeff Johnson295189b2012-06-20 16:38:30 -07004252 isSsrRequired = value;
4253}
4254
4255VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4256 hdd_adapter_list_node_t** ppAdapterNode)
4257{
4258 VOS_STATUS status;
4259 spin_lock(&pHddCtx->hddAdapters.lock);
4260 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4261 (hdd_list_node_t**) ppAdapterNode );
4262 spin_unlock(&pHddCtx->hddAdapters.lock);
4263 return status;
4264}
4265
4266VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4267 hdd_adapter_list_node_t* pAdapterNode,
4268 hdd_adapter_list_node_t** pNextAdapterNode)
4269{
4270 VOS_STATUS status;
4271 spin_lock(&pHddCtx->hddAdapters.lock);
4272 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4273 (hdd_list_node_t*) pAdapterNode,
4274 (hdd_list_node_t**)pNextAdapterNode );
4275
4276 spin_unlock(&pHddCtx->hddAdapters.lock);
4277 return status;
4278}
4279
4280VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4281 hdd_adapter_list_node_t* pAdapterNode)
4282{
4283 VOS_STATUS status;
4284 spin_lock(&pHddCtx->hddAdapters.lock);
4285 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4286 &pAdapterNode->node );
4287 spin_unlock(&pHddCtx->hddAdapters.lock);
4288 return status;
4289}
4290
4291VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4292 hdd_adapter_list_node_t** ppAdapterNode)
4293{
4294 VOS_STATUS status;
4295 spin_lock(&pHddCtx->hddAdapters.lock);
4296 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4297 (hdd_list_node_t**) ppAdapterNode );
4298 spin_unlock(&pHddCtx->hddAdapters.lock);
4299 return status;
4300}
4301
4302VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4303 hdd_adapter_list_node_t* pAdapterNode)
4304{
4305 VOS_STATUS status;
4306 spin_lock(&pHddCtx->hddAdapters.lock);
4307 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4308 (hdd_list_node_t*) pAdapterNode );
4309 spin_unlock(&pHddCtx->hddAdapters.lock);
4310 return status;
4311}
4312
4313VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4314 hdd_adapter_list_node_t* pAdapterNode)
4315{
4316 VOS_STATUS status;
4317 spin_lock(&pHddCtx->hddAdapters.lock);
4318 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4319 (hdd_list_node_t*) pAdapterNode );
4320 spin_unlock(&pHddCtx->hddAdapters.lock);
4321 return status;
4322}
4323
4324hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4325 tSirMacAddr macAddr )
4326{
4327 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4328 hdd_adapter_t *pAdapter;
4329 VOS_STATUS status;
4330
4331 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4332
4333 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4334 {
4335 pAdapter = pAdapterNode->pAdapter;
4336
4337 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4338 macAddr, sizeof(tSirMacAddr) ) )
4339 {
4340 return pAdapter;
4341 }
4342 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4343 pAdapterNode = pNext;
4344 }
4345
4346 return NULL;
4347
4348}
4349
4350hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4351{
4352 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4353 hdd_adapter_t *pAdapter;
4354 VOS_STATUS status;
4355
4356 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4357
4358 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4359 {
4360 pAdapter = pAdapterNode->pAdapter;
4361
4362 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4363 IFNAMSIZ ) )
4364 {
4365 return pAdapter;
4366 }
4367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4368 pAdapterNode = pNext;
4369 }
4370
4371 return NULL;
4372
4373}
4374
4375hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4376{
4377 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4378 hdd_adapter_t *pAdapter;
4379 VOS_STATUS status;
4380
4381 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4382
4383 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4384 {
4385 pAdapter = pAdapterNode->pAdapter;
4386
4387 if( pAdapter && (mode == pAdapter->device_mode) )
4388 {
4389 return pAdapter;
4390 }
4391 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4392 pAdapterNode = pNext;
4393 }
4394
4395 return NULL;
4396
4397}
4398
4399//Remove this function later
4400hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4401{
4402 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4403 hdd_adapter_t *pAdapter;
4404 VOS_STATUS status;
4405
4406 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4407
4408 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4409 {
4410 pAdapter = pAdapterNode->pAdapter;
4411
4412 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4413 {
4414 return pAdapter;
4415 }
4416
4417 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4418 pAdapterNode = pNext;
4419 }
4420
4421 return NULL;
4422
4423}
4424
Jeff Johnson295189b2012-06-20 16:38:30 -07004425/**---------------------------------------------------------------------------
4426
4427 \brief hdd_set_monitor_tx_adapter() -
4428
4429 This API initializes the adapter to be used while transmitting on monitor
4430 adapter.
4431
4432 \param - pHddCtx - Pointer to the HDD context.
4433 pAdapter - Adapter that will used for TX. This can be NULL.
4434 \return - None.
4435 --------------------------------------------------------------------------*/
4436void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4437{
4438 hdd_adapter_t *pMonAdapter;
4439
4440 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4441
4442 if( NULL != pMonAdapter )
4443 {
4444 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4445 }
4446}
Jeff Johnson295189b2012-06-20 16:38:30 -07004447/**---------------------------------------------------------------------------
4448
4449 \brief hdd_select_queue() -
4450
4451 This API returns the operating channel of the requested device mode
4452
4453 \param - pHddCtx - Pointer to the HDD context.
4454 - mode - Device mode for which operating channel is required
4455 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4456 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4457 \return - channel number. "0" id the requested device is not found OR it is not connected.
4458 --------------------------------------------------------------------------*/
4459v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4460{
4461 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4462 VOS_STATUS status;
4463 hdd_adapter_t *pAdapter;
4464 v_U8_t operatingChannel = 0;
4465
4466 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4467
4468 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4469 {
4470 pAdapter = pAdapterNode->pAdapter;
4471
4472 if( mode == pAdapter->device_mode )
4473 {
4474 switch(pAdapter->device_mode)
4475 {
4476 case WLAN_HDD_INFRA_STATION:
4477 case WLAN_HDD_P2P_CLIENT:
4478 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4479 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4480 break;
4481 case WLAN_HDD_SOFTAP:
4482 case WLAN_HDD_P2P_GO:
4483 /*softap connection info */
4484 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4485 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4486 break;
4487 default:
4488 break;
4489 }
4490
4491 break; //Found the device of interest. break the loop
4492 }
4493
4494 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4495 pAdapterNode = pNext;
4496 }
4497 return operatingChannel;
4498}
4499
4500#ifdef WLAN_FEATURE_PACKET_FILTERING
4501/**---------------------------------------------------------------------------
4502
4503 \brief hdd_set_multicast_list() -
4504
4505 This used to set the multicast address list.
4506
4507 \param - dev - Pointer to the WLAN device.
4508 - skb - Pointer to OS packet (sk_buff).
4509 \return - success/fail
4510
4511 --------------------------------------------------------------------------*/
4512static void hdd_set_multicast_list(struct net_device *dev)
4513{
4514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004515 int mc_count;
4516 int i = 0;
4517 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304518
4519 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 {
4521 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304522 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 return;
4524 }
4525
4526 if (dev->flags & IFF_ALLMULTI)
4527 {
4528 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004529 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304530 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004531 }
4532 else
4533 {
4534 mc_count = netdev_mc_count(dev);
4535 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004536 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004537 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4538 {
4539 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004540 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304541 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004542 return;
4543 }
4544
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304545 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004546
4547 netdev_for_each_mc_addr(ha, dev) {
4548 if (i == mc_count)
4549 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304550 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4551 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4552 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004553 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304554 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004555 i++;
4556 }
4557 }
4558 return;
4559}
4560#endif
4561
4562/**---------------------------------------------------------------------------
4563
4564 \brief hdd_select_queue() -
4565
4566 This function is registered with the Linux OS for network
4567 core to decide which queue to use first.
4568
4569 \param - dev - Pointer to the WLAN device.
4570 - skb - Pointer to OS packet (sk_buff).
4571 \return - ac, Queue Index/access category corresponding to UP in IP header
4572
4573 --------------------------------------------------------------------------*/
4574v_U16_t hdd_select_queue(struct net_device *dev,
4575 struct sk_buff *skb)
4576{
4577 return hdd_wmm_select_queue(dev, skb);
4578}
4579
4580
4581/**---------------------------------------------------------------------------
4582
4583 \brief hdd_wlan_initial_scan() -
4584
4585 This function triggers the initial scan
4586
4587 \param - pAdapter - Pointer to the HDD adapter.
4588
4589 --------------------------------------------------------------------------*/
4590void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4591{
4592 tCsrScanRequest scanReq;
4593 tCsrChannelInfo channelInfo;
4594 eHalStatus halStatus;
4595 unsigned long scanId;
4596 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4597
4598 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4599 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4600 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4601
4602 if(sme_Is11dSupported(pHddCtx->hHal))
4603 {
4604 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4605 if ( HAL_STATUS_SUCCESS( halStatus ) )
4606 {
4607 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4608 if( !scanReq.ChannelInfo.ChannelList )
4609 {
4610 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4611 vos_mem_free(channelInfo.ChannelList);
4612 return;
4613 }
4614 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4615 channelInfo.numOfChannels);
4616 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4617 vos_mem_free(channelInfo.ChannelList);
4618 }
4619
4620 scanReq.scanType = eSIR_PASSIVE_SCAN;
4621 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4622 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4623 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4624 }
4625 else
4626 {
4627 scanReq.scanType = eSIR_ACTIVE_SCAN;
4628 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4629 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4630 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4631 }
4632
4633 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4634 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4635 {
4636 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4637 __func__, halStatus );
4638 }
4639
4640 if(sme_Is11dSupported(pHddCtx->hHal))
4641 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4642}
4643
4644struct fullPowerContext
4645{
4646 struct completion completion;
4647 unsigned int magic;
4648};
4649#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4650
4651/**---------------------------------------------------------------------------
4652
4653 \brief hdd_full_power_callback() - HDD full power callback function
4654
4655 This is the function invoked by SME to inform the result of a full power
4656 request issued by HDD
4657
4658 \param - callbackcontext - Pointer to cookie
4659 \param - status - result of request
4660
4661 \return - None
4662
4663 --------------------------------------------------------------------------*/
4664static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4665{
4666 struct fullPowerContext *pContext = callbackContext;
4667
4668 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304669 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004670
4671 if (NULL == callbackContext)
4672 {
4673 hddLog(VOS_TRACE_LEVEL_ERROR,
4674 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004675 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004676 return;
4677 }
4678
4679 /* there is a race condition that exists between this callback function
4680 and the caller since the caller could time out either before or
4681 while this code is executing. we'll assume the timeout hasn't
4682 occurred, but we'll verify that right before we save our work */
4683
4684 if (POWER_CONTEXT_MAGIC != pContext->magic)
4685 {
4686 /* the caller presumably timed out so there is nothing we can do */
4687 hddLog(VOS_TRACE_LEVEL_WARN,
4688 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004689 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004690 return;
4691 }
4692
4693 /* the race is on. caller could have timed out immediately after
4694 we verified the magic, but if so, caller will wait a short time
4695 for us to notify the caller, so the context will stay valid */
4696 complete(&pContext->completion);
4697}
4698
4699/**---------------------------------------------------------------------------
4700
4701 \brief hdd_wlan_exit() - HDD WLAN exit function
4702
4703 This is the driver exit point (invoked during rmmod)
4704
4705 \param - pHddCtx - Pointer to the HDD Context
4706
4707 \return - None
4708
4709 --------------------------------------------------------------------------*/
4710void hdd_wlan_exit(hdd_context_t *pHddCtx)
4711{
4712 eHalStatus halStatus;
4713 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4714 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304715 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004716 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 struct fullPowerContext powerContext;
4718 long lrc;
4719
4720 ENTER();
4721
Jeff Johnson88ba7742013-02-27 14:36:02 -08004722 if (VOS_FTM_MODE != hdd_get_conparam())
4723 {
4724 // Unloading, restart logic is no more required.
4725 wlan_hdd_restart_deinit(pHddCtx);
4726 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004727
Jeff Johnson295189b2012-06-20 16:38:30 -07004728 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004729 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004730 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 {
4732 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4733 WLAN_HDD_INFRA_STATION);
4734 if (pAdapter == NULL)
4735 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4736
4737 if (pAdapter != NULL)
4738 {
4739 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4740 hdd_UnregisterWext(pAdapter->dev);
4741 }
4742 }
4743 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004744
Jeff Johnson295189b2012-06-20 16:38:30 -07004745 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004746 {
4747 wlan_hdd_ftm_close(pHddCtx);
4748 goto free_hdd_ctx;
4749 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004750 //Stop the Interface TX queue.
4751 //netif_tx_disable(pWlanDev);
4752 //netif_carrier_off(pWlanDev);
4753
Jeff Johnson295189b2012-06-20 16:38:30 -07004754 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4755 {
4756 pAdapter = hdd_get_adapter(pHddCtx,
4757 WLAN_HDD_SOFTAP);
4758 }
4759 else
4760 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004762 {
4763 pAdapter = hdd_get_adapter(pHddCtx,
4764 WLAN_HDD_INFRA_STATION);
4765 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004766 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004767 /* DeRegister with platform driver as client for Suspend/Resume */
4768 vosStatus = hddDeregisterPmOps(pHddCtx);
4769 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4770 {
4771 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4772 VOS_ASSERT(0);
4773 }
4774
4775 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4776 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4777 {
4778 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4779 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004780
4781 // Cancel any outstanding scan requests. We are about to close all
4782 // of our adapters, but an adapter structure is what SME passes back
4783 // to our callback function. Hence if there are any outstanding scan
4784 // requests then there is a race condition between when the adapter
4785 // is closed and when the callback is invoked. We try to resolve that
4786 // race condition here by canceling any outstanding scans before we
4787 // close the adapters.
4788 // Note that the scans may be cancelled in an asynchronous manner, so
4789 // ideally there needs to be some kind of synchronization. Rather than
4790 // introduce a new synchronization here, we will utilize the fact that
4791 // we are about to Request Full Power, and since that is synchronized,
4792 // the expectation is that by the time Request Full Power has completed,
4793 // all scans will be cancelled.
4794 hdd_abort_mac_scan( pHddCtx );
4795
4796 //Disable IMPS/BMPS as we do not want the device to enter any power
4797 //save mode during shutdown
4798 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4799 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4800 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4801
4802 //Ensure that device is in full power as we will touch H/W during vos_Stop
4803 init_completion(&powerContext.completion);
4804 powerContext.magic = POWER_CONTEXT_MAGIC;
4805
4806 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4807 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4808
4809 if (eHAL_STATUS_SUCCESS != halStatus)
4810 {
4811 if (eHAL_STATUS_PMC_PENDING == halStatus)
4812 {
4813 /* request was sent -- wait for the response */
4814 lrc = wait_for_completion_interruptible_timeout(
4815 &powerContext.completion,
4816 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4817 /* either we have a response or we timed out
4818 either way, first invalidate our magic */
4819 powerContext.magic = 0;
4820 if (lrc <= 0)
4821 {
4822 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004823 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 /* there is a race condition such that the callback
4825 function could be executing at the same time we are. of
4826 primary concern is if the callback function had already
4827 verified the "magic" but hasn't yet set the completion
4828 variable. Since the completion variable is on our
4829 stack, we'll delay just a bit to make sure the data is
4830 still valid if that is the case */
4831 msleep(50);
4832 }
4833 }
4834 else
4835 {
4836 hddLog(VOS_TRACE_LEVEL_ERROR,
4837 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004838 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 VOS_ASSERT(0);
4840 /* continue -- need to clean up as much as possible */
4841 }
4842 }
4843
4844 // Unregister the Net Device Notifier
4845 unregister_netdevice_notifier(&hdd_netdev_notifier);
4846
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 hdd_stop_all_adapters( pHddCtx );
4848
Jeff Johnson295189b2012-06-20 16:38:30 -07004849#ifdef WLAN_BTAMP_FEATURE
4850 vosStatus = WLANBAP_Stop(pVosContext);
4851 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4852 {
4853 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4854 "%s: Failed to stop BAP",__func__);
4855 }
4856#endif //WLAN_BTAMP_FEATURE
4857
4858 //Stop all the modules
4859 vosStatus = vos_stop( pVosContext );
4860 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4861 {
4862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4863 "%s: Failed to stop VOSS",__func__);
4864 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4865 }
4866
Jeff Johnson295189b2012-06-20 16:38:30 -07004867 //Assert Deep sleep signal now to put Libra HW in lowest power state
4868 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4869 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4870
4871 //Vote off any PMIC voltage supplies
4872 vos_chipPowerDown(NULL, NULL, NULL);
4873
4874 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4875
4876 //Clean up HDD Nlink Service
4877 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4878 nl_srv_exit();
4879
4880 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004882
4883 //Close the scheduler before calling vos_close to make sure no thread is
4884 // scheduled after the each module close is called i.e after all the data
4885 // structures are freed.
4886 vosStatus = vos_sched_close( pVosContext );
4887 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4888 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4889 "%s: Failed to close VOSS Scheduler",__func__);
4890 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4891 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004892#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004893#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4894 /* Destroy the wake lock */
4895 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4896#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004897 /* Destroy the wake lock */
4898 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004899#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004900
4901 //Close VOSS
4902 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4903 vos_close(pVosContext);
4904
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 //Close Watchdog
4906 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4907 vos_watchdog_close(pVosContext);
4908
4909 /* Cancel the vote for XO Core ON.
4910 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4911 * exited at this point
4912 */
4913 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4914 " when WLAN is turned OFF\n");
4915 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4916 {
4917 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4918 " Not returning failure."
4919 " Power consumed will be high\n");
4920 }
4921
4922 hdd_close_all_adapters( pHddCtx );
4923
4924
4925 //Free up dynamically allocated members inside HDD Adapter
4926 kfree(pHddCtx->cfg_ini);
4927 pHddCtx->cfg_ini= NULL;
4928
4929 /* free the power on lock from platform driver */
4930 if (free_riva_power_on_lock("wlan"))
4931 {
4932 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4933 __func__);
4934 }
4935
Jeff Johnson88ba7742013-02-27 14:36:02 -08004936free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004937 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004938 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004939 if (hdd_is_ssr_required())
4940 {
4941 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004942 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 msleep(5000);
4944 }
4945 hdd_set_ssr_required (VOS_FALSE);
4946}
4947
4948
4949/**---------------------------------------------------------------------------
4950
4951 \brief hdd_update_config_from_nv() - Function to update the contents of
4952 the running configuration with parameters taken from NV storage
4953
4954 \param - pHddCtx - Pointer to the HDD global context
4955
4956 \return - VOS_STATUS_SUCCESS if successful
4957
4958 --------------------------------------------------------------------------*/
4959static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4960{
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 v_BOOL_t itemIsValid = VOS_FALSE;
4962 VOS_STATUS status;
4963 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4964 v_U8_t macLoop;
4965
4966 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4967 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4968 if(status != VOS_STATUS_SUCCESS)
4969 {
4970 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4971 return VOS_STATUS_E_FAILURE;
4972 }
4973
4974 if (itemIsValid == VOS_TRUE)
4975 {
4976 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4977 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4978 VOS_MAX_CONCURRENCY_PERSONA);
4979 if(status != VOS_STATUS_SUCCESS)
4980 {
4981 /* Get MAC from NV fail, not update CFG info
4982 * INI MAC value will be used for MAC setting */
4983 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4984 return VOS_STATUS_E_FAILURE;
4985 }
4986
4987 /* If first MAC is not valid, treat all others are not valid
4988 * Then all MACs will be got from ini file */
4989 if(vos_is_macaddr_zero(&macFromNV[0]))
4990 {
4991 /* MAC address in NV file is not configured yet */
4992 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4993 return VOS_STATUS_E_INVAL;
4994 }
4995
4996 /* Get MAC address from NV, update CFG info */
4997 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4998 {
4999 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5000 {
5001 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5002 /* This MAC is not valid, skip it
5003 * This MAC will be got from ini file */
5004 }
5005 else
5006 {
5007 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5008 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5009 VOS_MAC_ADDR_SIZE);
5010 }
5011 }
5012 }
5013 else
5014 {
5015 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5016 return VOS_STATUS_E_FAILURE;
5017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005018
Jeff Johnson295189b2012-06-20 16:38:30 -07005019
5020 return VOS_STATUS_SUCCESS;
5021}
5022
5023/**---------------------------------------------------------------------------
5024
5025 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5026
5027 \param - pAdapter - Pointer to the HDD
5028
5029 \return - None
5030
5031 --------------------------------------------------------------------------*/
5032VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5033{
5034 eHalStatus halStatus;
5035 v_U32_t listenInterval;
5036
Jeff Johnson295189b2012-06-20 16:38:30 -07005037
5038 // Send ready indication to the HDD. This will kick off the MAC
5039 // into a 'running' state and should kick off an initial scan.
5040 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5041 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5042 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305043 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005044 "code %08d [x%08x]",__func__, halStatus, halStatus );
5045 return VOS_STATUS_E_FAILURE;
5046 }
5047
5048 // Set default LI into HDD context,
5049 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5050 // And RIVA will crash
5051 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5052 pHddCtx->hdd_actual_LI_value = listenInterval;
5053
5054 return VOS_STATUS_SUCCESS;
5055}
5056
Jeff Johnson295189b2012-06-20 16:38:30 -07005057/* wake lock APIs for HDD */
5058void hdd_prevent_suspend(void)
5059{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005060#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005061 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005062#else
5063 wcnss_prevent_suspend();
5064#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005065}
5066
5067void hdd_allow_suspend(void)
5068{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005069#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005070 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005071#else
5072 wcnss_allow_suspend();
5073#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005074}
5075
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005076void hdd_allow_suspend_timeout(v_U32_t timeout)
5077{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005078#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005079 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005080#else
5081 /* Do nothing as there is no API in wcnss for timeout*/
5082#endif
5083}
5084
Jeff Johnson295189b2012-06-20 16:38:30 -07005085/**---------------------------------------------------------------------------
5086
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005087 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5088 information between Host and Riva
5089
5090 This function gets reported version of FW
5091 It also finds the version of Riva headers used to compile the host
5092 It compares the above two and prints a warning if they are different
5093 It gets the SW and HW version string
5094 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5095 indicating the features they support through a bitmap
5096
5097 \param - pHddCtx - Pointer to HDD context
5098
5099 \return - void
5100
5101 --------------------------------------------------------------------------*/
5102
5103void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5104{
5105
5106 tSirVersionType versionCompiled;
5107 tSirVersionType versionReported;
5108 tSirVersionString versionString;
5109 tANI_U8 fwFeatCapsMsgSupported = 0;
5110 VOS_STATUS vstatus;
5111
5112 /* retrieve and display WCNSS version information */
5113 do {
5114
5115 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5116 &versionCompiled);
5117 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5118 {
5119 hddLog(VOS_TRACE_LEVEL_FATAL,
5120 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005121 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005122 break;
5123 }
5124
5125 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5126 &versionReported);
5127 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5128 {
5129 hddLog(VOS_TRACE_LEVEL_FATAL,
5130 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005131 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005132 break;
5133 }
5134
5135 if ((versionCompiled.major != versionReported.major) ||
5136 (versionCompiled.minor != versionReported.minor) ||
5137 (versionCompiled.version != versionReported.version) ||
5138 (versionCompiled.revision != versionReported.revision))
5139 {
5140 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5141 "Host expected %u.%u.%u.%u\n",
5142 WLAN_MODULE_NAME,
5143 (int)versionReported.major,
5144 (int)versionReported.minor,
5145 (int)versionReported.version,
5146 (int)versionReported.revision,
5147 (int)versionCompiled.major,
5148 (int)versionCompiled.minor,
5149 (int)versionCompiled.version,
5150 (int)versionCompiled.revision);
5151 }
5152 else
5153 {
5154 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5155 WLAN_MODULE_NAME,
5156 (int)versionReported.major,
5157 (int)versionReported.minor,
5158 (int)versionReported.version,
5159 (int)versionReported.revision);
5160 }
5161
5162 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5163 versionString,
5164 sizeof(versionString));
5165 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5166 {
5167 hddLog(VOS_TRACE_LEVEL_FATAL,
5168 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005169 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005170 break;
5171 }
5172
5173 pr_info("%s: WCNSS software version %s\n",
5174 WLAN_MODULE_NAME, versionString);
5175
5176 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5177 versionString,
5178 sizeof(versionString));
5179 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5180 {
5181 hddLog(VOS_TRACE_LEVEL_FATAL,
5182 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005183 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005184 break;
5185 }
5186
5187 pr_info("%s: WCNSS hardware version %s\n",
5188 WLAN_MODULE_NAME, versionString);
5189
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005190 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5191 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005192 send the message only if it the riva is 1.1
5193 minor numbers for different riva branches:
5194 0 -> (1.0)Mainline Build
5195 1 -> (1.1)Mainline Build
5196 2->(1.04) Stability Build
5197 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005198 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005199 ((versionReported.minor>=1) && (versionReported.version>=1)))
5200 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5201 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005202
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005203 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005204 {
5205#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5206 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5207 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5208#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005209 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005210 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005211
5212 } while (0);
5213
5214}
5215
5216/**---------------------------------------------------------------------------
5217
Jeff Johnson295189b2012-06-20 16:38:30 -07005218 \brief hdd_wlan_startup() - HDD init function
5219
5220 This is the driver startup code executed once a WLAN device has been detected
5221
5222 \param - dev - Pointer to the underlying device
5223
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005224 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005225
5226 --------------------------------------------------------------------------*/
5227
5228int hdd_wlan_startup(struct device *dev )
5229{
5230 VOS_STATUS status;
5231 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005232 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005233 hdd_context_t *pHddCtx = NULL;
5234 v_CONTEXT_t pVosContext= NULL;
5235#ifdef WLAN_BTAMP_FEATURE
5236 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5237 WLANBAP_ConfigType btAmpConfig;
5238 hdd_config_t *pConfig;
5239#endif
5240 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005242
5243 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005244 /*
5245 * cfg80211: wiphy allocation
5246 */
5247 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5248
5249 if(wiphy == NULL)
5250 {
5251 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005252 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 }
5254
5255 pHddCtx = wiphy_priv(wiphy);
5256
Jeff Johnson295189b2012-06-20 16:38:30 -07005257 //Initialize the adapter context to zeros.
5258 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5259
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 hdd_prevent_suspend();
5262 pHddCtx->isLoadUnloadInProgress = TRUE;
5263
5264 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5265
5266 /*Get vos context here bcoz vos_open requires it*/
5267 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5268
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005269 if(pVosContext == NULL)
5270 {
5271 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5272 goto err_free_hdd_context;
5273 }
5274
Jeff Johnson295189b2012-06-20 16:38:30 -07005275 //Save the Global VOSS context in adapter context for future.
5276 pHddCtx->pvosContext = pVosContext;
5277
5278 //Save the adapter context in global context for future.
5279 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5280
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 pHddCtx->parent_dev = dev;
5282
5283 init_completion(&pHddCtx->full_pwr_comp_var);
5284 init_completion(&pHddCtx->standby_comp_var);
5285 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005286 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005287 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005288
5289 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5290
5291 // Load all config first as TL config is needed during vos_open
5292 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5293 if(pHddCtx->cfg_ini == NULL)
5294 {
5295 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5296 goto err_free_hdd_context;
5297 }
5298
5299 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5300
5301 // Read and parse the qcom_cfg.ini file
5302 status = hdd_parse_config_ini( pHddCtx );
5303 if ( VOS_STATUS_SUCCESS != status )
5304 {
5305 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5306 __func__, WLAN_INI_FILE);
5307 goto err_config;
5308 }
5309
Jeff Johnson295189b2012-06-20 16:38:30 -07005310 /*
5311 * cfg80211: Initialization and registration ...
5312 */
5313 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5314 {
5315 hddLog(VOS_TRACE_LEVEL_FATAL,
5316 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5317 goto err_wiphy_reg;
5318 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005319
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005320 // Update VOS trace levels based upon the cfg.ini
5321 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5322 pHddCtx->cfg_ini->vosTraceEnableBAP);
5323 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5324 pHddCtx->cfg_ini->vosTraceEnableTL);
5325 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5326 pHddCtx->cfg_ini->vosTraceEnableWDI);
5327 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5328 pHddCtx->cfg_ini->vosTraceEnableHDD);
5329 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5330 pHddCtx->cfg_ini->vosTraceEnableSME);
5331 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5332 pHddCtx->cfg_ini->vosTraceEnablePE);
5333 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5334 pHddCtx->cfg_ini->vosTraceEnableWDA);
5335 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5336 pHddCtx->cfg_ini->vosTraceEnableSYS);
5337 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5338 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005339 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5340 pHddCtx->cfg_ini->vosTraceEnableSAP);
5341 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5342 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005343
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 // Update WDI trace levels based upon the cfg.ini
5345 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5346 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5347 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5348 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5349 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5350 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5351 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5352 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005353
Jeff Johnson88ba7742013-02-27 14:36:02 -08005354 if (VOS_FTM_MODE == hdd_get_conparam())
5355 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005356 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5357 {
5358 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5359 goto err_free_hdd_context;
5360 }
5361 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5362 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005363 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005364
Jeff Johnson88ba7742013-02-27 14:36:02 -08005365 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005366 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5367 {
5368 status = vos_watchdog_open(pVosContext,
5369 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5370
5371 if(!VOS_IS_STATUS_SUCCESS( status ))
5372 {
5373 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005375 }
5376 }
5377
5378 pHddCtx->isLogpInProgress = FALSE;
5379 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5380
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5382 if(!VOS_IS_STATUS_SUCCESS(status))
5383 {
5384 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005385 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 }
5387
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 status = vos_open( &pVosContext, 0);
5389 if ( !VOS_IS_STATUS_SUCCESS( status ))
5390 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005391 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5392 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 }
5394
Jeff Johnson295189b2012-06-20 16:38:30 -07005395 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5396
5397 if ( NULL == pHddCtx->hHal )
5398 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005399 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 goto err_vosclose;
5401 }
5402
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005403 status = vos_preStart( pHddCtx->pvosContext );
5404 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5405 {
5406 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5407 goto err_vosclose;
5408 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005409
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005410 /* Note that the vos_preStart() sequence triggers the cfg download.
5411 The cfg download must occur before we update the SME config
5412 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 status = hdd_set_sme_config( pHddCtx );
5414
5415 if ( VOS_STATUS_SUCCESS != status )
5416 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005417 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5418 goto err_vosclose;
5419 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005420
5421 //Initialize the WMM module
5422 status = hdd_wmm_init(pHddCtx);
5423 if (!VOS_IS_STATUS_SUCCESS(status))
5424 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005425 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 goto err_vosclose;
5427 }
5428
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 /* In the integrated architecture we update the configuration from
5430 the INI file and from NV before vOSS has been started so that
5431 the final contents are available to send down to the cCPU */
5432
5433 // Apply the cfg.ini to cfg.dat
5434 if (FALSE == hdd_update_config_dat(pHddCtx))
5435 {
5436 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5437 goto err_vosclose;
5438 }
5439
5440 // Apply the NV to cfg.dat
5441 /* Prima Update MAC address only at here */
5442 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5443 {
5444#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5445 /* There was not a valid set of MAC Addresses in NV. See if the
5446 default addresses were modified by the cfg.ini settings. If so,
5447 we'll use them, but if not, we'll autogenerate a set of MAC
5448 addresses based upon the device serial number */
5449
5450 static const v_MACADDR_t default_address =
5451 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5452 unsigned int serialno;
5453 int i;
5454
5455 serialno = wcnss_get_serial_number();
5456 if ((0 != serialno) &&
5457 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5458 sizeof(default_address))))
5459 {
5460 /* cfg.ini has the default address, invoke autogen logic */
5461
5462 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5463 bytes of the serial number that can be used to generate
5464 the other 3 bytes of the MAC address. Mask off all but
5465 the lower 3 bytes (this will also make sure we don't
5466 overflow in the next step) */
5467 serialno &= 0x00FFFFFF;
5468
5469 /* we need a unique address for each session */
5470 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5471
5472 /* autogen all addresses */
5473 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5474 {
5475 /* start with the entire default address */
5476 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5477 /* then replace the lower 3 bytes */
5478 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5479 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5480 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5481
5482 serialno++;
5483 }
5484
5485 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5486 MAC_ADDRESS_STR,
5487 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5488 }
5489 else
5490#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5491 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005492 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005493 "%s: Invalid MAC address in NV, using MAC from ini file "
5494 MAC_ADDRESS_STR, __func__,
5495 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5496 }
5497 }
5498 {
5499 eHalStatus halStatus;
5500 // Set the MAC Address
5501 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5502 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5503 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5504 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5505
5506 if (!HAL_STATUS_SUCCESS( halStatus ))
5507 {
5508 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5509 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005510 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 }
5512 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005513
5514 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5515 Note: Firmware image will be read and downloaded inside vos_start API */
5516 status = vos_start( pHddCtx->pvosContext );
5517 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5518 {
5519 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5520 goto err_vosclose;
5521 }
5522
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005523 /* Exchange capability info between Host and FW and also get versioning info from FW */
5524 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005525
5526 status = hdd_post_voss_start_config( pHddCtx );
5527 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5528 {
5529 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5530 __func__);
5531 goto err_vosstop;
5532 }
5533
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5535 {
5536 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5537 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5538 }
5539 else
5540 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005541 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5542 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5543 if (pAdapter != NULL)
5544 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305545 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005546 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305547 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5548 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5549 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005550
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305551 /* Generate the P2P Device Address. This consists of the device's
5552 * primary MAC address with the locally administered bit set.
5553 */
5554 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005555 }
5556 else
5557 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305558 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5559 if (p2p_dev_addr != NULL)
5560 {
5561 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5562 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5563 }
5564 else
5565 {
5566 hddLog(VOS_TRACE_LEVEL_FATAL,
5567 "%s: Failed to allocate mac_address for p2p_device",
5568 __func__);
5569 goto err_close_adapter;
5570 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005572
5573 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5574 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5575 if ( NULL == pP2pAdapter )
5576 {
5577 hddLog(VOS_TRACE_LEVEL_FATAL,
5578 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005579 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005580 goto err_close_adapter;
5581 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005582 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005583 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005584
5585 if( pAdapter == NULL )
5586 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005587 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5588 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591#ifdef WLAN_BTAMP_FEATURE
5592 vStatus = WLANBAP_Open(pVosContext);
5593 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5594 {
5595 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5596 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005597 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 }
5599
5600 vStatus = BSL_Init(pVosContext);
5601 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5602 {
5603 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5604 "%s: Failed to Init BSL",__func__);
5605 goto err_bap_close;
5606 }
5607 vStatus = WLANBAP_Start(pVosContext);
5608 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5609 {
5610 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5611 "%s: Failed to start TL",__func__);
5612 goto err_bap_close;
5613 }
5614
5615 pConfig = pHddCtx->cfg_ini;
5616 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5617 status = WLANBAP_SetConfig(&btAmpConfig);
5618
5619#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005620
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005621#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5622 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5623 {
5624 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5625 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5626 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5627 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5628 }
5629#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005630#ifdef FEATURE_WLAN_SCAN_PNO
5631 /*SME must send channel update configuration to RIVA*/
5632 sme_UpdateChannelConfig(pHddCtx->hHal);
5633#endif
5634
Jeff Johnson295189b2012-06-20 16:38:30 -07005635 /* Register with platform driver as client for Suspend/Resume */
5636 status = hddRegisterPmOps(pHddCtx);
5637 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5638 {
5639 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5640#ifdef WLAN_BTAMP_FEATURE
5641 goto err_bap_stop;
5642#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005643 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005644#endif //WLAN_BTAMP_FEATURE
5645 }
5646
5647 /* Register TM level change handler function to the platform */
5648 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5649 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5650 {
5651 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5652 goto err_unregister_pmops;
5653 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005654
5655 /* register for riva power on lock to platform driver */
5656 if (req_riva_power_on_lock("wlan"))
5657 {
5658 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5659 __func__);
5660 goto err_unregister_pmops;
5661 }
5662
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 // register net device notifier for device change notification
5664 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5665
5666 if(ret < 0)
5667 {
5668 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5669 goto err_free_power_on_lock;
5670 }
5671
5672 //Initialize the nlink service
5673 if(nl_srv_init() != 0)
5674 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305675 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005676 goto err_reg_netdev;
5677 }
5678
5679 //Initialize the BTC service
5680 if(btc_activate_service(pHddCtx) != 0)
5681 {
5682 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5683 goto err_nl_srv;
5684 }
5685
5686#ifdef PTT_SOCK_SVC_ENABLE
5687 //Initialize the PTT service
5688 if(ptt_sock_activate_svc(pHddCtx) != 0)
5689 {
5690 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5691 goto err_nl_srv;
5692 }
5693#endif
5694
Jeff Johnson295189b2012-06-20 16:38:30 -07005695 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005696 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005697 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005698 /* Action frame registered in one adapter which will
5699 * applicable to all interfaces
5700 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005701 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005702 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005703
5704 mutex_init(&pHddCtx->sap_lock);
5705
5706 pHddCtx->isLoadUnloadInProgress = FALSE;
5707
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005708#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005709#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5710 /* Initialize the wake lcok */
5711 wake_lock_init(&pHddCtx->rx_wake_lock,
5712 WAKE_LOCK_SUSPEND,
5713 "qcom_rx_wakelock");
5714#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005715 /* Initialize the wake lcok */
5716 wake_lock_init(&pHddCtx->sap_wake_lock,
5717 WAKE_LOCK_SUSPEND,
5718 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005719#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005720
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005721 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5722 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005723
5724 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5725 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005726
5727 // Initialize the restart logic
5728 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305729
Jeff Johnson295189b2012-06-20 16:38:30 -07005730 goto success;
5731
5732err_nl_srv:
5733 nl_srv_exit();
5734
5735err_reg_netdev:
5736 unregister_netdevice_notifier(&hdd_netdev_notifier);
5737
5738err_free_power_on_lock:
5739 free_riva_power_on_lock("wlan");
5740
5741err_unregister_pmops:
5742 hddDevTmUnregisterNotifyCallback(pHddCtx);
5743 hddDeregisterPmOps(pHddCtx);
5744
5745#ifdef WLAN_BTAMP_FEATURE
5746err_bap_stop:
5747 WLANBAP_Stop(pVosContext);
5748#endif
5749
5750#ifdef WLAN_BTAMP_FEATURE
5751err_bap_close:
5752 WLANBAP_Close(pVosContext);
5753#endif
5754
Jeff Johnson295189b2012-06-20 16:38:30 -07005755err_close_adapter:
5756 hdd_close_all_adapters( pHddCtx );
5757
5758err_vosstop:
5759 vos_stop(pVosContext);
5760
5761err_vosclose:
5762 status = vos_sched_close( pVosContext );
5763 if (!VOS_IS_STATUS_SUCCESS(status)) {
5764 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5765 "%s: Failed to close VOSS Scheduler", __func__);
5766 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5767 }
5768 vos_close(pVosContext );
5769
Jeff Johnson295189b2012-06-20 16:38:30 -07005770err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005771 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005772
5773err_wdclose:
5774 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5775 vos_watchdog_close(pVosContext);
5776
Jeff Johnson295189b2012-06-20 16:38:30 -07005777err_wiphy_reg:
5778 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005779
5780err_config:
5781 kfree(pHddCtx->cfg_ini);
5782 pHddCtx->cfg_ini= NULL;
5783
5784err_free_hdd_context:
5785 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 wiphy_free(wiphy) ;
5787 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005788 VOS_BUG(1);
5789
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005790 if (hdd_is_ssr_required())
5791 {
5792 /* WDI timeout had happened during load, so SSR is needed here */
5793 subsystem_restart("wcnss");
5794 msleep(5000);
5795 }
5796 hdd_set_ssr_required (VOS_FALSE);
5797
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005798 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005799
5800success:
5801 EXIT();
5802 return 0;
5803}
5804
5805/**---------------------------------------------------------------------------
5806
Jeff Johnson32d95a32012-09-10 13:15:23 -07005807 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005808
Jeff Johnson32d95a32012-09-10 13:15:23 -07005809 This is the driver entry point - called in different timeline depending
5810 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005811
5812 \param - None
5813
5814 \return - 0 for success, non zero for failure
5815
5816 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005817static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005818{
5819 VOS_STATUS status;
5820 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 struct device *dev = NULL;
5822 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005823#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5824 int max_retries = 0;
5825#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005826
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305827#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5828 vos_wconn_trace_init();
5829#endif
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 ENTER();
5832
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005833#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005835#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005836
5837 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5838 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5839
5840 //Power Up Libra WLAN card first if not already powered up
5841 status = vos_chipPowerUp(NULL,NULL,NULL);
5842 if (!VOS_IS_STATUS_SUCCESS(status))
5843 {
5844 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5845 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005846 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 }
5848
Jeff Johnson295189b2012-06-20 16:38:30 -07005849#ifdef ANI_BUS_TYPE_PCI
5850
5851 dev = wcnss_wlan_get_device();
5852
5853#endif // ANI_BUS_TYPE_PCI
5854
5855#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005856
5857#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5858 /* wait until WCNSS driver downloads NV */
5859 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5860 msleep(1000);
5861 }
5862 if (max_retries >= 5) {
5863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5864 return -ENODEV;
5865 }
5866#endif
5867
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 dev = wcnss_wlan_get_device();
5869#endif // ANI_BUS_TYPE_PLATFORM
5870
5871
5872 do {
5873 if (NULL == dev) {
5874 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5875 ret_status = -1;
5876 break;
5877 }
5878
5879#ifdef MEMORY_DEBUG
5880 vos_mem_init();
5881#endif
5882
5883#ifdef TIMER_MANAGER
5884 vos_timer_manager_init();
5885#endif
5886
5887 /* Preopen VOSS so that it is ready to start at least SAL */
5888 status = vos_preOpen(&pVosContext);
5889
5890 if (!VOS_IS_STATUS_SUCCESS(status))
5891 {
5892 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5893 ret_status = -1;
5894 break;
5895 }
5896
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005897#ifndef MODULE
5898 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5899 */
5900 hdd_set_conparam((v_UINT_t)con_mode);
5901#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005902
5903 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005904 if (hdd_wlan_startup(dev))
5905 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005907 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 vos_preClose( &pVosContext );
5909 ret_status = -1;
5910 break;
5911 }
5912
5913 /* Cancel the vote for XO Core ON
5914 * This is done here for safety purposes in case we re-initialize without turning
5915 * it OFF in any error scenario.
5916 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005917 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005919 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5921 {
5922 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5923 " Power consumed will be high\n");
5924 }
5925 } while (0);
5926
5927 if (0 != ret_status)
5928 {
5929 //Assert Deep sleep signal now to put Libra HW in lowest power state
5930 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5931 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5932
5933 //Vote off any PMIC voltage supplies
5934 vos_chipPowerDown(NULL, NULL, NULL);
5935#ifdef TIMER_MANAGER
5936 vos_timer_exit();
5937#endif
5938#ifdef MEMORY_DEBUG
5939 vos_mem_exit();
5940#endif
5941
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005942#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005944#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005945 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5946 }
5947 else
5948 {
5949 //Send WLAN UP indication to Nlink Service
5950 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5951
5952 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5953
5954 }
5955
5956 EXIT();
5957
5958 return ret_status;
5959}
5960
Jeff Johnson32d95a32012-09-10 13:15:23 -07005961/**---------------------------------------------------------------------------
5962
5963 \brief hdd_module_init() - Init Function
5964
5965 This is the driver entry point (invoked when module is loaded using insmod)
5966
5967 \param - None
5968
5969 \return - 0 for success, non zero for failure
5970
5971 --------------------------------------------------------------------------*/
5972#ifdef MODULE
5973static int __init hdd_module_init ( void)
5974{
5975 return hdd_driver_init();
5976}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005977#else /* #ifdef MODULE */
5978static int __init hdd_module_init ( void)
5979{
5980 /* Driver initialization is delayed to fwpath_changed_handler */
5981 return 0;
5982}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005983#endif /* #ifdef MODULE */
5984
Jeff Johnson295189b2012-06-20 16:38:30 -07005985
5986/**---------------------------------------------------------------------------
5987
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005988 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005989
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005990 This is the driver exit point (invoked when module is unloaded using rmmod
5991 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005992
5993 \param - None
5994
5995 \return - None
5996
5997 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005998static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005999{
6000 hdd_context_t *pHddCtx = NULL;
6001 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006002
6003 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6004
6005 //Get the global vos context
6006 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6007
6008 if(!pVosContext)
6009 {
6010 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6011 goto done;
6012 }
6013
6014 //Get the HDD context.
6015 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6016
6017 if(!pHddCtx)
6018 {
6019 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6020 }
6021 else
6022 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006023 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6026 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 }
6028
6029 pHddCtx->isLoadUnloadInProgress = TRUE;
6030 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6031
6032 //Do all the cleanup before deregistering the driver
6033 hdd_wlan_exit(pHddCtx);
6034 }
6035
Jeff Johnson295189b2012-06-20 16:38:30 -07006036 vos_preClose( &pVosContext );
6037
6038#ifdef TIMER_MANAGER
6039 vos_timer_exit();
6040#endif
6041#ifdef MEMORY_DEBUG
6042 vos_mem_exit();
6043#endif
6044
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306045#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6046 vos_wconn_trace_exit();
6047#endif
6048
Jeff Johnson295189b2012-06-20 16:38:30 -07006049done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006050#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006052#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6054}
6055
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006056/**---------------------------------------------------------------------------
6057
6058 \brief hdd_module_exit() - Exit function
6059
6060 This is the driver exit point (invoked when module is unloaded using rmmod)
6061
6062 \param - None
6063
6064 \return - None
6065
6066 --------------------------------------------------------------------------*/
6067static void __exit hdd_module_exit(void)
6068{
6069 hdd_driver_exit();
6070}
6071
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006072#ifdef MODULE
6073static int fwpath_changed_handler(const char *kmessage,
6074 struct kernel_param *kp)
6075{
Jeff Johnson76052702013-04-16 13:55:05 -07006076 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006077}
6078
6079static int con_mode_handler(const char *kmessage,
6080 struct kernel_param *kp)
6081{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006082 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006083}
6084#else /* #ifdef MODULE */
6085/**---------------------------------------------------------------------------
6086
Jeff Johnson76052702013-04-16 13:55:05 -07006087 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006088
Jeff Johnson76052702013-04-16 13:55:05 -07006089 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006090 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006091 - invoked when module parameter fwpath is modified from userspace to signal
6092 initializing the WLAN driver or when con_mode is modified from userspace
6093 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006094
6095 \return - 0 for success, non zero for failure
6096
6097 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006098static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006099{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006100 int ret_status;
6101
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006102 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006103 ret_status = hdd_driver_init();
6104 wlan_hdd_inited = ret_status ? 0 : 1;
6105 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006106 }
6107
6108 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006109
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006110 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006111
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006112 ret_status = hdd_driver_init();
6113 wlan_hdd_inited = ret_status ? 0 : 1;
6114 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006115}
6116
Jeff Johnson295189b2012-06-20 16:38:30 -07006117/**---------------------------------------------------------------------------
6118
Jeff Johnson76052702013-04-16 13:55:05 -07006119 \brief fwpath_changed_handler() - Handler Function
6120
6121 Handle changes to the fwpath parameter
6122
6123 \return - 0 for success, non zero for failure
6124
6125 --------------------------------------------------------------------------*/
6126static int fwpath_changed_handler(const char *kmessage,
6127 struct kernel_param *kp)
6128{
6129 int ret;
6130
6131 ret = param_set_copystring(kmessage, kp);
6132 if (0 == ret)
6133 ret = kickstart_driver();
6134 return ret;
6135}
6136
6137/**---------------------------------------------------------------------------
6138
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006139 \brief con_mode_handler() -
6140
6141 Handler function for module param con_mode when it is changed by userspace
6142 Dynamically linked - do nothing
6143 Statically linked - exit and init driver, as in rmmod and insmod
6144
Jeff Johnson76052702013-04-16 13:55:05 -07006145 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006146
Jeff Johnson76052702013-04-16 13:55:05 -07006147 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006148
6149 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006150static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006151{
Jeff Johnson76052702013-04-16 13:55:05 -07006152 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006153
Jeff Johnson76052702013-04-16 13:55:05 -07006154 ret = param_set_int(kmessage, kp);
6155 if (0 == ret)
6156 ret = kickstart_driver();
6157 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006158}
6159#endif /* #ifdef MODULE */
6160
6161/**---------------------------------------------------------------------------
6162
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 \brief hdd_get_conparam() -
6164
6165 This is the driver exit point (invoked when module is unloaded using rmmod)
6166
6167 \param - None
6168
6169 \return - tVOS_CON_MODE
6170
6171 --------------------------------------------------------------------------*/
6172tVOS_CON_MODE hdd_get_conparam ( void )
6173{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006174#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006176#else
6177 return (tVOS_CON_MODE)curr_con_mode;
6178#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006179}
6180void hdd_set_conparam ( v_UINT_t newParam )
6181{
6182 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006183#ifndef MODULE
6184 curr_con_mode = con_mode;
6185#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006186}
6187/**---------------------------------------------------------------------------
6188
6189 \brief hdd_softap_sta_deauth() - function
6190
6191 This to take counter measure to handle deauth req from HDD
6192
6193 \param - pAdapter - Pointer to the HDD
6194
6195 \param - enable - boolean value
6196
6197 \return - None
6198
6199 --------------------------------------------------------------------------*/
6200
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006201VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006202{
Jeff Johnson295189b2012-06-20 16:38:30 -07006203 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006204 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006205
6206 ENTER();
6207
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306208 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006209
6210 //Ignore request to deauth bcmc station
6211 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006212 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006213
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006214 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006215
6216 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006217 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006218}
6219
6220/**---------------------------------------------------------------------------
6221
6222 \brief hdd_softap_sta_disassoc() - function
6223
6224 This to take counter measure to handle deauth req from HDD
6225
6226 \param - pAdapter - Pointer to the HDD
6227
6228 \param - enable - boolean value
6229
6230 \return - None
6231
6232 --------------------------------------------------------------------------*/
6233
6234void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6235{
6236 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6237
6238 ENTER();
6239
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306240 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006241
6242 //Ignore request to disassoc bcmc station
6243 if( pDestMacAddress[0] & 0x1 )
6244 return;
6245
6246 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6247}
6248
6249void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6250{
6251 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6252
6253 ENTER();
6254
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306255 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006256
6257 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6258}
6259
Jeff Johnson295189b2012-06-20 16:38:30 -07006260/**---------------------------------------------------------------------------
6261 *
6262 * \brief hdd_get__concurrency_mode() -
6263 *
6264 *
6265 * \param - None
6266 *
6267 * \return - CONCURRENCY MODE
6268 *
6269 * --------------------------------------------------------------------------*/
6270tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6271{
6272 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6273 hdd_context_t *pHddCtx;
6274
6275 if (NULL != pVosContext)
6276 {
6277 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6278 if (NULL != pHddCtx)
6279 {
6280 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6281 }
6282 }
6283
6284 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006285 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 return VOS_STA;
6287}
6288
6289/* Decide whether to allow/not the apps power collapse.
6290 * Allow apps power collapse if we are in connected state.
6291 * if not, allow only if we are in IMPS */
6292v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6293{
6294 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006295 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006296 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6298 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6299 hdd_adapter_t *pAdapter = NULL;
6300 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006301 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006302
Jeff Johnson295189b2012-06-20 16:38:30 -07006303 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6304 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006305
Yathish9f22e662012-12-10 14:21:35 -08006306 concurrent_state = hdd_get_concurrency_mode();
6307
6308#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6309 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6310 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6311 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6312 return TRUE;
6313#endif
6314
Jeff Johnson295189b2012-06-20 16:38:30 -07006315 /*loop through all adapters. TBD fix for Concurrency */
6316 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6317 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6318 {
6319 pAdapter = pAdapterNode->pAdapter;
6320 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6321 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6322 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006323 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006324 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006325 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006326 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6327 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006329 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006330 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6331 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 return FALSE;
6333 }
6334 }
6335 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6336 pAdapterNode = pNext;
6337 }
6338 return TRUE;
6339}
6340
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006341/* Decides whether to send suspend notification to Riva
6342 * if any adapter is in BMPS; then it is required */
6343v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6344{
6345 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6346 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6347
6348 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6349 {
6350 return TRUE;
6351 }
6352 return FALSE;
6353}
6354
Jeff Johnson295189b2012-06-20 16:38:30 -07006355void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6356{
6357 switch(mode)
6358 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006359 case VOS_STA_MODE:
6360 case VOS_P2P_CLIENT_MODE:
6361 case VOS_P2P_GO_MODE:
6362 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006363 pHddCtx->concurrency_mode |= (1 << mode);
6364 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006365 break;
6366 default:
6367 break;
6368
6369 }
6370 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6371 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6372}
6373
6374
6375void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6376{
6377 switch(mode)
6378 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006379 case VOS_STA_MODE:
6380 case VOS_P2P_CLIENT_MODE:
6381 case VOS_P2P_GO_MODE:
6382 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006383 pHddCtx->no_of_sessions[mode]--;
6384 if (!(pHddCtx->no_of_sessions[mode]))
6385 pHddCtx->concurrency_mode &= (~(1 << mode));
6386 break;
6387 default:
6388 break;
6389 }
6390 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6391 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6392}
6393
Jeff Johnsone7245742012-09-05 17:12:55 -07006394/**---------------------------------------------------------------------------
6395 *
6396 * \brief wlan_hdd_restart_init
6397 *
6398 * This function initalizes restart timer/flag. An internal function.
6399 *
6400 * \param - pHddCtx
6401 *
6402 * \return - None
6403 *
6404 * --------------------------------------------------------------------------*/
6405
6406static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6407{
6408 /* Initialize */
6409 pHddCtx->hdd_restart_retries = 0;
6410 atomic_set(&pHddCtx->isRestartInProgress, 0);
6411 vos_timer_init(&pHddCtx->hdd_restart_timer,
6412 VOS_TIMER_TYPE_SW,
6413 wlan_hdd_restart_timer_cb,
6414 pHddCtx);
6415}
6416/**---------------------------------------------------------------------------
6417 *
6418 * \brief wlan_hdd_restart_deinit
6419 *
6420 * This function cleans up the resources used. An internal function.
6421 *
6422 * \param - pHddCtx
6423 *
6424 * \return - None
6425 *
6426 * --------------------------------------------------------------------------*/
6427
6428static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6429{
6430
6431 VOS_STATUS vos_status;
6432 /* Block any further calls */
6433 atomic_set(&pHddCtx->isRestartInProgress, 1);
6434 /* Cleanup */
6435 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6436 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006437 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006438 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6439 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006440 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006441
6442}
6443
6444/**---------------------------------------------------------------------------
6445 *
6446 * \brief wlan_hdd_framework_restart
6447 *
6448 * This function uses a cfg80211 API to start a framework initiated WLAN
6449 * driver module unload/load.
6450 *
6451 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6452 *
6453 *
6454 * \param - pHddCtx
6455 *
6456 * \return - VOS_STATUS_SUCCESS: Success
6457 * VOS_STATUS_E_EMPTY: Adapter is Empty
6458 * VOS_STATUS_E_NOMEM: No memory
6459
6460 * --------------------------------------------------------------------------*/
6461
6462static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6463{
6464 VOS_STATUS status = VOS_STATUS_SUCCESS;
6465 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006466 int len = (sizeof (struct ieee80211_mgmt));
6467 struct ieee80211_mgmt *mgmt = NULL;
6468
6469 /* Prepare the DEAUTH managment frame with reason code */
6470 mgmt = kzalloc(len, GFP_KERNEL);
6471 if(mgmt == NULL)
6472 {
6473 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6474 "%s: memory allocation failed (%d bytes)", __func__, len);
6475 return VOS_STATUS_E_NOMEM;
6476 }
6477 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006478
6479 /* Iterate over all adapters/devices */
6480 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6481 do
6482 {
6483 if( (status == VOS_STATUS_SUCCESS) &&
6484 pAdapterNode &&
6485 pAdapterNode->pAdapter)
6486 {
6487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6488 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6489 pAdapterNode->pAdapter->dev->name,
6490 pAdapterNode->pAdapter->device_mode,
6491 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006492 /*
6493 * CFG80211 event to restart the driver
6494 *
6495 * 'cfg80211_send_unprot_deauth' sends a
6496 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6497 * of SME(Linux Kernel) state machine.
6498 *
6499 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6500 * the driver.
6501 *
6502 */
6503
6504 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006505 }
6506 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6507 pAdapterNode = pNext;
6508 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6509
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006510
6511 /* Free the allocated management frame */
6512 kfree(mgmt);
6513
Jeff Johnsone7245742012-09-05 17:12:55 -07006514 /* Retry until we unload or reach max count */
6515 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6516 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6517
6518 return status;
6519
6520}
6521/**---------------------------------------------------------------------------
6522 *
6523 * \brief wlan_hdd_restart_timer_cb
6524 *
6525 * Restart timer callback. An internal function.
6526 *
6527 * \param - User data:
6528 *
6529 * \return - None
6530 *
6531 * --------------------------------------------------------------------------*/
6532
6533void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6534{
6535 hdd_context_t *pHddCtx = usrDataForCallback;
6536 wlan_hdd_framework_restart(pHddCtx);
6537 return;
6538
6539}
6540
6541
6542/**---------------------------------------------------------------------------
6543 *
6544 * \brief wlan_hdd_restart_driver
6545 *
6546 * This function sends an event to supplicant to restart the WLAN driver.
6547 *
6548 * This function is called from vos_wlanRestart.
6549 *
6550 * \param - pHddCtx
6551 *
6552 * \return - VOS_STATUS_SUCCESS: Success
6553 * VOS_STATUS_E_EMPTY: Adapter is Empty
6554 * VOS_STATUS_E_ALREADY: Request already in progress
6555
6556 * --------------------------------------------------------------------------*/
6557VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6558{
6559 VOS_STATUS status = VOS_STATUS_SUCCESS;
6560
6561 /* A tight check to make sure reentrancy */
6562 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6563 {
6564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6565 "%s: WLAN restart is already in progress", __func__);
6566
6567 return VOS_STATUS_E_ALREADY;
6568 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006569 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006570#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006571 wcnss_reset_intr();
6572#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006573
Jeff Johnsone7245742012-09-05 17:12:55 -07006574 return status;
6575}
6576
6577
Jeff Johnson295189b2012-06-20 16:38:30 -07006578//Register the module init/exit functions
6579module_init(hdd_module_init);
6580module_exit(hdd_module_exit);
6581
6582MODULE_LICENSE("Dual BSD/GPL");
6583MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6584MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6585
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006586module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6587 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006588
Jeff Johnson76052702013-04-16 13:55:05 -07006589module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006590 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);