blob: 033bce8163f5cecaf711d564f3bc6a1eba821520 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700201static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
202 tANI_U8 *pTargetApBssid,
203 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700205static int hdd_netdev_notifier_call(struct notifier_block * nb,
206 unsigned long state,
207 void *ndev)
208{
209 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700212#ifdef WLAN_BTAMP_FEATURE
213 VOS_STATUS status;
214 hdd_context_t *pHddCtx;
215#endif
216
217 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700219 (strncmp(dev->name, "p2p", 3)))
220 return NOTIFY_DONE;
221
222 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 return NOTIFY_DONE;
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
Jeff Johnson27cee452013-03-27 11:10:24 -0700228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
236 if (NULL == pHddCtx)
237 {
238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
244 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245
246 switch (state) {
247 case NETDEV_REGISTER:
248 break;
249
250 case NETDEV_UNREGISTER:
251 break;
252
253 case NETDEV_UP:
254 break;
255
256 case NETDEV_DOWN:
257 break;
258
259 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 if(TRUE == pAdapter->isLinkUpSvcNeeded)
261 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 break;
263
264 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 {
267 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 hdd_abort_mac_scan(pAdapter->pHddCtx);
270 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800271 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
273 if(!result)
274 {
275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800276 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279 }
280 else
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
285#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 status = WLANBAP_StopAmp();
288 if(VOS_STATUS_SUCCESS != status )
289 {
290 pHddCtx->isAmpAllowed = VOS_TRUE;
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Failed to stop AMP", __func__);
293 }
294 else
295 {
296 //a state m/c implementation in PAL is TBD to avoid this delay
297 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700298 if ( pHddCtx->isAmpAllowed )
299 {
300 WLANBAP_DeregisterFromHCI();
301 pHddCtx->isAmpAllowed = VOS_FALSE;
302 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#endif //WLAN_BTAMP_FEATURE
305 break;
306
307 default:
308 break;
309 }
310
311 return NOTIFY_DONE;
312}
313
314struct notifier_block hdd_netdev_notifier = {
315 .notifier_call = hdd_netdev_notifier_call,
316};
317
318/*---------------------------------------------------------------------------
319 * Function definitions
320 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700321void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
322void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700325#ifndef MODULE
326/* current con_mode - used only for statically linked driver
327 * con_mode is changed by userspace to indicate a mode change which will
328 * result in calling the module exit and init functions. The module
329 * exit function will clean up based on the value of con_mode prior to it
330 * being changed by userspace. So curr_con_mode records the current con_mode
331 * for exit when con_mode becomes the next mode for init
332 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700333static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700334#endif
335
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800336/**---------------------------------------------------------------------------
337
338 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
339
340 Called immediately after the cfg.ini is read in order to configure
341 the desired trace levels.
342
343 \param - moduleId - module whose trace level is being configured
344 \param - bitmask - bitmask of log levels to be enabled
345
346 \return - void
347
348 --------------------------------------------------------------------------*/
349static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
350{
351 wpt_tracelevel level;
352
353 /* if the bitmask is the default value, then a bitmask was not
354 specified in cfg.ini, so leave the logging level alone (it
355 will remain at the "compiled in" default value) */
356 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
357 {
358 return;
359 }
360
361 /* a mask was specified. start by disabling all logging */
362 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
363
364 /* now cycle through the bitmask until all "set" bits are serviced */
365 level = VOS_TRACE_LEVEL_FATAL;
366 while (0 != bitmask)
367 {
368 if (bitmask & 1)
369 {
370 vos_trace_setValue(moduleId, level, 1);
371 }
372 level++;
373 bitmask >>= 1;
374 }
375}
376
377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378/**---------------------------------------------------------------------------
379
380 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels in the WDI.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 wpalTraceSetLevel(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
Jeff Johnson295189b2012-06-20 16:38:30 -0700418
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530419/*
420 * FUNCTION: wlan_hdd_validate_context
421 * This function is used to check the HDD context
422 */
423int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
424{
425 ENTER();
426
427 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: HDD context is Null", __func__);
431 return -ENODEV;
432 }
433
434 if (pHddCtx->isLogpInProgress)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: LOGP in Progress. Ignore!!!", __func__);
438 return -EAGAIN;
439 }
440
441 if (pHddCtx->isLoadUnloadInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447 return 0;
448}
449
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530450void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
451{
452 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
454 hdd_config_t *cfg_param;
455 eCsrPhyMode phyMode;
456
457 if (NULL == pHddCtx)
458 {
459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
460 "HDD Context is null !!");
461 return ;
462 }
463
464 cfg_param = pHddCtx->cfg_ini;
465
466 if (NULL == cfg_param)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
469 "cfg_params not available !!");
470 return ;
471 }
472
473 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
474
475 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
476 {
477 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
478 (eCSR_DOT11_MODE_11ac == phyMode) ||
479 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
482 "Setting phymode to 11n!!");
483 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
484 }
485 }
486 else
487 {
488 /*New country Supports 11ac as well resetting value back from .ini*/
489 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
490 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
491 return ;
492 }
493
494 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
495 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
496 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
497 {
498 VOS_STATUS vosStatus;
499
500 // need to issue a disconnect to CSR.
501 INIT_COMPLETION(pAdapter->disconnect_comp_var);
502 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
503 pAdapter->sessionId,
504 eCSR_DISCONNECT_REASON_UNSPECIFIED );
505
506 if (VOS_STATUS_SUCCESS == vosStatus)
507 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
509
510 }
511}
512
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700513void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
514{
515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
516 hdd_config_t *cfg_param;
517
518 if (NULL == pHddCtx)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "HDD Context is null !!");
522 return ;
523 }
524
525 cfg_param = pHddCtx->cfg_ini;
526
527 if (NULL == cfg_param)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
530 "cfg_params not available !!");
531 return ;
532 }
533
534 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
535 {
536 /*New country doesn't support DFS */
537 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
538 }
539 else
540 {
541 /*New country Supports DFS as well resetting value back from .ini*/
542 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
543 }
544
545}
546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
548{
549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
550 hdd_priv_data_t priv_data;
551 tANI_U8 *command = NULL;
552 int ret = 0;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 ret = -ENODEV;
559 goto exit;
560 }
561
Jeff Johnsone7245742012-09-05 17:12:55 -0700562 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 {
564 ret = -EINVAL;
565 goto exit;
566 }
567
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700568 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
569 {
570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s:LOGP in Progress. Ignore!!!", __func__);
572 ret = -EBUSY;
573 goto exit;
574 }
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
577 {
578 ret = -EFAULT;
579 goto exit;
580 }
581
582 command = kmalloc(priv_data.total_len, GFP_KERNEL);
583 if (!command)
584 {
585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 ret = -ENOMEM;
588 goto exit;
589 }
590
591 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
592 {
593 ret = -EFAULT;
594 goto exit;
595 }
596
597 if ((SIOCDEVPRIVATE + 1) == cmd)
598 {
599 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
600
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700602 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700603
604 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
605 {
606 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
607 sizeof(tSirMacAddr)))
608 {
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 ret = -EFAULT;
612 }
613 }
Amar Singhal0974e402013-02-12 14:27:46 -0800614 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 {
Amar Singhal0974e402013-02-12 14:27:46 -0800616 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800620
621 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800624 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626 ret = hdd_setBand_helper(dev, ptr);
627 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700628 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
629 {
630 char *country_code;
631
632 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633
634 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530637 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700638 if( 0 != ret )
639 {
640 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
641 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
642
643 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700644 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
646 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
647 {
648 tANI_U8 *value = command;
649 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
650 tANI_U8 revision = 0;
651 eHalStatus status = eHAL_STATUS_SUCCESS;
652 v_REGDOMAIN_t regId;
653
654 status = hdd_parse_countryrev(value, countryCode, &revision);
655 if (eHAL_STATUS_SUCCESS != status)
656 {
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: Failed to parse country revision information", __func__);
659 ret = -EINVAL;
660 goto exit;
661 }
662
663 /* Validate country code */
664 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
665 if (eHAL_STATUS_SUCCESS != status)
666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
668 "%s: Invalid country code %s", __func__, countryCode);
669 ret = -EINVAL;
670 goto exit;
671 }
672
673 /* Validate revision */
674 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: Invalid revision %d", __func__, revision);
678 ret = -EINVAL;
679 goto exit;
680 }
681
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700682 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530683 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800684 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530685 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 if (0 != ret)
687 {
688 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
689 "%s: SME Change Country code fail ret=%d", __func__, ret);
690 ret = -EINVAL;
691 goto exit;
692 }
693
694 if (0 == strncmp(countryCode, "KR", 2))
695 {
696 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
697 revision);
698 if (eHAL_STATUS_SUCCESS != status)
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: Failed to build valid channel list", __func__);
702 ret = -EINVAL;
703 goto exit;
704 }
705 }
706 }
707#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700708 /*
709 command should be a string having format
710 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
711 */
Amar Singhal0974e402013-02-12 14:27:46 -0800712 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700713 {
Amar Singhal0974e402013-02-12 14:27:46 -0800714 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700717 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700718
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800719 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700720 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800721 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
722 {
723 int suspend = 0;
724 tANI_U8 *ptr = (tANI_U8*)command + 15;
725
726 suspend = *ptr - '0';
727 hdd_set_wlan_suspend_mode(suspend);
728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800729#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
730 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 *value = command;
733 int rssi = 0;
734 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
735 eHalStatus status = eHAL_STATUS_SUCCESS;
736
737 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
738 value = value + 15;
739
740 sscanf(value, "%d", &rssi);
741 lookUpThreshold = abs(rssi);
742 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
743 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
744 {
745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
746 "Neighbor lookup threshold value %d is out of range"
747 " (Min: %d Max: %d)", lookUpThreshold,
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
755 "%s: Received Command to Set Roam trigger"
756 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
757
758 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
759 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
760 if (eHAL_STATUS_SUCCESS != status)
761 {
762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
763 "%s: Failed to set roam trigger, try again", __func__);
764 ret = -EPERM;
765 goto exit;
766 }
767
768 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
769 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
770 }
771 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
772 {
773 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
774 int rssi = (-1) * lookUpThreshold;
775 char extra[32];
776 tANI_U8 len = 0;
777
778 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
779 if (copy_to_user(priv_data.buf, &extra, len + 1))
780 {
781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
782 "%s: failed to copy data to user buffer", __func__);
783 ret = -EFAULT;
784 goto exit;
785 }
786 }
787 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
788 {
789 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700790 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800791 /* input refresh period is in terms of seconds */
792 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
793 value = value + 18;
794 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700795 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800796 if (ret < 0)
797 {
798 /* If the input value is greater than max value of datatype, then also
799 kstrtou16 fails */
800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
801 "%s: kstrtou16 failed ",
802 "Input value may be out of range[%d - %d]",
803 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700804 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
805 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800806 ret = -EINVAL;
807 goto exit;
808 }
809
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700810 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
811 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
812 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800813 {
814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 "Neighbor empty scan results refresh period value %d is out of range"
816 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700817 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
818 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800819 ret = -EINVAL;
820 goto exit;
821 }
822
823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
824 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700825 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800826
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700827 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
828 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800829 }
830 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
831 {
832 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
833 char extra[32];
834 tANI_U8 len = 0;
835
836 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
837 /* Returned value is in units of seconds */
838 if (copy_to_user(priv_data.buf, &extra, len + 1))
839 {
840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
841 "%s: failed to copy data to user buffer", __func__);
842 ret = -EFAULT;
843 goto exit;
844 }
845 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
847 {
848 tANI_U8 *value = command;
849 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
850 /* input refresh period is in terms of seconds */
851 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
852 value = value + 25;
853 /* Convert the value from ascii to integer */
854 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
855 if (ret < 0)
856 {
857 /* If the input value is greater than max value of datatype, then also
858 kstrtou16 fails */
859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
860 "%s: kstrtou16 failed ",
861 "Input value may be out of range[%d - %d]",
862 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700863 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
864 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 ret = -EINVAL;
866 goto exit;
867 }
868
869 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700870 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
871 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700872 {
873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
874 "Neighbor scan results refresh period value %d is out of range"
875 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
876 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
877 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
878 ret = -EINVAL;
879 goto exit;
880 }
881
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
883 "%s: Received Command to Set roam scan refresh period"
884 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
885
886 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
887 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
888 }
889 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
890 {
891 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
892 char extra[32];
893 tANI_U8 len = 0;
894
895 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
896 /* Returned value is in units of seconds */
897 if (copy_to_user(priv_data.buf, &extra, len + 1))
898 {
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
900 "%s: failed to copy data to user buffer", __func__);
901 ret = -EFAULT;
902 goto exit;
903 }
904 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700905#ifdef FEATURE_WLAN_LFR
906 /* SETROAMMODE */
907 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
908 {
909 tANI_U8 *value = command;
910 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
911
912 /* Move pointer to ahead of SETROAMMODE<delimiter> */
913 value = value + SIZE_OF_SETROAMMODE + 1;
914
915 /* Convert the value from ascii to integer */
916 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
917 if (ret < 0)
918 {
919 /* If the input value is greater than max value of datatype, then also
920 kstrtou8 fails */
921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
922 "%s: kstrtou8 failed range [%d - %d]", __func__,
923 CFG_LFR_FEATURE_ENABLED_MIN,
924 CFG_LFR_FEATURE_ENABLED_MAX);
925 ret = -EINVAL;
926 goto exit;
927 }
928 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
929 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
930 {
931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
932 "Roam Mode value %d is out of range"
933 " (Min: %d Max: %d)", roamMode,
934 CFG_LFR_FEATURE_ENABLED_MIN,
935 CFG_LFR_FEATURE_ENABLED_MAX);
936 ret = -EINVAL;
937 goto exit;
938 }
939
940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
941 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
942 /*
943 * Note that
944 * SETROAMMODE 0 is to enable LFR while
945 * SETROAMMODE 1 is to disable LFR, but
946 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
947 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
948 */
949 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
950 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
951 else
952 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
953
954 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
955 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
956 }
957 /* GETROAMMODE */
958 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
959 {
960 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
961 char extra[32];
962 tANI_U8 len = 0;
963
964 /*
965 * roamMode value shall be inverted because the sementics is different.
966 */
967 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
968 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
969 else
970 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
971
972 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
973 if (copy_to_user(priv_data.buf, &extra, len + 1))
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: failed to copy data to user buffer", __func__);
977 ret = -EFAULT;
978 goto exit;
979 }
980 }
981#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800982#endif
983#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
984 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 *value = command;
987 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
988
989 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
990 value = value + 13;
991 /* Convert the value from ascii to integer */
992 ret = kstrtou8(value, 10, &roamRssiDiff);
993 if (ret < 0)
994 {
995 /* If the input value is greater than max value of datatype, then also
996 kstrtou8 fails */
997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
998 "%s: kstrtou8 failed range [%d - %d]", __func__,
999 CFG_ROAM_RSSI_DIFF_MIN,
1000 CFG_ROAM_RSSI_DIFF_MAX);
1001 ret = -EINVAL;
1002 goto exit;
1003 }
1004
1005 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1006 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1007 {
1008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1009 "Roam rssi diff value %d is out of range"
1010 " (Min: %d Max: %d)", roamRssiDiff,
1011 CFG_ROAM_RSSI_DIFF_MIN,
1012 CFG_ROAM_RSSI_DIFF_MAX);
1013 ret = -EINVAL;
1014 goto exit;
1015 }
1016
1017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1018 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1019
1020 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1021 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1022 }
1023 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1024 {
1025 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1026 char extra[32];
1027 tANI_U8 len = 0;
1028
1029 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1030 if (copy_to_user(priv_data.buf, &extra, len + 1))
1031 {
1032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: failed to copy data to user buffer", __func__);
1034 ret = -EFAULT;
1035 goto exit;
1036 }
1037 }
1038#endif
1039#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1040 else if (strncmp(command, "GETBAND", 7) == 0)
1041 {
1042 int band = -1;
1043 char extra[32];
1044 tANI_U8 len = 0;
1045 hdd_getBand_helper(pHddCtx, &band);
1046
1047 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1048 if (copy_to_user(priv_data.buf, &extra, len + 1))
1049 {
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: failed to copy data to user buffer", __func__);
1052 ret = -EFAULT;
1053 goto exit;
1054 }
1055 }
1056 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1057 {
1058 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1059 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1060 tANI_U8 revision = 0;
1061 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1062 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1063 char extra[32] = {0};
1064 tANI_U8 len = 0;
1065
1066 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1067 {
1068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1069 "%s: failed to get country code", __func__);
1070 ret = -EFAULT;
1071 goto exit;
1072 }
1073 pBuf[uBufLen] = '\0';
1074 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1075
1076 if (0 == strncmp(pBuf, "KR", 2))
1077 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1078 else
1079 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1080
1081 if (copy_to_user(priv_data.buf, &extra, len + 1))
1082 {
1083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: failed to copy data to user buffer", __func__);
1085 ret = -EFAULT;
1086 goto exit;
1087 }
1088 }
1089 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1090 {
1091 tANI_U8 *value = command;
1092 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1093 tANI_U8 numChannels = 0;
1094 eHalStatus status = eHAL_STATUS_SUCCESS;
1095
1096 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1097 if (eHAL_STATUS_SUCCESS != status)
1098 {
1099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Failed to parse channel list information", __func__);
1101 ret = -EINVAL;
1102 goto exit;
1103 }
1104
1105 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1106 {
1107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1108 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1109 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1110 ret = -EINVAL;
1111 goto exit;
1112 }
1113 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1114 numChannels);
1115 if (eHAL_STATUS_SUCCESS != status)
1116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1118 "%s: Failed to update channel list information", __func__);
1119 ret = -EINVAL;
1120 goto exit;
1121 }
1122 }
1123 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1124 {
1125 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1126 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001127 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001128 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001129 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001130
1131 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1132 ChannelList, &numChannels ))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1135 "%s: failed to get roam scan channel list", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 /* output channel list is of the format
1140 [Number of roam scan channels][Channel1][Channel2]... */
1141 /* copy the number of channels in the 0th index */
1142 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1143 for (j = 0; (j < numChannels); j++)
1144 {
1145 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1146 }
1147
1148 if (copy_to_user(priv_data.buf, &extra, len + 1))
1149 {
1150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1151 "%s: failed to copy data to user buffer", __func__);
1152 ret = -EFAULT;
1153 goto exit;
1154 }
1155 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001156 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1157 {
1158 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1159 char extra[32];
1160 tANI_U8 len = 0;
1161
1162 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1163 if (copy_to_user(priv_data.buf, &extra, len + 1))
1164 {
1165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1166 "%s: failed to copy data to user buffer", __func__);
1167 ret = -EFAULT;
1168 goto exit;
1169 }
1170 }
1171 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1172 {
1173 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1174 char extra[32];
1175 tANI_U8 len = 0;
1176
1177 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1178 if (copy_to_user(priv_data.buf, &extra, len + 1))
1179 {
1180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1181 "%s: failed to copy data to user buffer", __func__);
1182 ret = -EFAULT;
1183 goto exit;
1184 }
1185 }
1186 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1187 {
1188 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1189 char extra[32];
1190 tANI_U8 len = 0;
1191
1192 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1193 if (copy_to_user(priv_data.buf, &extra, len + 1))
1194 {
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: failed to copy data to user buffer", __func__);
1197 ret = -EFAULT;
1198 goto exit;
1199 }
1200 }
1201 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1202 {
1203 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1204 char extra[32];
1205 tANI_U8 len = 0;
1206
1207 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1208 if (copy_to_user(priv_data.buf, &extra, len + 1))
1209 {
1210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1211 "%s: failed to copy data to user buffer", __func__);
1212 ret = -EFAULT;
1213 goto exit;
1214 }
1215 }
1216 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1217 {
1218 tANI_U8 *value = command;
1219 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1220
1221 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1222 value = value + 26;
1223 /* Convert the value from ascii to integer */
1224 ret = kstrtou8(value, 10, &minTime);
1225 if (ret < 0)
1226 {
1227 /* If the input value is greater than max value of datatype, then also
1228 kstrtou8 fails */
1229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1230 "%s: kstrtou8 failed range [%d - %d]", __func__,
1231 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1232 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1233 ret = -EINVAL;
1234 goto exit;
1235 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001236 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1237 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1238 {
1239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1240 "scan min channel time value %d is out of range"
1241 " (Min: %d Max: %d)", minTime,
1242 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1243 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1244 ret = -EINVAL;
1245 goto exit;
1246 }
1247
1248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1249 "%s: Received Command to change channel min time = %d", __func__, minTime);
1250
1251 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1252 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1253 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001254 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1255 {
1256 tANI_U8 *value = command;
1257 tANI_U8 channel = 0;
1258 tANI_U8 dwellTime = 0;
1259 tANI_U8 bufLen = 0;
1260 tANI_U8 *buf = NULL;
1261 tSirMacAddr targetApBssid;
1262 eHalStatus status = eHAL_STATUS_SUCCESS;
1263 struct ieee80211_channel chan;
1264 tANI_U8 finalLen = 0;
1265 tANI_U8 *finalBuf = NULL;
1266 tANI_U8 temp = 0;
1267 u64 cookie;
1268 hdd_station_ctx_t *pHddStaCtx = NULL;
1269 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1270
1271 /* if not associated, no need to send action frame */
1272 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1273 {
1274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1275 ret = -EINVAL;
1276 goto exit;
1277 }
1278
1279 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1280 &dwellTime, &buf, &bufLen);
1281 if (eHAL_STATUS_SUCCESS != status)
1282 {
1283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1284 "%s: Failed to parse send action frame data", __func__);
1285 ret = -EINVAL;
1286 goto exit;
1287 }
1288
1289 /* if the target bssid is different from currently associated AP,
1290 then no need to send action frame */
1291 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1292 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1293 {
1294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1295 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001296 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 goto exit;
1298 }
1299
1300 /* if the channel number is different from operating channel then
1301 no need to send action frame */
1302 if (channel != pHddStaCtx->conn_info.operationChannel)
1303 {
1304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1305 "%s: channel(%d) is different from operating channel(%d)",
1306 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1307 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001308 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001309 goto exit;
1310 }
1311 chan.center_freq = sme_ChnToFreq(channel);
1312
1313 finalLen = bufLen + 24;
1314 finalBuf = vos_mem_malloc(finalLen);
1315 if (NULL == finalBuf)
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1318 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001319 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001320 goto exit;
1321 }
1322 vos_mem_zero(finalBuf, finalLen);
1323
1324 /* Fill subtype */
1325 temp = SIR_MAC_MGMT_ACTION << 4;
1326 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1327
1328 /* Fill type */
1329 temp = SIR_MAC_MGMT_FRAME;
1330 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1331
1332 /* Fill destination address (bssid of the AP) */
1333 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1334
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001335 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001336 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1337
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001338 /* Fill BSSID (AP mac address) */
1339 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340
1341 /* Fill received buffer from 24th address */
1342 vos_mem_copy(finalBuf + 24, buf, bufLen);
1343
Jeff Johnson11c33152013-04-16 17:52:40 -07001344 /* done with the parsed buffer */
1345 vos_mem_free(buf);
1346
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001347 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1348 1, dwellTime, finalBuf, finalLen, 1,
1349 1, &cookie );
1350 vos_mem_free(finalBuf);
1351 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001352 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1353 {
1354 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1355 char extra[32];
1356 tANI_U8 len = 0;
1357
1358 /* value is interms of msec */
1359 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1360 if (copy_to_user(priv_data.buf, &extra, len + 1))
1361 {
1362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1363 "%s: failed to copy data to user buffer", __func__);
1364 ret = -EFAULT;
1365 goto exit;
1366 }
1367 }
1368 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1369 {
1370 tANI_U8 *value = command;
1371 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1372
1373 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1374 value = value + 19;
1375 /* Convert the value from ascii to integer */
1376 ret = kstrtou8(value, 10, &maxTime);
1377 if (ret < 0)
1378 {
1379 /* If the input value is greater than max value of datatype, then also
1380 kstrtou8 fails */
1381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1382 "%s: kstrtou8 failed range [%d - %d]", __func__,
1383 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1384 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1385 ret = -EINVAL;
1386 goto exit;
1387 }
1388
1389 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1390 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1391 {
1392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1393 "lfr mode value %d is out of range"
1394 " (Min: %d Max: %d)", maxTime,
1395 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1396 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1397 ret = -EINVAL;
1398 goto exit;
1399 }
1400
1401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1402 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1403
1404 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1405 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1406 }
1407 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1408 {
1409 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1410 char extra[32];
1411 tANI_U8 len = 0;
1412
1413 /* value is interms of msec */
1414 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1415 if (copy_to_user(priv_data.buf, &extra, len + 1))
1416 {
1417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1418 "%s: failed to copy data to user buffer", __func__);
1419 ret = -EFAULT;
1420 goto exit;
1421 }
1422 }
1423 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1424 {
1425 tANI_U8 *value = command;
1426 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1427
1428 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1429 value = value + 16;
1430 /* Convert the value from ascii to integer */
1431 ret = kstrtou16(value, 10, &val);
1432 if (ret < 0)
1433 {
1434 /* If the input value is greater than max value of datatype, then also
1435 kstrtou16 fails */
1436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1437 "%s: kstrtou16 failed range [%d - %d]", __func__,
1438 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1439 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1440 ret = -EINVAL;
1441 goto exit;
1442 }
1443
1444 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1445 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1446 {
1447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1448 "scan home time value %d is out of range"
1449 " (Min: %d Max: %d)", val,
1450 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1451 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1452 ret = -EINVAL;
1453 goto exit;
1454 }
1455
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1457 "%s: Received Command to change scan home time = %d", __func__, val);
1458
1459 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1460 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1461 }
1462 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1463 {
1464 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1465 char extra[32];
1466 tANI_U8 len = 0;
1467
1468 /* value is interms of msec */
1469 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1470 if (copy_to_user(priv_data.buf, &extra, len + 1))
1471 {
1472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1473 "%s: failed to copy data to user buffer", __func__);
1474 ret = -EFAULT;
1475 goto exit;
1476 }
1477 }
1478 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1479 {
1480 tANI_U8 *value = command;
1481 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1482
1483 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1484 value = value + 17;
1485 /* Convert the value from ascii to integer */
1486 ret = kstrtou8(value, 10, &val);
1487 if (ret < 0)
1488 {
1489 /* If the input value is greater than max value of datatype, then also
1490 kstrtou8 fails */
1491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1492 "%s: kstrtou8 failed range [%d - %d]", __func__,
1493 CFG_ROAM_INTRA_BAND_MIN,
1494 CFG_ROAM_INTRA_BAND_MAX);
1495 ret = -EINVAL;
1496 goto exit;
1497 }
1498
1499 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1500 (val > CFG_ROAM_INTRA_BAND_MAX))
1501 {
1502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1503 "intra band mode value %d is out of range"
1504 " (Min: %d Max: %d)", val,
1505 CFG_ROAM_INTRA_BAND_MIN,
1506 CFG_ROAM_INTRA_BAND_MAX);
1507 ret = -EINVAL;
1508 goto exit;
1509 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1511 "%s: Received Command to change intra band = %d", __func__, val);
1512
1513 pHddCtx->cfg_ini->nRoamIntraBand = val;
1514 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1515 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001516 else if (strncmp(command, "SETWESMODE", 10) == 0)
1517 {
1518 tANI_U8 *value = command;
1519 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1520
1521 /* Move pointer to ahead of SETWESMODE<delimiter> */
1522 value = value + 11;
1523 /* Convert the value from ascii to integer */
1524 ret = kstrtou8(value, 10, &wesMode);
1525 if (ret < 0)
1526 {
1527 /* If the input value is greater than max value of datatype, then also
1528 kstrtou8 fails */
1529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1530 "%s: kstrtou8 failed range [%d - %d]", __func__,
1531 CFG_ENABLE_WES_MODE_NAME_MIN,
1532 CFG_ENABLE_WES_MODE_NAME_MAX);
1533 ret = -EINVAL;
1534 goto exit;
1535 }
1536
1537 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1538 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1539 {
1540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1541 "WES Mode value %d is out of range"
1542 " (Min: %d Max: %d)", wesMode,
1543 CFG_ENABLE_WES_MODE_NAME_MIN,
1544 CFG_ENABLE_WES_MODE_NAME_MAX);
1545 ret = -EINVAL;
1546 goto exit;
1547 }
1548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1549 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1550
1551 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1552 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1553 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001554 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1555 {
1556 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1557 char extra[32];
1558 tANI_U8 len = 0;
1559
1560 /* value is interms of msec */
1561 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1562 if (copy_to_user(priv_data.buf, &extra, len + 1))
1563 {
1564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1565 "%s: failed to copy data to user buffer", __func__);
1566 ret = -EFAULT;
1567 goto exit;
1568 }
1569 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001570 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1571 {
1572 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1573 char extra[32];
1574 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001575
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001576 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1577 if (copy_to_user(priv_data.buf, &extra, len + 1))
1578 {
1579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1580 "%s: failed to copy data to user buffer", __func__);
1581 ret = -EFAULT;
1582 goto exit;
1583 }
1584 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001585 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1586 {
1587 tANI_U8 *value = command;
1588 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1589
1590 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1591 value = value + 15;
1592 /* Convert the value from ascii to integer */
1593 ret = kstrtou8(value, 10, &nProbes);
1594 if (ret < 0)
1595 {
1596 /* If the input value is greater than max value of datatype, then also
1597 kstrtou8 fails */
1598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1599 "%s: kstrtou8 failed range [%d - %d]", __func__,
1600 CFG_ROAM_SCAN_N_PROBES_MIN,
1601 CFG_ROAM_SCAN_N_PROBES_MAX);
1602 ret = -EINVAL;
1603 goto exit;
1604 }
1605
1606 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1607 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1610 "NProbes value %d is out of range"
1611 " (Min: %d Max: %d)", nProbes,
1612 CFG_ROAM_SCAN_N_PROBES_MIN,
1613 CFG_ROAM_SCAN_N_PROBES_MAX);
1614 ret = -EINVAL;
1615 goto exit;
1616 }
1617
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1619 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1620
1621 pHddCtx->cfg_ini->nProbes = nProbes;
1622 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1623 }
1624 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1625 {
1626 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1627 char extra[32];
1628 tANI_U8 len = 0;
1629
1630 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1631 if (copy_to_user(priv_data.buf, &extra, len + 1))
1632 {
1633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1634 "%s: failed to copy data to user buffer", __func__);
1635 ret = -EFAULT;
1636 goto exit;
1637 }
1638 }
1639 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1640 {
1641 tANI_U8 *value = command;
1642 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
1643
1644 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1645 /* input value is in units of msec */
1646 value = value + 20;
1647 /* Convert the value from ascii to integer */
1648 ret = kstrtou16(value, 10, &homeAwayTime);
1649 if (ret < 0)
1650 {
1651 /* If the input value is greater than max value of datatype, then also
1652 kstrtou8 fails */
1653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1654 "%s: kstrtou8 failed range [%d - %d]", __func__,
1655 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1656 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1657 ret = -EINVAL;
1658 goto exit;
1659 }
1660
1661 /*Currently Home Away Time has a MIN value of 3.
1662 * But, we sould allow the user to input Zero,
1663 * since we are using the value of Zero to disable
1664 * this and fallback to LFR1.5 behaviour.*/
1665 if (0 != homeAwayTime)
1666 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1667 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1668 {
1669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1670 "homeAwayTime value %d is out of range"
1671 " (Min: %d Max: %d)", homeAwayTime,
1672 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1673 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
1678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1679 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1680
1681 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1682 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime);
1683 }
1684 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1685 {
1686 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1687 char extra[32];
1688 tANI_U8 len = 0;
1689
1690 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1691 if (copy_to_user(priv_data.buf, &extra, len + 1))
1692 {
1693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1694 "%s: failed to copy data to user buffer", __func__);
1695 ret = -EFAULT;
1696 goto exit;
1697 }
1698 }
1699 else if (strncmp(command, "REASSOC", 7) == 0)
1700 {
1701 tANI_U8 *value = command;
1702 tANI_U8 channel = 0;
1703 tSirMacAddr targetApBssid;
1704 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001705#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1706 tCsrHandoffRequest handoffInfo;
1707#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001708 hdd_station_ctx_t *pHddStaCtx = NULL;
1709 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1710 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1711
1712 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1713
1714 /* Reassoc command is allowed only if WES mode is enabled */
1715 if (!wesMode)
1716 {
1717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1718 ret = -EINVAL;
1719 goto exit;
1720 }
1721
1722 /* if not associated, no need to proceed with reassoc */
1723 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1724 {
1725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1726 ret = -EINVAL;
1727 goto exit;
1728 }
1729
1730 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1731 if (eHAL_STATUS_SUCCESS != status)
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "%s: Failed to parse reassoc command data", __func__);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 /* if the target bssid is same as currently associated AP,
1740 then no need to proceed with reassoc */
1741 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1742 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1743 {
1744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1745 ret = -EINVAL;
1746 goto exit;
1747 }
1748
1749 /* Check channel number is a valid channel number */
1750 if(VOS_STATUS_SUCCESS !=
1751 wlan_hdd_validate_operation_channel(pAdapter, channel))
1752 {
1753 hddLog(VOS_TRACE_LEVEL_ERROR,
1754 "%s: Invalid Channel [%d] \n", __func__, channel);
1755 return -EINVAL;
1756 }
1757
1758 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001759#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1760 handoffInfo.channel = channel;
1761 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1762 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1763#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001764 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001765#endif
1766#ifdef FEATURE_WLAN_LFR
1767 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1768 {
1769 tANI_U8 *value = command;
1770 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1771
1772 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1773 value = value + 12;
1774 /* Convert the value from ascii to integer */
1775 ret = kstrtou8(value, 10, &lfrMode);
1776 if (ret < 0)
1777 {
1778 /* If the input value is greater than max value of datatype, then also
1779 kstrtou8 fails */
1780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1781 "%s: kstrtou8 failed range [%d - %d]", __func__,
1782 CFG_LFR_FEATURE_ENABLED_MIN,
1783 CFG_LFR_FEATURE_ENABLED_MAX);
1784 ret = -EINVAL;
1785 goto exit;
1786 }
1787
1788 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1789 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1790 {
1791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1792 "lfr mode value %d is out of range"
1793 " (Min: %d Max: %d)", lfrMode,
1794 CFG_LFR_FEATURE_ENABLED_MIN,
1795 CFG_LFR_FEATURE_ENABLED_MAX);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799
1800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1801 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1802
1803 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1804 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1805 }
1806#endif
1807#ifdef WLAN_FEATURE_VOWIFI_11R
1808 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1809 {
1810 tANI_U8 *value = command;
1811 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1812
1813 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1814 value = value + 18;
1815 /* Convert the value from ascii to integer */
1816 ret = kstrtou8(value, 10, &ft);
1817 if (ret < 0)
1818 {
1819 /* If the input value is greater than max value of datatype, then also
1820 kstrtou8 fails */
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1822 "%s: kstrtou8 failed range [%d - %d]", __func__,
1823 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1824 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1825 ret = -EINVAL;
1826 goto exit;
1827 }
1828
1829 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1830 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1831 {
1832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1833 "ft mode value %d is out of range"
1834 " (Min: %d Max: %d)", ft,
1835 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1836 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1837 ret = -EINVAL;
1838 goto exit;
1839 }
1840
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1842 "%s: Received Command to change ft mode = %d", __func__, ft);
1843
1844 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1845 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1846 }
1847#endif
1848#ifdef FEATURE_WLAN_CCX
1849 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1850 {
1851 tANI_U8 *value = command;
1852 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1853
1854 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1855 value = value + 11;
1856 /* Convert the value from ascii to integer */
1857 ret = kstrtou8(value, 10, &ccxMode);
1858 if (ret < 0)
1859 {
1860 /* If the input value is greater than max value of datatype, then also
1861 kstrtou8 fails */
1862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1863 "%s: kstrtou8 failed range [%d - %d]", __func__,
1864 CFG_CCX_FEATURE_ENABLED_MIN,
1865 CFG_CCX_FEATURE_ENABLED_MAX);
1866 ret = -EINVAL;
1867 goto exit;
1868 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001869 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1870 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1871 {
1872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1873 "Ccx mode value %d is out of range"
1874 " (Min: %d Max: %d)", ccxMode,
1875 CFG_CCX_FEATURE_ENABLED_MIN,
1876 CFG_CCX_FEATURE_ENABLED_MAX);
1877 ret = -EINVAL;
1878 goto exit;
1879 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1881 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1882
1883 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1884 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1885 }
1886#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001887 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1888 {
1889 tANI_U8 *value = command;
1890 tANI_BOOLEAN roamScanControl = 0;
1891
1892 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1893 value = value + 19;
1894 /* Convert the value from ascii to integer */
1895 ret = kstrtou8(value, 10, &roamScanControl);
1896 if (ret < 0)
1897 {
1898 /* If the input value is greater than max value of datatype, then also
1899 kstrtou8 fails */
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1901 "%s: kstrtou8 failed ", __func__);
1902 ret = -EINVAL;
1903 goto exit;
1904 }
1905
1906 if (0 != roamScanControl)
1907 {
1908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1909 "roam scan control invalid value = %d",
1910 roamScanControl);
1911 ret = -EINVAL;
1912 goto exit;
1913 }
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1915 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1916
1917 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1918 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919#ifdef FEATURE_WLAN_OKC
1920 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1921 {
1922 tANI_U8 *value = command;
1923 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1924
1925 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1926 value = value + 11;
1927 /* Convert the value from ascii to integer */
1928 ret = kstrtou8(value, 10, &okcMode);
1929 if (ret < 0)
1930 {
1931 /* If the input value is greater than max value of datatype, then also
1932 kstrtou8 fails */
1933 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1934 "%s: kstrtou8 failed range [%d - %d]", __func__,
1935 CFG_OKC_FEATURE_ENABLED_MIN,
1936 CFG_OKC_FEATURE_ENABLED_MAX);
1937 ret = -EINVAL;
1938 goto exit;
1939 }
1940
1941 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1942 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1943 {
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1945 "Okc mode value %d is out of range"
1946 " (Min: %d Max: %d)", okcMode,
1947 CFG_OKC_FEATURE_ENABLED_MIN,
1948 CFG_OKC_FEATURE_ENABLED_MAX);
1949 ret = -EINVAL;
1950 goto exit;
1951 }
1952
1953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1954 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1955
1956 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1957 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001958 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1959 {
1960 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1961 char extra[32];
1962 tANI_U8 len = 0;
1963
1964 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1965 if (copy_to_user(priv_data.buf, &extra, len + 1))
1966 {
1967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1968 "%s: failed to copy data to user buffer", __func__);
1969 ret = -EFAULT;
1970 goto exit;
1971 }
1972 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001973#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001974 else {
1975 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1976 __func__, command);
1977 }
1978
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 }
1980exit:
1981 if (command)
1982 {
1983 kfree(command);
1984 }
1985 return ret;
1986}
1987
Srinivas Girigowdade697412013-02-14 16:31:48 -08001988#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1989void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1990{
1991 eCsrBand band = -1;
1992 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1993 switch (band)
1994 {
1995 case eCSR_BAND_ALL:
1996 *pBand = WLAN_HDD_UI_BAND_AUTO;
1997 break;
1998
1999 case eCSR_BAND_24:
2000 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2001 break;
2002
2003 case eCSR_BAND_5G:
2004 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2005 break;
2006
2007 default:
2008 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2009 *pBand = -1;
2010 break;
2011 }
2012}
2013
2014/**---------------------------------------------------------------------------
2015
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002016 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2017
2018 This function parses the send action frame data passed in the format
2019 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2020
2021 \param - pValue Pointer to input country code revision
2022 \param - pTargetApBssid Pointer to target Ap bssid
2023 \param - pChannel Pointer to the Target AP channel
2024 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2025 \param - pBuf Pointer to data
2026 \param - pBufLen Pointer to data length
2027
2028 \return - 0 for success non-zero for failure
2029
2030 --------------------------------------------------------------------------*/
2031VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2032 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2033{
2034 tANI_U8 *inPtr = pValue;
2035 tANI_U8 *dataEnd;
2036 int tempInt;
2037 int j = 0;
2038 int i = 0;
2039 int v = 0;
2040 tANI_U8 tempBuf[32];
2041 tANI_U8 tempByte = 0;
2042
2043 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2044 /*no argument after the command*/
2045 if (NULL == inPtr)
2046 {
2047 return -EINVAL;
2048 }
2049
2050 /*no space after the command*/
2051 else if (SPACE_ASCII_VALUE != *inPtr)
2052 {
2053 return -EINVAL;
2054 }
2055
2056 /*removing empty spaces*/
2057 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2058
2059 /*no argument followed by spaces*/
2060 if ('\0' == *inPtr)
2061 {
2062 return -EINVAL;
2063 }
2064
2065 /*getting the first argument ie the target AP bssid */
2066 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2067 {
2068 return -EINVAL;
2069 }
2070 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2071 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2072 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2073
2074 /* point to the next argument */
2075 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2076 /*no argument after the command*/
2077 if (NULL == inPtr) return -EINVAL;
2078
2079 /*removing empty spaces*/
2080 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2081
2082 /*no argument followed by spaces*/
2083 if ('\0' == *inPtr)
2084 {
2085 return -EINVAL;
2086 }
2087
2088 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002089 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002090 v = kstrtos32(tempBuf, 10, &tempInt);
2091 if ( v < 0) return -EINVAL;
2092
2093 *pChannel = tempInt;
2094
2095 /* point to the next argument */
2096 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2097 /*no argument after the command*/
2098 if (NULL == inPtr) return -EINVAL;
2099 /*removing empty spaces*/
2100 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2101
2102 /*no argument followed by spaces*/
2103 if ('\0' == *inPtr)
2104 {
2105 return -EINVAL;
2106 }
2107
2108 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002109 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002110 v = kstrtos32(tempBuf, 10, &tempInt);
2111 if ( v < 0) return -EINVAL;
2112
2113 *pDwellTime = tempInt;
2114
2115 /* point to the next argument */
2116 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2117 /*no argument after the command*/
2118 if (NULL == inPtr) return -EINVAL;
2119 /*removing empty spaces*/
2120 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2121
2122 /*no argument followed by spaces*/
2123 if ('\0' == *inPtr)
2124 {
2125 return -EINVAL;
2126 }
2127
2128 /* find the length of data */
2129 dataEnd = inPtr;
2130 while(('\0' != *dataEnd) )
2131 {
2132 dataEnd++;
2133 ++(*pBufLen);
2134 }
2135 if ( *pBufLen <= 0) return -EINVAL;
2136
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002137 /* Allocate the number of bytes based on the number of input characters
2138 whether it is even or odd.
2139 if the number of input characters are even, then we need N/2 byte.
2140 if the number of input characters are odd, then we need do (N+1)/2 to
2141 compensate rounding off.
2142 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2143 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2144 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002145 if (NULL == *pBuf)
2146 {
2147 hddLog(VOS_TRACE_LEVEL_FATAL,
2148 "%s: vos_mem_alloc failed ", __func__);
2149 return -EINVAL;
2150 }
2151
2152 /* the buffer received from the upper layer is character buffer,
2153 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2154 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2155 and f0 in 3rd location */
2156 for (i = 0, j = 0; j < *pBufLen; j += 2)
2157 {
2158 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2159 (*pBuf)[i++] = tempByte;
2160 }
2161 *pBufLen = i;
2162 return VOS_STATUS_SUCCESS;
2163}
2164
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002165/**---------------------------------------------------------------------------
2166
Srinivas Girigowdade697412013-02-14 16:31:48 -08002167 \brief hdd_parse_countryrev() - HDD Parse country code revision
2168
2169 This function parses the country code revision passed in the format
2170 SETCOUNTRYREV<space><Country code><space>revision
2171
2172 \param - pValue Pointer to input country code revision
2173 \param - pCountryCode Pointer to local output array to record country code
2174 \param - pRevision Pointer to store revision integer number
2175
2176 \return - 0 for success non-zero for failure
2177
2178 --------------------------------------------------------------------------*/
2179VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2180{
2181 tANI_U8 *inPtr = pValue;
2182 int tempInt;
2183
2184 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2185 /*no argument after the command*/
2186 if (NULL == inPtr)
2187 {
2188 return -EINVAL;
2189 }
2190
2191 /*no space after the command*/
2192 else if (SPACE_ASCII_VALUE != *inPtr)
2193 {
2194 return -EINVAL;
2195 }
2196
2197 /*removing empty spaces*/
2198 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2199
2200 /*no argument followed by spaces*/
2201 if ('\0' == *inPtr)
2202 {
2203 return -EINVAL;
2204 }
2205
2206 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002207 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002208
2209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2210 "Country code is : %s", pCountryCode);
2211
2212 /*inPtr pointing to the beginning of first space after country code */
2213 inPtr = strpbrk( inPtr, " " );
2214 /*no revision number after the country code argument */
2215 if (NULL == inPtr)
2216 {
2217 return -EINVAL;
2218 }
2219
2220 inPtr++;
2221
2222 /*removing empty space*/
2223 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2224
2225 /*no channel list after the number of channels argument and spaces*/
2226 if (0 == strncmp(pCountryCode, "KR", 2))
2227 {
2228 if ('\0' == *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 sscanf(inPtr, "%d", &tempInt);
2234 *pRevision = tempInt;
2235 }
2236 else
2237 {
2238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2239 "Revision input is required only for Country KR");
2240 return -EINVAL;
2241 }
2242 return VOS_STATUS_SUCCESS;
2243}
2244
2245/**---------------------------------------------------------------------------
2246
2247 \brief hdd_parse_channellist() - HDD Parse channel list
2248
2249 This function parses the channel list passed in the format
2250 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002251 if the Number of channels (N) does not match with the actual number of channels passed
2252 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2253 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2254 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2255 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002256
2257 \param - pValue Pointer to input channel list
2258 \param - ChannelList Pointer to local output array to record channel list
2259 \param - pNumChannels Pointer to number of roam scan channels
2260
2261 \return - 0 for success non-zero for failure
2262
2263 --------------------------------------------------------------------------*/
2264VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2265{
2266 tANI_U8 *inPtr = pValue;
2267 int tempInt;
2268 int j = 0;
2269 int v = 0;
2270 char buf[32];
2271
2272 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2273 /*no argument after the command*/
2274 if (NULL == inPtr)
2275 {
2276 return -EINVAL;
2277 }
2278
2279 /*no space after the command*/
2280 else if (SPACE_ASCII_VALUE != *inPtr)
2281 {
2282 return -EINVAL;
2283 }
2284
2285 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002286 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002287
2288 /*no argument followed by spaces*/
2289 if ('\0' == *inPtr)
2290 {
2291 return -EINVAL;
2292 }
2293
2294 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002295 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002296 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002297 if ((v < 0) ||
2298 (tempInt <= 0) ||
2299 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2300 {
2301 return -EINVAL;
2302 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002303
2304 *pNumChannels = tempInt;
2305
2306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2307 "Number of channels are: %d", *pNumChannels);
2308
2309 for (j = 0; j < (*pNumChannels); j++)
2310 {
2311 /*inPtr pointing to the beginning of first space after number of channels*/
2312 inPtr = strpbrk( inPtr, " " );
2313 /*no channel list after the number of channels argument*/
2314 if (NULL == inPtr)
2315 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002316 if (0 != j)
2317 {
2318 *pNumChannels = j;
2319 return VOS_STATUS_SUCCESS;
2320 }
2321 else
2322 {
2323 return -EINVAL;
2324 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002325 }
2326
2327 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002328 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002329
2330 /*no channel list after the number of channels argument and spaces*/
2331 if ( '\0' == *inPtr )
2332 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002333 if (0 != j)
2334 {
2335 *pNumChannels = j;
2336 return VOS_STATUS_SUCCESS;
2337 }
2338 else
2339 {
2340 return -EINVAL;
2341 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002342 }
2343
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002344 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002346 if ((v < 0) ||
2347 (tempInt <= 0) ||
2348 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2349 {
2350 return -EINVAL;
2351 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002352 pChannelList[j] = tempInt;
2353
2354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2355 "Channel %d added to preferred channel list",
2356 pChannelList[j] );
2357 }
2358
Srinivas Girigowdade697412013-02-14 16:31:48 -08002359 return VOS_STATUS_SUCCESS;
2360}
2361
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002362
2363/**---------------------------------------------------------------------------
2364
2365 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2366
2367 This function parses the reasoc command data passed in the format
2368 REASSOC<space><bssid><space><channel>
2369
2370 \param - pValue Pointer to input country code revision
2371 \param - pTargetApBssid Pointer to target Ap bssid
2372 \param - pChannel Pointer to the Target AP channel
2373
2374 \return - 0 for success non-zero for failure
2375
2376 --------------------------------------------------------------------------*/
2377VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2378{
2379 tANI_U8 *inPtr = pValue;
2380 int tempInt;
2381 int v = 0;
2382 tANI_U8 tempBuf[32];
2383
2384 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2385 /*no argument after the command*/
2386 if (NULL == inPtr)
2387 {
2388 return -EINVAL;
2389 }
2390
2391 /*no space after the command*/
2392 else if (SPACE_ASCII_VALUE != *inPtr)
2393 {
2394 return -EINVAL;
2395 }
2396
2397 /*removing empty spaces*/
2398 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2399
2400 /*no argument followed by spaces*/
2401 if ('\0' == *inPtr)
2402 {
2403 return -EINVAL;
2404 }
2405
2406 /*getting the first argument ie the target AP bssid */
2407 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2408 {
2409 return -EINVAL;
2410 }
2411 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2412 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2413 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2414
2415 /* point to the next argument */
2416 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2417 /*no argument after the command*/
2418 if (NULL == inPtr) return -EINVAL;
2419
2420 /*removing empty spaces*/
2421 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2422
2423 /*no argument followed by spaces*/
2424 if ('\0' == *inPtr)
2425 {
2426 return -EINVAL;
2427 }
2428
2429 /*getting the next argument ie the channel number */
2430 sscanf(inPtr, "%s ", tempBuf);
2431 v = kstrtos32(tempBuf, 10, &tempInt);
2432 if ( v < 0) return -EINVAL;
2433
2434 *pChannel = tempInt;
2435 return VOS_STATUS_SUCCESS;
2436}
2437
2438#endif
2439
Jeff Johnson295189b2012-06-20 16:38:30 -07002440/**---------------------------------------------------------------------------
2441
2442 \brief hdd_open() - HDD Open function
2443
2444 This is called in response to ifconfig up
2445
2446 \param - dev Pointer to net_device structure
2447
2448 \return - 0 for success non-zero for failure
2449
2450 --------------------------------------------------------------------------*/
2451int hdd_open (struct net_device *dev)
2452{
2453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2454 hdd_context_t *pHddCtx;
2455 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2456 VOS_STATUS status;
2457 v_BOOL_t in_standby = TRUE;
2458
2459 if (NULL == pAdapter)
2460 {
2461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002462 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002463 return -ENODEV;
2464 }
2465
2466 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2467 if (NULL == pHddCtx)
2468 {
2469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002470 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 return -ENODEV;
2472 }
2473
2474 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2475 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2476 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002477 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2478 {
2479 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302480 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002481 in_standby = FALSE;
2482 break;
2483 }
2484 else
2485 {
2486 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2487 pAdapterNode = pNext;
2488 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002489 }
2490
2491 if (TRUE == in_standby)
2492 {
2493 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2494 {
2495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2496 "wlan out of power save", __func__);
2497 return -EINVAL;
2498 }
2499 }
2500
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002501 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002505 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002506 /* Enable TX queues only when we are connected */
2507 netif_tx_start_all_queues(dev);
2508 }
2509
2510 return 0;
2511}
2512
2513int hdd_mon_open (struct net_device *dev)
2514{
2515 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2516
2517 if(pAdapter == NULL) {
2518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002519 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002520 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 }
2522
2523 netif_start_queue(dev);
2524
2525 return 0;
2526}
2527/**---------------------------------------------------------------------------
2528
2529 \brief hdd_stop() - HDD stop function
2530
2531 This is called in response to ifconfig down
2532
2533 \param - dev Pointer to net_device structure
2534
2535 \return - 0 for success non-zero for failure
2536
2537 --------------------------------------------------------------------------*/
2538
2539int hdd_stop (struct net_device *dev)
2540{
2541 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2542 hdd_context_t *pHddCtx;
2543 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2544 VOS_STATUS status;
2545 v_BOOL_t enter_standby = TRUE;
2546
2547 ENTER();
2548
2549 if (NULL == pAdapter)
2550 {
2551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002552 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002553 return -ENODEV;
2554 }
2555
2556 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2557 if (NULL == pHddCtx)
2558 {
2559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002560 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002561 return -ENODEV;
2562 }
2563
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002564 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2566 netif_tx_disable(pAdapter->dev);
2567 netif_carrier_off(pAdapter->dev);
2568
2569
2570 /* SoftAP ifaces should never go in power save mode
2571 making sure same here. */
2572 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2573 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002574 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 )
2576 {
2577 /* SoftAP mode, so return from here */
2578 EXIT();
2579 return 0;
2580 }
2581
2582 /* Find if any iface is up then
2583 if any iface is up then can't put device to sleep/ power save mode. */
2584 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2585 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2586 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002587 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2588 {
2589 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302590 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002591 enter_standby = FALSE;
2592 break;
2593 }
2594 else
2595 {
2596 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2597 pAdapterNode = pNext;
2598 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 }
2600
2601 if (TRUE == enter_standby)
2602 {
2603 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2604 "entering standby", __func__);
2605 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2606 {
2607 /*log and return success*/
2608 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2609 "wlan in power save", __func__);
2610 }
2611 }
2612
2613 EXIT();
2614 return 0;
2615}
2616
2617/**---------------------------------------------------------------------------
2618
2619 \brief hdd_uninit() - HDD uninit function
2620
2621 This is called during the netdev unregister to uninitialize all data
2622associated with the device
2623
2624 \param - dev Pointer to net_device structure
2625
2626 \return - void
2627
2628 --------------------------------------------------------------------------*/
2629static void hdd_uninit (struct net_device *dev)
2630{
2631 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2632
2633 ENTER();
2634
2635 do
2636 {
2637 if (NULL == pAdapter)
2638 {
2639 hddLog(VOS_TRACE_LEVEL_FATAL,
2640 "%s: NULL pAdapter", __func__);
2641 break;
2642 }
2643
2644 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2645 {
2646 hddLog(VOS_TRACE_LEVEL_FATAL,
2647 "%s: Invalid magic", __func__);
2648 break;
2649 }
2650
2651 if (NULL == pAdapter->pHddCtx)
2652 {
2653 hddLog(VOS_TRACE_LEVEL_FATAL,
2654 "%s: NULL pHddCtx", __func__);
2655 break;
2656 }
2657
2658 if (dev != pAdapter->dev)
2659 {
2660 hddLog(VOS_TRACE_LEVEL_FATAL,
2661 "%s: Invalid device reference", __func__);
2662 /* we haven't validated all cases so let this go for now */
2663 }
2664
2665 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2666
2667 /* after uninit our adapter structure will no longer be valid */
2668 pAdapter->dev = NULL;
2669 pAdapter->magic = 0;
2670 } while (0);
2671
2672 EXIT();
2673}
2674
2675/**---------------------------------------------------------------------------
2676
2677 \brief hdd_release_firmware() -
2678
2679 This function calls the release firmware API to free the firmware buffer.
2680
2681 \param - pFileName Pointer to the File Name.
2682 pCtx - Pointer to the adapter .
2683
2684
2685 \return - 0 for success, non zero for failure
2686
2687 --------------------------------------------------------------------------*/
2688
2689VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2690{
2691 VOS_STATUS status = VOS_STATUS_SUCCESS;
2692 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2693 ENTER();
2694
2695
2696 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2697
2698 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2699
2700 if(pHddCtx->fw) {
2701 release_firmware(pHddCtx->fw);
2702 pHddCtx->fw = NULL;
2703 }
2704 else
2705 status = VOS_STATUS_E_FAILURE;
2706 }
2707 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2708 if(pHddCtx->nv) {
2709 release_firmware(pHddCtx->nv);
2710 pHddCtx->nv = NULL;
2711 }
2712 else
2713 status = VOS_STATUS_E_FAILURE;
2714
2715 }
2716
2717 EXIT();
2718 return status;
2719}
2720
2721/**---------------------------------------------------------------------------
2722
2723 \brief hdd_request_firmware() -
2724
2725 This function reads the firmware file using the request firmware
2726 API and returns the the firmware data and the firmware file size.
2727
2728 \param - pfileName - Pointer to the file name.
2729 - pCtx - Pointer to the adapter .
2730 - ppfw_data - Pointer to the pointer of the firmware data.
2731 - pSize - Pointer to the file size.
2732
2733 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2734
2735 --------------------------------------------------------------------------*/
2736
2737
2738VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2739{
2740 int status;
2741 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2742 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2743 ENTER();
2744
2745 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2746
2747 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2748
2749 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2750 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2751 __func__, pfileName);
2752 retval = VOS_STATUS_E_FAILURE;
2753 }
2754
2755 else {
2756 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2757 *pSize = pHddCtx->fw->size;
2758 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2759 __func__, *pSize);
2760 }
2761 }
2762 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2763
2764 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2765
2766 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2767 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2768 __func__, pfileName);
2769 retval = VOS_STATUS_E_FAILURE;
2770 }
2771
2772 else {
2773 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2774 *pSize = pHddCtx->nv->size;
2775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2776 __func__, *pSize);
2777 }
2778 }
2779
2780 EXIT();
2781 return retval;
2782}
2783/**---------------------------------------------------------------------------
2784 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2785
2786 This is the function invoked by SME to inform the result of a full power
2787 request issued by HDD
2788
2789 \param - callbackcontext - Pointer to cookie
2790 status - result of request
2791
2792 \return - None
2793
2794--------------------------------------------------------------------------*/
2795void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2796{
2797 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2798
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002799 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002800 if(&pHddCtx->full_pwr_comp_var)
2801 {
2802 complete(&pHddCtx->full_pwr_comp_var);
2803 }
2804}
2805
2806/**---------------------------------------------------------------------------
2807
2808 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2809
2810 This is the function invoked by SME to inform the result of BMPS
2811 request issued by HDD
2812
2813 \param - callbackcontext - Pointer to cookie
2814 status - result of request
2815
2816 \return - None
2817
2818--------------------------------------------------------------------------*/
2819void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2820{
2821
2822 struct completion *completion_var = (struct completion*) callbackContext;
2823
2824 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2825 if(completion_var != NULL)
2826 {
2827 complete(completion_var);
2828 }
2829}
2830
2831/**---------------------------------------------------------------------------
2832
2833 \brief hdd_get_cfg_file_size() -
2834
2835 This function reads the configuration file using the request firmware
2836 API and returns the configuration file size.
2837
2838 \param - pCtx - Pointer to the adapter .
2839 - pFileName - Pointer to the file name.
2840 - pBufSize - Pointer to the buffer size.
2841
2842 \return - 0 for success, non zero for failure
2843
2844 --------------------------------------------------------------------------*/
2845
2846VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2847{
2848 int status;
2849 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2850
2851 ENTER();
2852
2853 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2854
2855 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2857 status = VOS_STATUS_E_FAILURE;
2858 }
2859 else {
2860 *pBufSize = pHddCtx->fw->size;
2861 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2862 release_firmware(pHddCtx->fw);
2863 pHddCtx->fw = NULL;
2864 }
2865
2866 EXIT();
2867 return VOS_STATUS_SUCCESS;
2868}
2869
2870/**---------------------------------------------------------------------------
2871
2872 \brief hdd_read_cfg_file() -
2873
2874 This function reads the configuration file using the request firmware
2875 API and returns the cfg data and the buffer size of the configuration file.
2876
2877 \param - pCtx - Pointer to the adapter .
2878 - pFileName - Pointer to the file name.
2879 - pBuffer - Pointer to the data buffer.
2880 - pBufSize - Pointer to the buffer size.
2881
2882 \return - 0 for success, non zero for failure
2883
2884 --------------------------------------------------------------------------*/
2885
2886VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2887 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2888{
2889 int status;
2890 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2891
2892 ENTER();
2893
2894 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2895
2896 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2897 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2898 return VOS_STATUS_E_FAILURE;
2899 }
2900 else {
2901 if(*pBufSize != pHddCtx->fw->size) {
2902 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2903 "file size", __func__);
2904 release_firmware(pHddCtx->fw);
2905 pHddCtx->fw = NULL;
2906 return VOS_STATUS_E_FAILURE;
2907 }
2908 else {
2909 if(pBuffer) {
2910 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2911 }
2912 release_firmware(pHddCtx->fw);
2913 pHddCtx->fw = NULL;
2914 }
2915 }
2916
2917 EXIT();
2918
2919 return VOS_STATUS_SUCCESS;
2920}
2921
2922/**---------------------------------------------------------------------------
2923
Jeff Johnson295189b2012-06-20 16:38:30 -07002924 \brief hdd_set_mac_address() -
2925
2926 This function sets the user specified mac address using
2927 the command ifconfig wlanX hw ether <mac adress>.
2928
2929 \param - dev - Pointer to the net device.
2930 - addr - Pointer to the sockaddr.
2931 \return - 0 for success, non zero for failure
2932
2933 --------------------------------------------------------------------------*/
2934
2935static int hdd_set_mac_address(struct net_device *dev, void *addr)
2936{
2937 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2938 struct sockaddr *psta_mac_addr = addr;
2939 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2940
2941 ENTER();
2942
2943 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2944
2945#ifdef HDD_SESSIONIZE
2946 // set the MAC address though the STA ID CFG.
2947 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2948 (v_U8_t *)&pAdapter->macAddressCurrent,
2949 sizeof( pAdapter->macAddressCurrent ),
2950 hdd_set_mac_addr_cb, VOS_FALSE );
2951#endif
2952
2953 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2954
2955 EXIT();
2956 return halStatus;
2957}
2958
2959tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2960{
2961 int i;
2962 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2963 {
2964 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2965 break;
2966 }
2967
2968 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2969 return NULL;
2970
2971 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2972 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2973}
2974
2975void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2976{
2977 int i;
2978 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2979 {
2980 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2981 {
2982 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2983 break;
2984 }
2985 }
2986 return;
2987}
2988
2989#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2990 static struct net_device_ops wlan_drv_ops = {
2991 .ndo_open = hdd_open,
2992 .ndo_stop = hdd_stop,
2993 .ndo_uninit = hdd_uninit,
2994 .ndo_start_xmit = hdd_hard_start_xmit,
2995 .ndo_tx_timeout = hdd_tx_timeout,
2996 .ndo_get_stats = hdd_stats,
2997 .ndo_do_ioctl = hdd_ioctl,
2998 .ndo_set_mac_address = hdd_set_mac_address,
2999 .ndo_select_queue = hdd_select_queue,
3000#ifdef WLAN_FEATURE_PACKET_FILTERING
3001#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3002 .ndo_set_rx_mode = hdd_set_multicast_list,
3003#else
3004 .ndo_set_multicast_list = hdd_set_multicast_list,
3005#endif //LINUX_VERSION_CODE
3006#endif
3007 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003008 static struct net_device_ops wlan_mon_drv_ops = {
3009 .ndo_open = hdd_mon_open,
3010 .ndo_stop = hdd_stop,
3011 .ndo_uninit = hdd_uninit,
3012 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3013 .ndo_tx_timeout = hdd_tx_timeout,
3014 .ndo_get_stats = hdd_stats,
3015 .ndo_do_ioctl = hdd_ioctl,
3016 .ndo_set_mac_address = hdd_set_mac_address,
3017 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003018
3019#endif
3020
3021void hdd_set_station_ops( struct net_device *pWlanDev )
3022{
3023#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3024 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3025 pWlanDev->netdev_ops = &wlan_drv_ops;
3026#else
3027 pWlanDev->open = hdd_open;
3028 pWlanDev->stop = hdd_stop;
3029 pWlanDev->uninit = hdd_uninit;
3030 pWlanDev->hard_start_xmit = NULL;
3031 pWlanDev->tx_timeout = hdd_tx_timeout;
3032 pWlanDev->get_stats = hdd_stats;
3033 pWlanDev->do_ioctl = hdd_ioctl;
3034 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3035 pWlanDev->set_mac_address = hdd_set_mac_address;
3036#endif
3037}
3038
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003039static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003040{
3041 struct net_device *pWlanDev = NULL;
3042 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003043 /*
3044 * cfg80211 initialization and registration....
3045 */
3046 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3047
Jeff Johnson295189b2012-06-20 16:38:30 -07003048 if(pWlanDev != NULL)
3049 {
3050
3051 //Save the pointer to the net_device in the HDD adapter
3052 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3053
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3055
3056 pAdapter->dev = pWlanDev;
3057 pAdapter->pHddCtx = pHddCtx;
3058 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3059
3060 init_completion(&pAdapter->session_open_comp_var);
3061 init_completion(&pAdapter->session_close_comp_var);
3062 init_completion(&pAdapter->disconnect_comp_var);
3063 init_completion(&pAdapter->linkup_event_var);
3064 init_completion(&pAdapter->cancel_rem_on_chan_var);
3065 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003066#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3067 init_completion(&pAdapter->offchannel_tx_event);
3068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003070#ifdef FEATURE_WLAN_TDLS
3071 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003072 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003073 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303074 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 init_completion(&pHddCtx->mc_sus_event_var);
3077 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003078 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003079
Jeff Johnson295189b2012-06-20 16:38:30 -07003080 pAdapter->isLinkUpSvcNeeded = FALSE;
3081 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3082 //Init the net_device structure
3083 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3084
3085 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3086 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3087 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3088 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3089
3090 hdd_set_station_ops( pAdapter->dev );
3091
3092 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003093 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3094 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3095 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003096 /* set pWlanDev's parent to underlying device */
3097 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3098 }
3099
3100 return pAdapter;
3101}
3102
3103VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3104{
3105 struct net_device *pWlanDev = pAdapter->dev;
3106 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3107 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3108 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3109
3110 if( rtnl_lock_held )
3111 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003112 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003113 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3114 {
3115 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3116 return VOS_STATUS_E_FAILURE;
3117 }
3118 }
3119 if (register_netdevice(pWlanDev))
3120 {
3121 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3122 return VOS_STATUS_E_FAILURE;
3123 }
3124 }
3125 else
3126 {
3127 if(register_netdev(pWlanDev))
3128 {
3129 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3130 return VOS_STATUS_E_FAILURE;
3131 }
3132 }
3133 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3134
3135 return VOS_STATUS_SUCCESS;
3136}
3137
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003138static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003139{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003140 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003141
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003142 if (NULL == pAdapter)
3143 {
3144 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3145 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003146 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003147
3148 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3149 {
3150 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3151 return eHAL_STATUS_NOT_INITIALIZED;
3152 }
3153
3154 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3155
3156 /* need to make sure all of our scheduled work has completed.
3157 * This callback is called from MC thread context, so it is safe to
3158 * to call below flush workqueue API from here.
3159 */
3160 flush_scheduled_work();
3161
3162 /* We can be blocked while waiting for scheduled work to be
3163 * flushed, and the adapter structure can potentially be freed, in
3164 * which case the magic will have been reset. So make sure the
3165 * magic is still good, and hence the adapter structure is still
3166 * valid, before signaling completion */
3167 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3168 {
3169 complete(&pAdapter->session_close_comp_var);
3170 }
3171
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 return eHAL_STATUS_SUCCESS;
3173}
3174
3175VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3176{
3177 struct net_device *pWlanDev = pAdapter->dev;
3178 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3179 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3180 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3181 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3182 int rc = 0;
3183
3184 INIT_COMPLETION(pAdapter->session_open_comp_var);
3185 //Open a SME session for future operation
3186 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3187 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3188 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3189 {
3190 hddLog(VOS_TRACE_LEVEL_FATAL,
3191 "sme_OpenSession() failed with status code %08d [x%08lx]",
3192 halStatus, halStatus );
3193 status = VOS_STATUS_E_FAILURE;
3194 goto error_sme_open;
3195 }
3196
3197 //Block on a completion variable. Can't wait forever though.
3198 rc = wait_for_completion_interruptible_timeout(
3199 &pAdapter->session_open_comp_var,
3200 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3201 if (!rc)
3202 {
3203 hddLog(VOS_TRACE_LEVEL_FATAL,
3204 "Session is not opened within timeout period code %08d", rc );
3205 status = VOS_STATUS_E_FAILURE;
3206 goto error_sme_open;
3207 }
3208
3209 // Register wireless extensions
3210 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3211 {
3212 hddLog(VOS_TRACE_LEVEL_FATAL,
3213 "hdd_register_wext() failed with status code %08d [x%08lx]",
3214 halStatus, halStatus );
3215 status = VOS_STATUS_E_FAILURE;
3216 goto error_register_wext;
3217 }
3218 //Safe to register the hard_start_xmit function again
3219#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3220 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3221#else
3222 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3223#endif
3224
3225 //Set the Connection State to Not Connected
3226 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3227
3228 //Set the default operation channel
3229 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3230
3231 /* Make the default Auth Type as OPEN*/
3232 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3233
3234 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3235 {
3236 hddLog(VOS_TRACE_LEVEL_FATAL,
3237 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3238 status, status );
3239 goto error_init_txrx;
3240 }
3241
3242 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3243
3244 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3245 {
3246 hddLog(VOS_TRACE_LEVEL_FATAL,
3247 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3248 status, status );
3249 goto error_wmm_init;
3250 }
3251
3252 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3253
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003254#ifdef FEATURE_WLAN_TDLS
3255 if(0 != wlan_hdd_tdls_init(pAdapter))
3256 {
3257 status = VOS_STATUS_E_FAILURE;
3258 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3259 goto error_tdls_init;
3260 }
3261 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3262#endif
3263
Jeff Johnson295189b2012-06-20 16:38:30 -07003264 return VOS_STATUS_SUCCESS;
3265
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003266#ifdef FEATURE_WLAN_TDLS
3267error_tdls_init:
3268 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3269 hdd_wmm_adapter_close(pAdapter);
3270#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003271error_wmm_init:
3272 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3273 hdd_deinit_tx_rx(pAdapter);
3274error_init_txrx:
3275 hdd_UnregisterWext(pWlanDev);
3276error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003277 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003278 {
3279 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003280 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003281 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003282 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003283 {
3284 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003285 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003286 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003287 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003288 }
3289}
3290error_sme_open:
3291 return status;
3292}
3293
Jeff Johnson295189b2012-06-20 16:38:30 -07003294void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3295{
3296 hdd_cfg80211_state_t *cfgState;
3297
3298 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3299
3300 if( NULL != cfgState->buf )
3301 {
3302 int rc;
3303 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3304 rc = wait_for_completion_interruptible_timeout(
3305 &pAdapter->tx_action_cnf_event,
3306 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3307 if(!rc)
3308 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003309 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3311 }
3312 }
3313 return;
3314}
Jeff Johnson295189b2012-06-20 16:38:30 -07003315
3316void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3317{
3318 ENTER();
3319 switch ( pAdapter->device_mode )
3320 {
3321 case WLAN_HDD_INFRA_STATION:
3322 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003323 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003324 {
3325 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3326 {
3327 hdd_deinit_tx_rx( pAdapter );
3328 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3329 }
3330
3331 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3332 {
3333 hdd_wmm_adapter_close( pAdapter );
3334 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3335 }
3336
Jeff Johnson295189b2012-06-20 16:38:30 -07003337 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003338#ifdef FEATURE_WLAN_TDLS
3339 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3340 {
3341 wlan_hdd_tdls_exit(pAdapter);
3342 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3343 }
3344#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003345
3346 break;
3347 }
3348
3349 case WLAN_HDD_SOFTAP:
3350 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003352 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003353
3354 hdd_unregister_hostapd(pAdapter);
3355 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003356 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003357 break;
3358 }
3359
3360 case WLAN_HDD_MONITOR:
3361 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003362 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003363 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3364 {
3365 hdd_deinit_tx_rx( pAdapter );
3366 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003368 if(NULL != pAdapterforTx)
3369 {
3370 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3371 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 break;
3373 }
3374
3375
3376 default:
3377 break;
3378 }
3379
3380 EXIT();
3381}
3382
3383void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3384{
3385 struct net_device *pWlanDev = pAdapter->dev;
3386
3387 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3388 if( rtnl_held )
3389 {
3390 unregister_netdevice(pWlanDev);
3391 }
3392 else
3393 {
3394 unregister_netdev(pWlanDev);
3395 }
3396 // note that the pAdapter is no longer valid at this point
3397 // since the memory has been reclaimed
3398 }
3399
3400}
3401
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003402void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3403{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303404 VOS_STATUS status;
3405 hdd_adapter_t *pAdapter = NULL;
3406 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003407
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303408 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003409
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303410 /*loop through all adapters.*/
3411 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003412 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303413 pAdapter = pAdapterNode->pAdapter;
3414 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3415 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003416
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303417 { // we skip this registration for modes other than STA and P2P client modes.
3418 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3419 pAdapterNode = pNext;
3420 continue;
3421 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003422
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303423 //Apply Dynamic DTIM For P2P
3424 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3425 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3426 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3427 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3428 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3429 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3430 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3431 (eConnectionState_Associated ==
3432 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3433 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3434 {
3435 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003436
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303437 powerRequest.uIgnoreDTIM = 1;
3438 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3439
3440 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3441 {
3442 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3443 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3444 }
3445 else
3446 {
3447 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3448 }
3449
3450 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3451 * specified during Enter/Exit BMPS when LCD off*/
3452 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3453 NULL, eANI_BOOLEAN_FALSE);
3454 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3455 NULL, eANI_BOOLEAN_FALSE);
3456
3457 /* switch to the DTIM specified in cfg.ini */
3458 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3459 "Switch to DTIM %d", powerRequest.uListenInterval);
3460 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3461 break;
3462
3463 }
3464
3465 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3466 pAdapterNode = pNext;
3467 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003468}
3469
3470void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3471{
3472 /*Switch back to DTIM 1*/
3473 tSirSetPowerParamsReq powerRequest = { 0 };
3474
3475 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3476 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003477 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003478
3479 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3480 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3481 NULL, eANI_BOOLEAN_FALSE);
3482 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3483 NULL, eANI_BOOLEAN_FALSE);
3484
3485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3486 "Switch to DTIM%d",powerRequest.uListenInterval);
3487 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3488
3489}
3490
Jeff Johnson295189b2012-06-20 16:38:30 -07003491VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3492{
3493 VOS_STATUS status = VOS_STATUS_SUCCESS;
3494
3495 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3496 {
3497 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3498 }
3499
3500 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3501 {
3502 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3503 }
3504
3505 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3506 {
3507 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3508 }
3509
3510 return status;
3511}
3512
3513VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3514{
3515 hdd_adapter_t *pAdapter = NULL;
3516 eHalStatus halStatus;
3517 VOS_STATUS status = VOS_STATUS_E_INVAL;
3518 v_BOOL_t disableBmps = FALSE;
3519 v_BOOL_t disableImps = FALSE;
3520
3521 switch(session_type)
3522 {
3523 case WLAN_HDD_INFRA_STATION:
3524 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 case WLAN_HDD_P2P_CLIENT:
3526 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003527 //Exit BMPS -> Is Sta/P2P Client is already connected
3528 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3529 if((NULL != pAdapter)&&
3530 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3531 {
3532 disableBmps = TRUE;
3533 }
3534
3535 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3536 if((NULL != pAdapter)&&
3537 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3538 {
3539 disableBmps = TRUE;
3540 }
3541
3542 //Exit both Bmps and Imps incase of Go/SAP Mode
3543 if((WLAN_HDD_SOFTAP == session_type) ||
3544 (WLAN_HDD_P2P_GO == session_type))
3545 {
3546 disableBmps = TRUE;
3547 disableImps = TRUE;
3548 }
3549
3550 if(TRUE == disableImps)
3551 {
3552 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3553 {
3554 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3555 }
3556 }
3557
3558 if(TRUE == disableBmps)
3559 {
3560 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3561 {
3562 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3563
3564 if(eHAL_STATUS_SUCCESS != halStatus)
3565 {
3566 status = VOS_STATUS_E_FAILURE;
3567 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3568 VOS_ASSERT(0);
3569 return status;
3570 }
3571 }
3572
3573 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3574 {
3575 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3576
3577 if(eHAL_STATUS_SUCCESS != halStatus)
3578 {
3579 status = VOS_STATUS_E_FAILURE;
3580 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3581 VOS_ASSERT(0);
3582 return status;
3583 }
3584 }
3585 }
3586
3587 if((TRUE == disableBmps) ||
3588 (TRUE == disableImps))
3589 {
3590 /* Now, get the chip into Full Power now */
3591 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3592 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3593 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3594
3595 if(halStatus != eHAL_STATUS_SUCCESS)
3596 {
3597 if(halStatus == eHAL_STATUS_PMC_PENDING)
3598 {
3599 //Block on a completion variable. Can't wait forever though
3600 wait_for_completion_interruptible_timeout(
3601 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3602 }
3603 else
3604 {
3605 status = VOS_STATUS_E_FAILURE;
3606 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3607 VOS_ASSERT(0);
3608 return status;
3609 }
3610 }
3611
3612 status = VOS_STATUS_SUCCESS;
3613 }
3614
3615 break;
3616 }
3617 return status;
3618}
3619
3620hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003621 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003622 tANI_U8 rtnl_held )
3623{
3624 hdd_adapter_t *pAdapter = NULL;
3625 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3626 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3627 VOS_STATUS exitbmpsStatus;
3628
3629 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3630
3631 //Disable BMPS incase of Concurrency
3632 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3633
3634 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3635 {
3636 //Fail to Exit BMPS
3637 VOS_ASSERT(0);
3638 return NULL;
3639 }
3640
3641 switch(session_type)
3642 {
3643 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003644 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003645 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003646 {
3647 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3648
3649 if( NULL == pAdapter )
3650 return NULL;
3651
Jeff Johnsone7245742012-09-05 17:12:55 -07003652 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3653 NL80211_IFTYPE_P2P_CLIENT:
3654 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003655
Jeff Johnson295189b2012-06-20 16:38:30 -07003656 pAdapter->device_mode = session_type;
3657
3658 status = hdd_init_station_mode( pAdapter );
3659 if( VOS_STATUS_SUCCESS != status )
3660 goto err_free_netdev;
3661
3662 status = hdd_register_interface( pAdapter, rtnl_held );
3663 if( VOS_STATUS_SUCCESS != status )
3664 {
3665 hdd_deinit_adapter(pHddCtx, pAdapter);
3666 goto err_free_netdev;
3667 }
3668 //Stop the Interface TX queue.
3669 netif_tx_disable(pAdapter->dev);
3670 //netif_tx_disable(pWlanDev);
3671 netif_carrier_off(pAdapter->dev);
3672
3673 break;
3674 }
3675
Jeff Johnson295189b2012-06-20 16:38:30 -07003676 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003677 case WLAN_HDD_SOFTAP:
3678 {
3679 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3680 if( NULL == pAdapter )
3681 return NULL;
3682
Jeff Johnson295189b2012-06-20 16:38:30 -07003683 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3684 NL80211_IFTYPE_AP:
3685 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003686 pAdapter->device_mode = session_type;
3687
3688 status = hdd_init_ap_mode(pAdapter);
3689 if( VOS_STATUS_SUCCESS != status )
3690 goto err_free_netdev;
3691
3692 status = hdd_register_hostapd( pAdapter, rtnl_held );
3693 if( VOS_STATUS_SUCCESS != status )
3694 {
3695 hdd_deinit_adapter(pHddCtx, pAdapter);
3696 goto err_free_netdev;
3697 }
3698
3699 netif_tx_disable(pAdapter->dev);
3700 netif_carrier_off(pAdapter->dev);
3701
3702 hdd_set_conparam( 1 );
3703 break;
3704 }
3705 case WLAN_HDD_MONITOR:
3706 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003707 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3708 if( NULL == pAdapter )
3709 return NULL;
3710
3711 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3712 pAdapter->device_mode = session_type;
3713 status = hdd_register_interface( pAdapter, rtnl_held );
3714#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3715 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3716#else
3717 pAdapter->dev->open = hdd_mon_open;
3718 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3719#endif
3720 hdd_init_tx_rx( pAdapter );
3721 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3722 //Set adapter to be used for data tx. It will use either GO or softap.
3723 pAdapter->sessionCtx.monitor.pAdapterForTx =
3724 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003725 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3726 {
3727 pAdapter->sessionCtx.monitor.pAdapterForTx =
3728 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3729 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003730 /* This workqueue will be used to transmit management packet over
3731 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003732 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3733 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3734 return NULL;
3735 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003736
Jeff Johnson295189b2012-06-20 16:38:30 -07003737 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3738 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 }
3740 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003741 case WLAN_HDD_FTM:
3742 {
3743 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3744
3745 if( NULL == pAdapter )
3746 return NULL;
3747 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3748 * message while loading driver in FTM mode. */
3749 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3750 pAdapter->device_mode = session_type;
3751 status = hdd_register_interface( pAdapter, rtnl_held );
3752 }
3753 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 default:
3755 {
3756 VOS_ASSERT(0);
3757 return NULL;
3758 }
3759 }
3760
3761
3762 if( VOS_STATUS_SUCCESS == status )
3763 {
3764 //Add it to the hdd's session list.
3765 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3766 if( NULL == pHddAdapterNode )
3767 {
3768 status = VOS_STATUS_E_NOMEM;
3769 }
3770 else
3771 {
3772 pHddAdapterNode->pAdapter = pAdapter;
3773 status = hdd_add_adapter_back ( pHddCtx,
3774 pHddAdapterNode );
3775 }
3776 }
3777
3778 if( VOS_STATUS_SUCCESS != status )
3779 {
3780 if( NULL != pAdapter )
3781 {
3782 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3783 pAdapter = NULL;
3784 }
3785 if( NULL != pHddAdapterNode )
3786 {
3787 vos_mem_free( pHddAdapterNode );
3788 }
3789
3790 goto resume_bmps;
3791 }
3792
3793 if(VOS_STATUS_SUCCESS == status)
3794 {
3795 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3796
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003797 //Initialize the WoWL service
3798 if(!hdd_init_wowl(pAdapter))
3799 {
3800 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3801 goto err_free_netdev;
3802 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003803 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 return pAdapter;
3805
3806err_free_netdev:
3807 free_netdev(pAdapter->dev);
3808 wlan_hdd_release_intf_addr( pHddCtx,
3809 pAdapter->macAddressCurrent.bytes );
3810
3811resume_bmps:
3812 //If bmps disabled enable it
3813 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3814 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303815 if (pHddCtx->hdd_wlan_suspended)
3816 {
3817 hdd_set_pwrparams(pHddCtx);
3818 }
3819 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 }
3821 return NULL;
3822}
3823
3824VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3825 tANI_U8 rtnl_held )
3826{
3827 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3828 VOS_STATUS status;
3829
3830 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3831 if( VOS_STATUS_SUCCESS != status )
3832 return status;
3833
3834 while ( pCurrent->pAdapter != pAdapter )
3835 {
3836 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3837 if( VOS_STATUS_SUCCESS != status )
3838 break;
3839
3840 pCurrent = pNext;
3841 }
3842 pAdapterNode = pCurrent;
3843 if( VOS_STATUS_SUCCESS == status )
3844 {
3845 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3846 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3847 hdd_remove_adapter( pHddCtx, pAdapterNode );
3848 vos_mem_free( pAdapterNode );
3849
Jeff Johnson295189b2012-06-20 16:38:30 -07003850
3851 /* If there is a single session of STA/P2P client, re-enable BMPS */
3852 if ((!vos_concurrent_sessions_running()) &&
3853 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3854 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3855 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303856 if (pHddCtx->hdd_wlan_suspended)
3857 {
3858 hdd_set_pwrparams(pHddCtx);
3859 }
3860 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003861 }
3862
3863 return VOS_STATUS_SUCCESS;
3864 }
3865
3866 return VOS_STATUS_E_FAILURE;
3867}
3868
3869VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3870{
3871 hdd_adapter_list_node_t *pHddAdapterNode;
3872 VOS_STATUS status;
3873
3874 ENTER();
3875
3876 do
3877 {
3878 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3879 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3880 {
3881 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3882 vos_mem_free( pHddAdapterNode );
3883 }
3884 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3885
3886 EXIT();
3887
3888 return VOS_STATUS_SUCCESS;
3889}
3890
3891void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3892{
3893 v_U8_t addIE[1] = {0};
3894
3895 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3896 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3897 eANI_BOOLEAN_FALSE) )
3898 {
3899 hddLog(LOGE,
3900 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3901 }
3902
3903 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3904 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3905 eANI_BOOLEAN_FALSE) )
3906 {
3907 hddLog(LOGE,
3908 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3909 }
3910
3911 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3912 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3913 eANI_BOOLEAN_FALSE) )
3914 {
3915 hddLog(LOGE,
3916 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3917 }
3918}
3919
3920VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3921{
3922 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3923 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3924 union iwreq_data wrqu;
3925
3926 ENTER();
3927
3928 switch(pAdapter->device_mode)
3929 {
3930 case WLAN_HDD_INFRA_STATION:
3931 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003932 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003933 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3934 {
3935 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3936 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3937 pAdapter->sessionId,
3938 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3939 else
3940 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3941 pAdapter->sessionId,
3942 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3943 //success implies disconnect command got queued up successfully
3944 if(halStatus == eHAL_STATUS_SUCCESS)
3945 {
3946 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3947 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3948 }
3949 memset(&wrqu, '\0', sizeof(wrqu));
3950 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3951 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3952 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3953 }
3954 else
3955 {
3956 hdd_abort_mac_scan(pHddCtx);
3957 }
3958
3959 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3960 {
3961 INIT_COMPLETION(pAdapter->session_close_comp_var);
3962 if (eHAL_STATUS_SUCCESS ==
3963 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3964 hdd_smeCloseSessionCallback, pAdapter))
3965 {
3966 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003967 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003968 &pAdapter->session_close_comp_var,
3969 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3970 }
3971 }
3972
3973 break;
3974
3975 case WLAN_HDD_SOFTAP:
3976 case WLAN_HDD_P2P_GO:
3977 //Any softap specific cleanup here...
3978 mutex_lock(&pHddCtx->sap_lock);
3979 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3980 {
3981 VOS_STATUS status;
3982 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3983
3984 //Stop Bss.
3985 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3986 if (VOS_IS_STATUS_SUCCESS(status))
3987 {
3988 hdd_hostapd_state_t *pHostapdState =
3989 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3990
3991 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3992
3993 if (!VOS_IS_STATUS_SUCCESS(status))
3994 {
3995 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003996 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003997 }
3998 }
3999 else
4000 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004001 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004002 }
4003 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4004
4005 if (eHAL_STATUS_FAILURE ==
4006 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4007 0, NULL, eANI_BOOLEAN_FALSE))
4008 {
4009 hddLog(LOGE,
4010 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004011 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004012 }
4013
4014 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4015 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4016 eANI_BOOLEAN_FALSE) )
4017 {
4018 hddLog(LOGE,
4019 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4020 }
4021
4022 // Reset WNI_CFG_PROBE_RSP Flags
4023 wlan_hdd_reset_prob_rspies(pAdapter);
4024 kfree(pAdapter->sessionCtx.ap.beacon);
4025 pAdapter->sessionCtx.ap.beacon = NULL;
4026 }
4027 mutex_unlock(&pHddCtx->sap_lock);
4028 break;
4029 case WLAN_HDD_MONITOR:
4030 break;
4031 default:
4032 break;
4033 }
4034
4035 EXIT();
4036 return VOS_STATUS_SUCCESS;
4037}
4038
4039VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4040{
4041 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4042 VOS_STATUS status;
4043 hdd_adapter_t *pAdapter;
4044
4045 ENTER();
4046
4047 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4048
4049 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4050 {
4051 pAdapter = pAdapterNode->pAdapter;
4052 netif_tx_disable(pAdapter->dev);
4053 netif_carrier_off(pAdapter->dev);
4054
4055 hdd_stop_adapter( pHddCtx, pAdapter );
4056
4057 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4058 pAdapterNode = pNext;
4059 }
4060
4061 EXIT();
4062
4063 return VOS_STATUS_SUCCESS;
4064}
4065
4066VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4067{
4068 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4069 VOS_STATUS status;
4070 hdd_adapter_t *pAdapter;
4071
4072 ENTER();
4073
4074 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4075
4076 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4077 {
4078 pAdapter = pAdapterNode->pAdapter;
4079 netif_tx_disable(pAdapter->dev);
4080 netif_carrier_off(pAdapter->dev);
4081
4082 //Record whether STA is associated
4083 pAdapter->sessionCtx.station.bSendDisconnect =
4084 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
4085 VOS_TRUE : VOS_FALSE;
4086
4087 hdd_deinit_tx_rx(pAdapter);
4088 hdd_wmm_adapter_close(pAdapter);
4089
4090 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4091 pAdapterNode = pNext;
4092 }
4093
4094 EXIT();
4095
4096 return VOS_STATUS_SUCCESS;
4097}
4098
4099VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4100{
4101 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4102 VOS_STATUS status;
4103 hdd_adapter_t *pAdapter;
4104 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
4105
4106 ENTER();
4107
4108 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4109
4110 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4111 {
4112 pAdapter = pAdapterNode->pAdapter;
4113
4114 switch(pAdapter->device_mode)
4115 {
4116 case WLAN_HDD_INFRA_STATION:
4117 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004118 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 hdd_init_station_mode(pAdapter);
4120 /* Open the gates for HDD to receive Wext commands */
4121 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004122 pHddCtx->scan_info.mScanPending = FALSE;
4123 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004124
4125 //Trigger the initial scan
4126 hdd_wlan_initial_scan(pAdapter);
4127
4128 //Indicate disconnect event to supplicant if associated previously
4129 if(pAdapter->sessionCtx.station.bSendDisconnect)
4130 {
4131 union iwreq_data wrqu;
4132 memset(&wrqu, '\0', sizeof(wrqu));
4133 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4134 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4135 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4136 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
4137
Jeff Johnson295189b2012-06-20 16:38:30 -07004138 /* indicate disconnected event to nl80211 */
4139 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4140 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004141 }
4142 break;
4143
4144 case WLAN_HDD_SOFTAP:
4145 /* softAP can handle SSR */
4146 break;
4147
4148 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4150 __func__);
4151 /* event supplicant to restart */
4152 cfg80211_del_sta(pAdapter->dev,
4153 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004154 break;
4155
4156 case WLAN_HDD_MONITOR:
4157 /* monitor interface start */
4158 break;
4159 default:
4160 break;
4161 }
4162
4163 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4164 pAdapterNode = pNext;
4165 }
4166
4167 EXIT();
4168
4169 return VOS_STATUS_SUCCESS;
4170}
4171
4172VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4173{
4174 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4175 hdd_adapter_t *pAdapter;
4176 VOS_STATUS status;
4177 v_U32_t roamId;
4178
4179 ENTER();
4180
4181 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4182
4183 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4184 {
4185 pAdapter = pAdapterNode->pAdapter;
4186
4187 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4188 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4189 {
4190 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4191 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4192
4193 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4194 init_completion(&pAdapter->disconnect_comp_var);
4195 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4196 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4197
4198 wait_for_completion_interruptible_timeout(
4199 &pAdapter->disconnect_comp_var,
4200 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4201
4202 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4203 pHddCtx->isAmpAllowed = VOS_FALSE;
4204 sme_RoamConnect(pHddCtx->hHal,
4205 pAdapter->sessionId, &(pWextState->roamProfile),
4206 &roamId);
4207 }
4208
4209 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4210 pAdapterNode = pNext;
4211 }
4212
4213 EXIT();
4214
4215 return VOS_STATUS_SUCCESS;
4216}
4217
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004218void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4219{
4220 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4221 VOS_STATUS status;
4222 hdd_adapter_t *pAdapter;
4223 hdd_station_ctx_t *pHddStaCtx;
4224 hdd_ap_ctx_t *pHddApCtx;
4225 hdd_hostapd_state_t * pHostapdState;
4226 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4227 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4228 const char *p2pMode = "DEV";
4229 const char *ccMode = "Standalone";
4230 int n;
4231
4232 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4233 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4234 {
4235 pAdapter = pAdapterNode->pAdapter;
4236 switch (pAdapter->device_mode) {
4237 case WLAN_HDD_INFRA_STATION:
4238 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4239 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4240 staChannel = pHddStaCtx->conn_info.operationChannel;
4241 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4242 }
4243 break;
4244 case WLAN_HDD_P2P_CLIENT:
4245 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4246 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4247 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4248 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4249 p2pMode = "CLI";
4250 }
4251 break;
4252 case WLAN_HDD_P2P_GO:
4253 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4254 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4255 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4256 p2pChannel = pHddApCtx->operatingChannel;
4257 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4258 }
4259 p2pMode = "GO";
4260 break;
4261 case WLAN_HDD_SOFTAP:
4262 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4263 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4264 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4265 apChannel = pHddApCtx->operatingChannel;
4266 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4267 }
4268 break;
4269 default:
4270 break;
4271 }
4272 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4273 pAdapterNode = pNext;
4274 }
4275 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4276 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4277 }
4278 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4279 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4280 if (p2pChannel > 0) {
4281 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4282 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4283 }
4284 if (apChannel > 0) {
4285 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4286 apChannel, MAC_ADDR_ARRAY(apBssid));
4287 }
4288
4289 if (p2pChannel > 0 && apChannel > 0) {
4290 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4291 }
4292}
4293
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004294bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004295{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004296 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004297}
4298
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004299/* Once SSR is disabled then it cannot be set. */
4300void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004301{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004302 if (HDD_SSR_DISABLED == isSsrRequired)
4303 return;
4304
Jeff Johnson295189b2012-06-20 16:38:30 -07004305 isSsrRequired = value;
4306}
4307
4308VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4309 hdd_adapter_list_node_t** ppAdapterNode)
4310{
4311 VOS_STATUS status;
4312 spin_lock(&pHddCtx->hddAdapters.lock);
4313 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4314 (hdd_list_node_t**) ppAdapterNode );
4315 spin_unlock(&pHddCtx->hddAdapters.lock);
4316 return status;
4317}
4318
4319VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4320 hdd_adapter_list_node_t* pAdapterNode,
4321 hdd_adapter_list_node_t** pNextAdapterNode)
4322{
4323 VOS_STATUS status;
4324 spin_lock(&pHddCtx->hddAdapters.lock);
4325 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4326 (hdd_list_node_t*) pAdapterNode,
4327 (hdd_list_node_t**)pNextAdapterNode );
4328
4329 spin_unlock(&pHddCtx->hddAdapters.lock);
4330 return status;
4331}
4332
4333VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4334 hdd_adapter_list_node_t* pAdapterNode)
4335{
4336 VOS_STATUS status;
4337 spin_lock(&pHddCtx->hddAdapters.lock);
4338 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4339 &pAdapterNode->node );
4340 spin_unlock(&pHddCtx->hddAdapters.lock);
4341 return status;
4342}
4343
4344VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4345 hdd_adapter_list_node_t** ppAdapterNode)
4346{
4347 VOS_STATUS status;
4348 spin_lock(&pHddCtx->hddAdapters.lock);
4349 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4350 (hdd_list_node_t**) ppAdapterNode );
4351 spin_unlock(&pHddCtx->hddAdapters.lock);
4352 return status;
4353}
4354
4355VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4356 hdd_adapter_list_node_t* pAdapterNode)
4357{
4358 VOS_STATUS status;
4359 spin_lock(&pHddCtx->hddAdapters.lock);
4360 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4361 (hdd_list_node_t*) pAdapterNode );
4362 spin_unlock(&pHddCtx->hddAdapters.lock);
4363 return status;
4364}
4365
4366VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4367 hdd_adapter_list_node_t* pAdapterNode)
4368{
4369 VOS_STATUS status;
4370 spin_lock(&pHddCtx->hddAdapters.lock);
4371 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4372 (hdd_list_node_t*) pAdapterNode );
4373 spin_unlock(&pHddCtx->hddAdapters.lock);
4374 return status;
4375}
4376
4377hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4378 tSirMacAddr macAddr )
4379{
4380 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4381 hdd_adapter_t *pAdapter;
4382 VOS_STATUS status;
4383
4384 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4385
4386 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4387 {
4388 pAdapter = pAdapterNode->pAdapter;
4389
4390 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4391 macAddr, sizeof(tSirMacAddr) ) )
4392 {
4393 return pAdapter;
4394 }
4395 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4396 pAdapterNode = pNext;
4397 }
4398
4399 return NULL;
4400
4401}
4402
4403hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4404{
4405 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4406 hdd_adapter_t *pAdapter;
4407 VOS_STATUS status;
4408
4409 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4410
4411 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4412 {
4413 pAdapter = pAdapterNode->pAdapter;
4414
4415 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4416 IFNAMSIZ ) )
4417 {
4418 return pAdapter;
4419 }
4420 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4421 pAdapterNode = pNext;
4422 }
4423
4424 return NULL;
4425
4426}
4427
4428hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4429{
4430 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4431 hdd_adapter_t *pAdapter;
4432 VOS_STATUS status;
4433
4434 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4435
4436 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4437 {
4438 pAdapter = pAdapterNode->pAdapter;
4439
4440 if( pAdapter && (mode == pAdapter->device_mode) )
4441 {
4442 return pAdapter;
4443 }
4444 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4445 pAdapterNode = pNext;
4446 }
4447
4448 return NULL;
4449
4450}
4451
4452//Remove this function later
4453hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4454{
4455 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4456 hdd_adapter_t *pAdapter;
4457 VOS_STATUS status;
4458
4459 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4460
4461 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4462 {
4463 pAdapter = pAdapterNode->pAdapter;
4464
4465 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4466 {
4467 return pAdapter;
4468 }
4469
4470 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4471 pAdapterNode = pNext;
4472 }
4473
4474 return NULL;
4475
4476}
4477
Jeff Johnson295189b2012-06-20 16:38:30 -07004478/**---------------------------------------------------------------------------
4479
4480 \brief hdd_set_monitor_tx_adapter() -
4481
4482 This API initializes the adapter to be used while transmitting on monitor
4483 adapter.
4484
4485 \param - pHddCtx - Pointer to the HDD context.
4486 pAdapter - Adapter that will used for TX. This can be NULL.
4487 \return - None.
4488 --------------------------------------------------------------------------*/
4489void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4490{
4491 hdd_adapter_t *pMonAdapter;
4492
4493 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4494
4495 if( NULL != pMonAdapter )
4496 {
4497 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4498 }
4499}
Jeff Johnson295189b2012-06-20 16:38:30 -07004500/**---------------------------------------------------------------------------
4501
4502 \brief hdd_select_queue() -
4503
4504 This API returns the operating channel of the requested device mode
4505
4506 \param - pHddCtx - Pointer to the HDD context.
4507 - mode - Device mode for which operating channel is required
4508 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4509 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4510 \return - channel number. "0" id the requested device is not found OR it is not connected.
4511 --------------------------------------------------------------------------*/
4512v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4513{
4514 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4515 VOS_STATUS status;
4516 hdd_adapter_t *pAdapter;
4517 v_U8_t operatingChannel = 0;
4518
4519 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4520
4521 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4522 {
4523 pAdapter = pAdapterNode->pAdapter;
4524
4525 if( mode == pAdapter->device_mode )
4526 {
4527 switch(pAdapter->device_mode)
4528 {
4529 case WLAN_HDD_INFRA_STATION:
4530 case WLAN_HDD_P2P_CLIENT:
4531 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4532 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4533 break;
4534 case WLAN_HDD_SOFTAP:
4535 case WLAN_HDD_P2P_GO:
4536 /*softap connection info */
4537 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4538 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4539 break;
4540 default:
4541 break;
4542 }
4543
4544 break; //Found the device of interest. break the loop
4545 }
4546
4547 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4548 pAdapterNode = pNext;
4549 }
4550 return operatingChannel;
4551}
4552
4553#ifdef WLAN_FEATURE_PACKET_FILTERING
4554/**---------------------------------------------------------------------------
4555
4556 \brief hdd_set_multicast_list() -
4557
4558 This used to set the multicast address list.
4559
4560 \param - dev - Pointer to the WLAN device.
4561 - skb - Pointer to OS packet (sk_buff).
4562 \return - success/fail
4563
4564 --------------------------------------------------------------------------*/
4565static void hdd_set_multicast_list(struct net_device *dev)
4566{
4567 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 int mc_count;
4569 int i = 0;
4570 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304571
4572 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004573 {
4574 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304575 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004576 return;
4577 }
4578
4579 if (dev->flags & IFF_ALLMULTI)
4580 {
4581 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004582 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304583 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004584 }
4585 else
4586 {
4587 mc_count = netdev_mc_count(dev);
4588 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004589 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004590 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4591 {
4592 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004593 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304594 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004595 return;
4596 }
4597
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304598 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004599
4600 netdev_for_each_mc_addr(ha, dev) {
4601 if (i == mc_count)
4602 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304603 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4604 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4605 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004606 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304607 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 i++;
4609 }
4610 }
4611 return;
4612}
4613#endif
4614
4615/**---------------------------------------------------------------------------
4616
4617 \brief hdd_select_queue() -
4618
4619 This function is registered with the Linux OS for network
4620 core to decide which queue to use first.
4621
4622 \param - dev - Pointer to the WLAN device.
4623 - skb - Pointer to OS packet (sk_buff).
4624 \return - ac, Queue Index/access category corresponding to UP in IP header
4625
4626 --------------------------------------------------------------------------*/
4627v_U16_t hdd_select_queue(struct net_device *dev,
4628 struct sk_buff *skb)
4629{
4630 return hdd_wmm_select_queue(dev, skb);
4631}
4632
4633
4634/**---------------------------------------------------------------------------
4635
4636 \brief hdd_wlan_initial_scan() -
4637
4638 This function triggers the initial scan
4639
4640 \param - pAdapter - Pointer to the HDD adapter.
4641
4642 --------------------------------------------------------------------------*/
4643void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4644{
4645 tCsrScanRequest scanReq;
4646 tCsrChannelInfo channelInfo;
4647 eHalStatus halStatus;
4648 unsigned long scanId;
4649 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4650
4651 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4652 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4653 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4654
4655 if(sme_Is11dSupported(pHddCtx->hHal))
4656 {
4657 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4658 if ( HAL_STATUS_SUCCESS( halStatus ) )
4659 {
4660 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4661 if( !scanReq.ChannelInfo.ChannelList )
4662 {
4663 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4664 vos_mem_free(channelInfo.ChannelList);
4665 return;
4666 }
4667 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4668 channelInfo.numOfChannels);
4669 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4670 vos_mem_free(channelInfo.ChannelList);
4671 }
4672
4673 scanReq.scanType = eSIR_PASSIVE_SCAN;
4674 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4675 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4676 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4677 }
4678 else
4679 {
4680 scanReq.scanType = eSIR_ACTIVE_SCAN;
4681 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4682 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4683 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4684 }
4685
4686 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4687 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4688 {
4689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4690 __func__, halStatus );
4691 }
4692
4693 if(sme_Is11dSupported(pHddCtx->hHal))
4694 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4695}
4696
4697struct fullPowerContext
4698{
4699 struct completion completion;
4700 unsigned int magic;
4701};
4702#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4703
4704/**---------------------------------------------------------------------------
4705
4706 \brief hdd_full_power_callback() - HDD full power callback function
4707
4708 This is the function invoked by SME to inform the result of a full power
4709 request issued by HDD
4710
4711 \param - callbackcontext - Pointer to cookie
4712 \param - status - result of request
4713
4714 \return - None
4715
4716 --------------------------------------------------------------------------*/
4717static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4718{
4719 struct fullPowerContext *pContext = callbackContext;
4720
4721 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304722 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004723
4724 if (NULL == callbackContext)
4725 {
4726 hddLog(VOS_TRACE_LEVEL_ERROR,
4727 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004728 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004729 return;
4730 }
4731
4732 /* there is a race condition that exists between this callback function
4733 and the caller since the caller could time out either before or
4734 while this code is executing. we'll assume the timeout hasn't
4735 occurred, but we'll verify that right before we save our work */
4736
4737 if (POWER_CONTEXT_MAGIC != pContext->magic)
4738 {
4739 /* the caller presumably timed out so there is nothing we can do */
4740 hddLog(VOS_TRACE_LEVEL_WARN,
4741 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004742 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004743 return;
4744 }
4745
4746 /* the race is on. caller could have timed out immediately after
4747 we verified the magic, but if so, caller will wait a short time
4748 for us to notify the caller, so the context will stay valid */
4749 complete(&pContext->completion);
4750}
4751
4752/**---------------------------------------------------------------------------
4753
4754 \brief hdd_wlan_exit() - HDD WLAN exit function
4755
4756 This is the driver exit point (invoked during rmmod)
4757
4758 \param - pHddCtx - Pointer to the HDD Context
4759
4760 \return - None
4761
4762 --------------------------------------------------------------------------*/
4763void hdd_wlan_exit(hdd_context_t *pHddCtx)
4764{
4765 eHalStatus halStatus;
4766 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4767 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304768 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004770 struct fullPowerContext powerContext;
4771 long lrc;
4772
4773 ENTER();
4774
Jeff Johnson88ba7742013-02-27 14:36:02 -08004775 if (VOS_FTM_MODE != hdd_get_conparam())
4776 {
4777 // Unloading, restart logic is no more required.
4778 wlan_hdd_restart_deinit(pHddCtx);
4779 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004782 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004783 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004784 {
4785 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4786 WLAN_HDD_INFRA_STATION);
4787 if (pAdapter == NULL)
4788 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4789
4790 if (pAdapter != NULL)
4791 {
4792 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4793 hdd_UnregisterWext(pAdapter->dev);
4794 }
4795 }
4796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004797
Jeff Johnson295189b2012-06-20 16:38:30 -07004798 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004799 {
4800 wlan_hdd_ftm_close(pHddCtx);
4801 goto free_hdd_ctx;
4802 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004803 //Stop the Interface TX queue.
4804 //netif_tx_disable(pWlanDev);
4805 //netif_carrier_off(pWlanDev);
4806
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4808 {
4809 pAdapter = hdd_get_adapter(pHddCtx,
4810 WLAN_HDD_SOFTAP);
4811 }
4812 else
4813 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004814 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 {
4816 pAdapter = hdd_get_adapter(pHddCtx,
4817 WLAN_HDD_INFRA_STATION);
4818 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 /* DeRegister with platform driver as client for Suspend/Resume */
4821 vosStatus = hddDeregisterPmOps(pHddCtx);
4822 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4823 {
4824 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4825 VOS_ASSERT(0);
4826 }
4827
4828 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4829 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4830 {
4831 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004833
4834 // Cancel any outstanding scan requests. We are about to close all
4835 // of our adapters, but an adapter structure is what SME passes back
4836 // to our callback function. Hence if there are any outstanding scan
4837 // requests then there is a race condition between when the adapter
4838 // is closed and when the callback is invoked. We try to resolve that
4839 // race condition here by canceling any outstanding scans before we
4840 // close the adapters.
4841 // Note that the scans may be cancelled in an asynchronous manner, so
4842 // ideally there needs to be some kind of synchronization. Rather than
4843 // introduce a new synchronization here, we will utilize the fact that
4844 // we are about to Request Full Power, and since that is synchronized,
4845 // the expectation is that by the time Request Full Power has completed,
4846 // all scans will be cancelled.
4847 hdd_abort_mac_scan( pHddCtx );
4848
4849 //Disable IMPS/BMPS as we do not want the device to enter any power
4850 //save mode during shutdown
4851 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4852 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4853 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4854
4855 //Ensure that device is in full power as we will touch H/W during vos_Stop
4856 init_completion(&powerContext.completion);
4857 powerContext.magic = POWER_CONTEXT_MAGIC;
4858
4859 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4860 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4861
4862 if (eHAL_STATUS_SUCCESS != halStatus)
4863 {
4864 if (eHAL_STATUS_PMC_PENDING == halStatus)
4865 {
4866 /* request was sent -- wait for the response */
4867 lrc = wait_for_completion_interruptible_timeout(
4868 &powerContext.completion,
4869 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4870 /* either we have a response or we timed out
4871 either way, first invalidate our magic */
4872 powerContext.magic = 0;
4873 if (lrc <= 0)
4874 {
4875 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004876 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 /* there is a race condition such that the callback
4878 function could be executing at the same time we are. of
4879 primary concern is if the callback function had already
4880 verified the "magic" but hasn't yet set the completion
4881 variable. Since the completion variable is on our
4882 stack, we'll delay just a bit to make sure the data is
4883 still valid if that is the case */
4884 msleep(50);
4885 }
4886 }
4887 else
4888 {
4889 hddLog(VOS_TRACE_LEVEL_ERROR,
4890 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004891 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 VOS_ASSERT(0);
4893 /* continue -- need to clean up as much as possible */
4894 }
4895 }
4896
4897 // Unregister the Net Device Notifier
4898 unregister_netdevice_notifier(&hdd_netdev_notifier);
4899
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 hdd_stop_all_adapters( pHddCtx );
4901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902#ifdef WLAN_BTAMP_FEATURE
4903 vosStatus = WLANBAP_Stop(pVosContext);
4904 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4905 {
4906 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4907 "%s: Failed to stop BAP",__func__);
4908 }
4909#endif //WLAN_BTAMP_FEATURE
4910
4911 //Stop all the modules
4912 vosStatus = vos_stop( pVosContext );
4913 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4914 {
4915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4916 "%s: Failed to stop VOSS",__func__);
4917 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4918 }
4919
Jeff Johnson295189b2012-06-20 16:38:30 -07004920 //Assert Deep sleep signal now to put Libra HW in lowest power state
4921 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4922 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4923
4924 //Vote off any PMIC voltage supplies
4925 vos_chipPowerDown(NULL, NULL, NULL);
4926
4927 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4928
4929 //Clean up HDD Nlink Service
4930 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4931 nl_srv_exit();
4932
4933 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004934 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004935
4936 //Close the scheduler before calling vos_close to make sure no thread is
4937 // scheduled after the each module close is called i.e after all the data
4938 // structures are freed.
4939 vosStatus = vos_sched_close( pVosContext );
4940 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4941 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4942 "%s: Failed to close VOSS Scheduler",__func__);
4943 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4944 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004945#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004946#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4947 /* Destroy the wake lock */
4948 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4949#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004950 /* Destroy the wake lock */
4951 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004952#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004953
4954 //Close VOSS
4955 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4956 vos_close(pVosContext);
4957
Jeff Johnson295189b2012-06-20 16:38:30 -07004958 //Close Watchdog
4959 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4960 vos_watchdog_close(pVosContext);
4961
4962 /* Cancel the vote for XO Core ON.
4963 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4964 * exited at this point
4965 */
4966 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4967 " when WLAN is turned OFF\n");
4968 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4969 {
4970 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4971 " Not returning failure."
4972 " Power consumed will be high\n");
4973 }
4974
4975 hdd_close_all_adapters( pHddCtx );
4976
4977
4978 //Free up dynamically allocated members inside HDD Adapter
4979 kfree(pHddCtx->cfg_ini);
4980 pHddCtx->cfg_ini= NULL;
4981
4982 /* free the power on lock from platform driver */
4983 if (free_riva_power_on_lock("wlan"))
4984 {
4985 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4986 __func__);
4987 }
4988
Jeff Johnson88ba7742013-02-27 14:36:02 -08004989free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004990 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004991 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 if (hdd_is_ssr_required())
4993 {
4994 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004995 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004996 msleep(5000);
4997 }
4998 hdd_set_ssr_required (VOS_FALSE);
4999}
5000
5001
5002/**---------------------------------------------------------------------------
5003
5004 \brief hdd_update_config_from_nv() - Function to update the contents of
5005 the running configuration with parameters taken from NV storage
5006
5007 \param - pHddCtx - Pointer to the HDD global context
5008
5009 \return - VOS_STATUS_SUCCESS if successful
5010
5011 --------------------------------------------------------------------------*/
5012static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5013{
Jeff Johnson295189b2012-06-20 16:38:30 -07005014 v_BOOL_t itemIsValid = VOS_FALSE;
5015 VOS_STATUS status;
5016 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5017 v_U8_t macLoop;
5018
5019 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5020 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5021 if(status != VOS_STATUS_SUCCESS)
5022 {
5023 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5024 return VOS_STATUS_E_FAILURE;
5025 }
5026
5027 if (itemIsValid == VOS_TRUE)
5028 {
5029 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5030 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5031 VOS_MAX_CONCURRENCY_PERSONA);
5032 if(status != VOS_STATUS_SUCCESS)
5033 {
5034 /* Get MAC from NV fail, not update CFG info
5035 * INI MAC value will be used for MAC setting */
5036 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5037 return VOS_STATUS_E_FAILURE;
5038 }
5039
5040 /* If first MAC is not valid, treat all others are not valid
5041 * Then all MACs will be got from ini file */
5042 if(vos_is_macaddr_zero(&macFromNV[0]))
5043 {
5044 /* MAC address in NV file is not configured yet */
5045 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5046 return VOS_STATUS_E_INVAL;
5047 }
5048
5049 /* Get MAC address from NV, update CFG info */
5050 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5051 {
5052 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5053 {
5054 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5055 /* This MAC is not valid, skip it
5056 * This MAC will be got from ini file */
5057 }
5058 else
5059 {
5060 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5061 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5062 VOS_MAC_ADDR_SIZE);
5063 }
5064 }
5065 }
5066 else
5067 {
5068 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5069 return VOS_STATUS_E_FAILURE;
5070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005071
Jeff Johnson295189b2012-06-20 16:38:30 -07005072
5073 return VOS_STATUS_SUCCESS;
5074}
5075
5076/**---------------------------------------------------------------------------
5077
5078 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5079
5080 \param - pAdapter - Pointer to the HDD
5081
5082 \return - None
5083
5084 --------------------------------------------------------------------------*/
5085VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5086{
5087 eHalStatus halStatus;
5088 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305089 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005090
Jeff Johnson295189b2012-06-20 16:38:30 -07005091
5092 // Send ready indication to the HDD. This will kick off the MAC
5093 // into a 'running' state and should kick off an initial scan.
5094 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5095 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5096 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305097 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 "code %08d [x%08x]",__func__, halStatus, halStatus );
5099 return VOS_STATUS_E_FAILURE;
5100 }
5101
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305102 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5104 // And RIVA will crash
5105 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5106 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305107 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5108 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5109
5110
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 return VOS_STATUS_SUCCESS;
5112}
5113
Jeff Johnson295189b2012-06-20 16:38:30 -07005114/* wake lock APIs for HDD */
5115void hdd_prevent_suspend(void)
5116{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005117#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005119#else
5120 wcnss_prevent_suspend();
5121#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005122}
5123
5124void hdd_allow_suspend(void)
5125{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005126#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005127 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005128#else
5129 wcnss_allow_suspend();
5130#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005131}
5132
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005133void hdd_allow_suspend_timeout(v_U32_t timeout)
5134{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005135#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005136 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005137#else
5138 /* Do nothing as there is no API in wcnss for timeout*/
5139#endif
5140}
5141
Jeff Johnson295189b2012-06-20 16:38:30 -07005142/**---------------------------------------------------------------------------
5143
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005144 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5145 information between Host and Riva
5146
5147 This function gets reported version of FW
5148 It also finds the version of Riva headers used to compile the host
5149 It compares the above two and prints a warning if they are different
5150 It gets the SW and HW version string
5151 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5152 indicating the features they support through a bitmap
5153
5154 \param - pHddCtx - Pointer to HDD context
5155
5156 \return - void
5157
5158 --------------------------------------------------------------------------*/
5159
5160void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5161{
5162
5163 tSirVersionType versionCompiled;
5164 tSirVersionType versionReported;
5165 tSirVersionString versionString;
5166 tANI_U8 fwFeatCapsMsgSupported = 0;
5167 VOS_STATUS vstatus;
5168
5169 /* retrieve and display WCNSS version information */
5170 do {
5171
5172 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5173 &versionCompiled);
5174 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5175 {
5176 hddLog(VOS_TRACE_LEVEL_FATAL,
5177 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005178 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005179 break;
5180 }
5181
5182 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5183 &versionReported);
5184 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5185 {
5186 hddLog(VOS_TRACE_LEVEL_FATAL,
5187 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005188 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005189 break;
5190 }
5191
5192 if ((versionCompiled.major != versionReported.major) ||
5193 (versionCompiled.minor != versionReported.minor) ||
5194 (versionCompiled.version != versionReported.version) ||
5195 (versionCompiled.revision != versionReported.revision))
5196 {
5197 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5198 "Host expected %u.%u.%u.%u\n",
5199 WLAN_MODULE_NAME,
5200 (int)versionReported.major,
5201 (int)versionReported.minor,
5202 (int)versionReported.version,
5203 (int)versionReported.revision,
5204 (int)versionCompiled.major,
5205 (int)versionCompiled.minor,
5206 (int)versionCompiled.version,
5207 (int)versionCompiled.revision);
5208 }
5209 else
5210 {
5211 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5212 WLAN_MODULE_NAME,
5213 (int)versionReported.major,
5214 (int)versionReported.minor,
5215 (int)versionReported.version,
5216 (int)versionReported.revision);
5217 }
5218
5219 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5220 versionString,
5221 sizeof(versionString));
5222 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5223 {
5224 hddLog(VOS_TRACE_LEVEL_FATAL,
5225 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005226 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005227 break;
5228 }
5229
5230 pr_info("%s: WCNSS software version %s\n",
5231 WLAN_MODULE_NAME, versionString);
5232
5233 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5234 versionString,
5235 sizeof(versionString));
5236 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5237 {
5238 hddLog(VOS_TRACE_LEVEL_FATAL,
5239 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005240 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005241 break;
5242 }
5243
5244 pr_info("%s: WCNSS hardware version %s\n",
5245 WLAN_MODULE_NAME, versionString);
5246
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005247 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5248 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005249 send the message only if it the riva is 1.1
5250 minor numbers for different riva branches:
5251 0 -> (1.0)Mainline Build
5252 1 -> (1.1)Mainline Build
5253 2->(1.04) Stability Build
5254 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005255 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005256 ((versionReported.minor>=1) && (versionReported.version>=1)))
5257 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5258 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005259
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005260 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005261 {
5262#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5263 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5264 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5265#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005266 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005267 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005268
5269 } while (0);
5270
5271}
5272
5273/**---------------------------------------------------------------------------
5274
Jeff Johnson295189b2012-06-20 16:38:30 -07005275 \brief hdd_wlan_startup() - HDD init function
5276
5277 This is the driver startup code executed once a WLAN device has been detected
5278
5279 \param - dev - Pointer to the underlying device
5280
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005281 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005282
5283 --------------------------------------------------------------------------*/
5284
5285int hdd_wlan_startup(struct device *dev )
5286{
5287 VOS_STATUS status;
5288 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005289 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 hdd_context_t *pHddCtx = NULL;
5291 v_CONTEXT_t pVosContext= NULL;
5292#ifdef WLAN_BTAMP_FEATURE
5293 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5294 WLANBAP_ConfigType btAmpConfig;
5295 hdd_config_t *pConfig;
5296#endif
5297 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005299
5300 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 /*
5302 * cfg80211: wiphy allocation
5303 */
5304 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5305
5306 if(wiphy == NULL)
5307 {
5308 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005309 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005310 }
5311
5312 pHddCtx = wiphy_priv(wiphy);
5313
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 //Initialize the adapter context to zeros.
5315 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5316
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 hdd_prevent_suspend();
5319 pHddCtx->isLoadUnloadInProgress = TRUE;
5320
5321 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5322
5323 /*Get vos context here bcoz vos_open requires it*/
5324 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5325
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005326 if(pVosContext == NULL)
5327 {
5328 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5329 goto err_free_hdd_context;
5330 }
5331
Jeff Johnson295189b2012-06-20 16:38:30 -07005332 //Save the Global VOSS context in adapter context for future.
5333 pHddCtx->pvosContext = pVosContext;
5334
5335 //Save the adapter context in global context for future.
5336 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5337
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 pHddCtx->parent_dev = dev;
5339
5340 init_completion(&pHddCtx->full_pwr_comp_var);
5341 init_completion(&pHddCtx->standby_comp_var);
5342 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005343 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005344 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005345
5346 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5347
5348 // Load all config first as TL config is needed during vos_open
5349 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5350 if(pHddCtx->cfg_ini == NULL)
5351 {
5352 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5353 goto err_free_hdd_context;
5354 }
5355
5356 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5357
5358 // Read and parse the qcom_cfg.ini file
5359 status = hdd_parse_config_ini( pHddCtx );
5360 if ( VOS_STATUS_SUCCESS != status )
5361 {
5362 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5363 __func__, WLAN_INI_FILE);
5364 goto err_config;
5365 }
5366
Jeff Johnson295189b2012-06-20 16:38:30 -07005367 /*
5368 * cfg80211: Initialization and registration ...
5369 */
5370 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5371 {
5372 hddLog(VOS_TRACE_LEVEL_FATAL,
5373 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5374 goto err_wiphy_reg;
5375 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005376
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005377 // Update VOS trace levels based upon the cfg.ini
5378 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5379 pHddCtx->cfg_ini->vosTraceEnableBAP);
5380 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5381 pHddCtx->cfg_ini->vosTraceEnableTL);
5382 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5383 pHddCtx->cfg_ini->vosTraceEnableWDI);
5384 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5385 pHddCtx->cfg_ini->vosTraceEnableHDD);
5386 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5387 pHddCtx->cfg_ini->vosTraceEnableSME);
5388 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5389 pHddCtx->cfg_ini->vosTraceEnablePE);
5390 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5391 pHddCtx->cfg_ini->vosTraceEnableWDA);
5392 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5393 pHddCtx->cfg_ini->vosTraceEnableSYS);
5394 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5395 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005396 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5397 pHddCtx->cfg_ini->vosTraceEnableSAP);
5398 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5399 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005400
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 // Update WDI trace levels based upon the cfg.ini
5402 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5403 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5404 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5405 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5406 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5407 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5408 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5409 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005410
Jeff Johnson88ba7742013-02-27 14:36:02 -08005411 if (VOS_FTM_MODE == hdd_get_conparam())
5412 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5414 {
5415 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5416 goto err_free_hdd_context;
5417 }
5418 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5419 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005420 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005421
Jeff Johnson88ba7742013-02-27 14:36:02 -08005422 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005423 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5424 {
5425 status = vos_watchdog_open(pVosContext,
5426 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5427
5428 if(!VOS_IS_STATUS_SUCCESS( status ))
5429 {
5430 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005431 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 }
5433 }
5434
5435 pHddCtx->isLogpInProgress = FALSE;
5436 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5437
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5439 if(!VOS_IS_STATUS_SUCCESS(status))
5440 {
5441 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 }
5444
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 status = vos_open( &pVosContext, 0);
5446 if ( !VOS_IS_STATUS_SUCCESS( status ))
5447 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005448 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5449 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005450 }
5451
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5453
5454 if ( NULL == pHddCtx->hHal )
5455 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005456 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 goto err_vosclose;
5458 }
5459
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005460 status = vos_preStart( pHddCtx->pvosContext );
5461 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5462 {
5463 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5464 goto err_vosclose;
5465 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005466
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005467 /* Note that the vos_preStart() sequence triggers the cfg download.
5468 The cfg download must occur before we update the SME config
5469 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 status = hdd_set_sme_config( pHddCtx );
5471
5472 if ( VOS_STATUS_SUCCESS != status )
5473 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005474 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5475 goto err_vosclose;
5476 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005477
5478 //Initialize the WMM module
5479 status = hdd_wmm_init(pHddCtx);
5480 if (!VOS_IS_STATUS_SUCCESS(status))
5481 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005482 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 goto err_vosclose;
5484 }
5485
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 /* In the integrated architecture we update the configuration from
5487 the INI file and from NV before vOSS has been started so that
5488 the final contents are available to send down to the cCPU */
5489
5490 // Apply the cfg.ini to cfg.dat
5491 if (FALSE == hdd_update_config_dat(pHddCtx))
5492 {
5493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5494 goto err_vosclose;
5495 }
5496
5497 // Apply the NV to cfg.dat
5498 /* Prima Update MAC address only at here */
5499 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5500 {
5501#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5502 /* There was not a valid set of MAC Addresses in NV. See if the
5503 default addresses were modified by the cfg.ini settings. If so,
5504 we'll use them, but if not, we'll autogenerate a set of MAC
5505 addresses based upon the device serial number */
5506
5507 static const v_MACADDR_t default_address =
5508 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5509 unsigned int serialno;
5510 int i;
5511
5512 serialno = wcnss_get_serial_number();
5513 if ((0 != serialno) &&
5514 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5515 sizeof(default_address))))
5516 {
5517 /* cfg.ini has the default address, invoke autogen logic */
5518
5519 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5520 bytes of the serial number that can be used to generate
5521 the other 3 bytes of the MAC address. Mask off all but
5522 the lower 3 bytes (this will also make sure we don't
5523 overflow in the next step) */
5524 serialno &= 0x00FFFFFF;
5525
5526 /* we need a unique address for each session */
5527 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5528
5529 /* autogen all addresses */
5530 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5531 {
5532 /* start with the entire default address */
5533 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5534 /* then replace the lower 3 bytes */
5535 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5536 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5537 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5538
5539 serialno++;
5540 }
5541
5542 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5543 MAC_ADDRESS_STR,
5544 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5545 }
5546 else
5547#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5548 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005549 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 "%s: Invalid MAC address in NV, using MAC from ini file "
5551 MAC_ADDRESS_STR, __func__,
5552 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5553 }
5554 }
5555 {
5556 eHalStatus halStatus;
5557 // Set the MAC Address
5558 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5559 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5560 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5561 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5562
5563 if (!HAL_STATUS_SUCCESS( halStatus ))
5564 {
5565 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5566 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005567 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 }
5569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005570
5571 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5572 Note: Firmware image will be read and downloaded inside vos_start API */
5573 status = vos_start( pHddCtx->pvosContext );
5574 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5575 {
5576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5577 goto err_vosclose;
5578 }
5579
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005580 /* Exchange capability info between Host and FW and also get versioning info from FW */
5581 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005582
5583 status = hdd_post_voss_start_config( pHddCtx );
5584 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5585 {
5586 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5587 __func__);
5588 goto err_vosstop;
5589 }
5590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5592 {
5593 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5594 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5595 }
5596 else
5597 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5599 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5600 if (pAdapter != NULL)
5601 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305602 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305604 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5605 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5606 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005607
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305608 /* Generate the P2P Device Address. This consists of the device's
5609 * primary MAC address with the locally administered bit set.
5610 */
5611 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005612 }
5613 else
5614 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305615 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5616 if (p2p_dev_addr != NULL)
5617 {
5618 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5619 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5620 }
5621 else
5622 {
5623 hddLog(VOS_TRACE_LEVEL_FATAL,
5624 "%s: Failed to allocate mac_address for p2p_device",
5625 __func__);
5626 goto err_close_adapter;
5627 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005629
5630 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5631 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5632 if ( NULL == pP2pAdapter )
5633 {
5634 hddLog(VOS_TRACE_LEVEL_FATAL,
5635 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005636 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005637 goto err_close_adapter;
5638 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005639 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005640 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005641
5642 if( pAdapter == NULL )
5643 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005644 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5645 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005647
Jeff Johnson295189b2012-06-20 16:38:30 -07005648#ifdef WLAN_BTAMP_FEATURE
5649 vStatus = WLANBAP_Open(pVosContext);
5650 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5651 {
5652 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5653 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005654 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 }
5656
5657 vStatus = BSL_Init(pVosContext);
5658 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5659 {
5660 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5661 "%s: Failed to Init BSL",__func__);
5662 goto err_bap_close;
5663 }
5664 vStatus = WLANBAP_Start(pVosContext);
5665 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5666 {
5667 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5668 "%s: Failed to start TL",__func__);
5669 goto err_bap_close;
5670 }
5671
5672 pConfig = pHddCtx->cfg_ini;
5673 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5674 status = WLANBAP_SetConfig(&btAmpConfig);
5675
5676#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005677
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005678#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5679 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5680 {
5681 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5682 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5683 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5684 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5685 }
5686#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005687#ifdef FEATURE_WLAN_SCAN_PNO
5688 /*SME must send channel update configuration to RIVA*/
5689 sme_UpdateChannelConfig(pHddCtx->hHal);
5690#endif
5691
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 /* Register with platform driver as client for Suspend/Resume */
5693 status = hddRegisterPmOps(pHddCtx);
5694 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5695 {
5696 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5697#ifdef WLAN_BTAMP_FEATURE
5698 goto err_bap_stop;
5699#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005700 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005701#endif //WLAN_BTAMP_FEATURE
5702 }
5703
5704 /* Register TM level change handler function to the platform */
5705 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5706 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5707 {
5708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5709 goto err_unregister_pmops;
5710 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005711
5712 /* register for riva power on lock to platform driver */
5713 if (req_riva_power_on_lock("wlan"))
5714 {
5715 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5716 __func__);
5717 goto err_unregister_pmops;
5718 }
5719
Jeff Johnson295189b2012-06-20 16:38:30 -07005720 // register net device notifier for device change notification
5721 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5722
5723 if(ret < 0)
5724 {
5725 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5726 goto err_free_power_on_lock;
5727 }
5728
5729 //Initialize the nlink service
5730 if(nl_srv_init() != 0)
5731 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305732 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 goto err_reg_netdev;
5734 }
5735
5736 //Initialize the BTC service
5737 if(btc_activate_service(pHddCtx) != 0)
5738 {
5739 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5740 goto err_nl_srv;
5741 }
5742
5743#ifdef PTT_SOCK_SVC_ENABLE
5744 //Initialize the PTT service
5745 if(ptt_sock_activate_svc(pHddCtx) != 0)
5746 {
5747 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5748 goto err_nl_srv;
5749 }
5750#endif
5751
Jeff Johnson295189b2012-06-20 16:38:30 -07005752 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005755 /* Action frame registered in one adapter which will
5756 * applicable to all interfaces
5757 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005758 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005760
5761 mutex_init(&pHddCtx->sap_lock);
5762
5763 pHddCtx->isLoadUnloadInProgress = FALSE;
5764
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005765#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005766#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5767 /* Initialize the wake lcok */
5768 wake_lock_init(&pHddCtx->rx_wake_lock,
5769 WAKE_LOCK_SUSPEND,
5770 "qcom_rx_wakelock");
5771#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005772 /* Initialize the wake lcok */
5773 wake_lock_init(&pHddCtx->sap_wake_lock,
5774 WAKE_LOCK_SUSPEND,
5775 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005776#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005777
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005778 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5779 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005780
5781 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5782 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005783
5784 // Initialize the restart logic
5785 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305786
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 goto success;
5788
5789err_nl_srv:
5790 nl_srv_exit();
5791
5792err_reg_netdev:
5793 unregister_netdevice_notifier(&hdd_netdev_notifier);
5794
5795err_free_power_on_lock:
5796 free_riva_power_on_lock("wlan");
5797
5798err_unregister_pmops:
5799 hddDevTmUnregisterNotifyCallback(pHddCtx);
5800 hddDeregisterPmOps(pHddCtx);
5801
5802#ifdef WLAN_BTAMP_FEATURE
5803err_bap_stop:
5804 WLANBAP_Stop(pVosContext);
5805#endif
5806
5807#ifdef WLAN_BTAMP_FEATURE
5808err_bap_close:
5809 WLANBAP_Close(pVosContext);
5810#endif
5811
Jeff Johnson295189b2012-06-20 16:38:30 -07005812err_close_adapter:
5813 hdd_close_all_adapters( pHddCtx );
5814
5815err_vosstop:
5816 vos_stop(pVosContext);
5817
5818err_vosclose:
5819 status = vos_sched_close( pVosContext );
5820 if (!VOS_IS_STATUS_SUCCESS(status)) {
5821 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5822 "%s: Failed to close VOSS Scheduler", __func__);
5823 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5824 }
5825 vos_close(pVosContext );
5826
Jeff Johnson295189b2012-06-20 16:38:30 -07005827err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005828 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005829
5830err_wdclose:
5831 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5832 vos_watchdog_close(pVosContext);
5833
Jeff Johnson295189b2012-06-20 16:38:30 -07005834err_wiphy_reg:
5835 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005836
5837err_config:
5838 kfree(pHddCtx->cfg_ini);
5839 pHddCtx->cfg_ini= NULL;
5840
5841err_free_hdd_context:
5842 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 wiphy_free(wiphy) ;
5844 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 VOS_BUG(1);
5846
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005847 if (hdd_is_ssr_required())
5848 {
5849 /* WDI timeout had happened during load, so SSR is needed here */
5850 subsystem_restart("wcnss");
5851 msleep(5000);
5852 }
5853 hdd_set_ssr_required (VOS_FALSE);
5854
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005855 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005856
5857success:
5858 EXIT();
5859 return 0;
5860}
5861
5862/**---------------------------------------------------------------------------
5863
Jeff Johnson32d95a32012-09-10 13:15:23 -07005864 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005865
Jeff Johnson32d95a32012-09-10 13:15:23 -07005866 This is the driver entry point - called in different timeline depending
5867 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005868
5869 \param - None
5870
5871 \return - 0 for success, non zero for failure
5872
5873 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005874static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005875{
5876 VOS_STATUS status;
5877 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 struct device *dev = NULL;
5879 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005880#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5881 int max_retries = 0;
5882#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005883
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305884#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5885 vos_wconn_trace_init();
5886#endif
5887
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 ENTER();
5889
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005890#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005892#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005893
5894 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5895 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5896
5897 //Power Up Libra WLAN card first if not already powered up
5898 status = vos_chipPowerUp(NULL,NULL,NULL);
5899 if (!VOS_IS_STATUS_SUCCESS(status))
5900 {
5901 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5902 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005903 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 }
5905
Jeff Johnson295189b2012-06-20 16:38:30 -07005906#ifdef ANI_BUS_TYPE_PCI
5907
5908 dev = wcnss_wlan_get_device();
5909
5910#endif // ANI_BUS_TYPE_PCI
5911
5912#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005913
5914#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5915 /* wait until WCNSS driver downloads NV */
5916 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5917 msleep(1000);
5918 }
5919 if (max_retries >= 5) {
5920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5921 return -ENODEV;
5922 }
5923#endif
5924
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 dev = wcnss_wlan_get_device();
5926#endif // ANI_BUS_TYPE_PLATFORM
5927
5928
5929 do {
5930 if (NULL == dev) {
5931 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5932 ret_status = -1;
5933 break;
5934 }
5935
5936#ifdef MEMORY_DEBUG
5937 vos_mem_init();
5938#endif
5939
5940#ifdef TIMER_MANAGER
5941 vos_timer_manager_init();
5942#endif
5943
5944 /* Preopen VOSS so that it is ready to start at least SAL */
5945 status = vos_preOpen(&pVosContext);
5946
5947 if (!VOS_IS_STATUS_SUCCESS(status))
5948 {
5949 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5950 ret_status = -1;
5951 break;
5952 }
5953
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005954#ifndef MODULE
5955 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5956 */
5957 hdd_set_conparam((v_UINT_t)con_mode);
5958#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005959
5960 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005961 if (hdd_wlan_startup(dev))
5962 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005964 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 vos_preClose( &pVosContext );
5966 ret_status = -1;
5967 break;
5968 }
5969
5970 /* Cancel the vote for XO Core ON
5971 * This is done here for safety purposes in case we re-initialize without turning
5972 * it OFF in any error scenario.
5973 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005974 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005975 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005976 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005977 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5978 {
5979 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5980 " Power consumed will be high\n");
5981 }
5982 } while (0);
5983
5984 if (0 != ret_status)
5985 {
5986 //Assert Deep sleep signal now to put Libra HW in lowest power state
5987 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5988 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5989
5990 //Vote off any PMIC voltage supplies
5991 vos_chipPowerDown(NULL, NULL, NULL);
5992#ifdef TIMER_MANAGER
5993 vos_timer_exit();
5994#endif
5995#ifdef MEMORY_DEBUG
5996 vos_mem_exit();
5997#endif
5998
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005999#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006001#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6003 }
6004 else
6005 {
6006 //Send WLAN UP indication to Nlink Service
6007 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6008
6009 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6010
6011 }
6012
6013 EXIT();
6014
6015 return ret_status;
6016}
6017
Jeff Johnson32d95a32012-09-10 13:15:23 -07006018/**---------------------------------------------------------------------------
6019
6020 \brief hdd_module_init() - Init Function
6021
6022 This is the driver entry point (invoked when module is loaded using insmod)
6023
6024 \param - None
6025
6026 \return - 0 for success, non zero for failure
6027
6028 --------------------------------------------------------------------------*/
6029#ifdef MODULE
6030static int __init hdd_module_init ( void)
6031{
6032 return hdd_driver_init();
6033}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006034#else /* #ifdef MODULE */
6035static int __init hdd_module_init ( void)
6036{
6037 /* Driver initialization is delayed to fwpath_changed_handler */
6038 return 0;
6039}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006040#endif /* #ifdef MODULE */
6041
Jeff Johnson295189b2012-06-20 16:38:30 -07006042
6043/**---------------------------------------------------------------------------
6044
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006045 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006046
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006047 This is the driver exit point (invoked when module is unloaded using rmmod
6048 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006049
6050 \param - None
6051
6052 \return - None
6053
6054 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006055static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006056{
6057 hdd_context_t *pHddCtx = NULL;
6058 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006059
6060 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6061
6062 //Get the global vos context
6063 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6064
6065 if(!pVosContext)
6066 {
6067 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6068 goto done;
6069 }
6070
6071 //Get the HDD context.
6072 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6073
6074 if(!pHddCtx)
6075 {
6076 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6077 }
6078 else
6079 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006080 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006082 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6083 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 }
6085
6086 pHddCtx->isLoadUnloadInProgress = TRUE;
6087 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6088
6089 //Do all the cleanup before deregistering the driver
6090 hdd_wlan_exit(pHddCtx);
6091 }
6092
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 vos_preClose( &pVosContext );
6094
6095#ifdef TIMER_MANAGER
6096 vos_timer_exit();
6097#endif
6098#ifdef MEMORY_DEBUG
6099 vos_mem_exit();
6100#endif
6101
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306102#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6103 vos_wconn_trace_exit();
6104#endif
6105
Jeff Johnson295189b2012-06-20 16:38:30 -07006106done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006107#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006110 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6111}
6112
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006113/**---------------------------------------------------------------------------
6114
6115 \brief hdd_module_exit() - Exit function
6116
6117 This is the driver exit point (invoked when module is unloaded using rmmod)
6118
6119 \param - None
6120
6121 \return - None
6122
6123 --------------------------------------------------------------------------*/
6124static void __exit hdd_module_exit(void)
6125{
6126 hdd_driver_exit();
6127}
6128
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006129#ifdef MODULE
6130static int fwpath_changed_handler(const char *kmessage,
6131 struct kernel_param *kp)
6132{
Jeff Johnson76052702013-04-16 13:55:05 -07006133 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006134}
6135
6136static int con_mode_handler(const char *kmessage,
6137 struct kernel_param *kp)
6138{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006139 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006140}
6141#else /* #ifdef MODULE */
6142/**---------------------------------------------------------------------------
6143
Jeff Johnson76052702013-04-16 13:55:05 -07006144 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006145
Jeff Johnson76052702013-04-16 13:55:05 -07006146 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006147 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006148 - invoked when module parameter fwpath is modified from userspace to signal
6149 initializing the WLAN driver or when con_mode is modified from userspace
6150 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006151
6152 \return - 0 for success, non zero for failure
6153
6154 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006155static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006156{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006157 int ret_status;
6158
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006159 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006160 ret_status = hdd_driver_init();
6161 wlan_hdd_inited = ret_status ? 0 : 1;
6162 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006163 }
6164
6165 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006166
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006167 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006168
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006169 ret_status = hdd_driver_init();
6170 wlan_hdd_inited = ret_status ? 0 : 1;
6171 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006172}
6173
Jeff Johnson295189b2012-06-20 16:38:30 -07006174/**---------------------------------------------------------------------------
6175
Jeff Johnson76052702013-04-16 13:55:05 -07006176 \brief fwpath_changed_handler() - Handler Function
6177
6178 Handle changes to the fwpath parameter
6179
6180 \return - 0 for success, non zero for failure
6181
6182 --------------------------------------------------------------------------*/
6183static int fwpath_changed_handler(const char *kmessage,
6184 struct kernel_param *kp)
6185{
6186 int ret;
6187
6188 ret = param_set_copystring(kmessage, kp);
6189 if (0 == ret)
6190 ret = kickstart_driver();
6191 return ret;
6192}
6193
6194/**---------------------------------------------------------------------------
6195
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006196 \brief con_mode_handler() -
6197
6198 Handler function for module param con_mode when it is changed by userspace
6199 Dynamically linked - do nothing
6200 Statically linked - exit and init driver, as in rmmod and insmod
6201
Jeff Johnson76052702013-04-16 13:55:05 -07006202 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006203
Jeff Johnson76052702013-04-16 13:55:05 -07006204 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006205
6206 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006207static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006208{
Jeff Johnson76052702013-04-16 13:55:05 -07006209 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006210
Jeff Johnson76052702013-04-16 13:55:05 -07006211 ret = param_set_int(kmessage, kp);
6212 if (0 == ret)
6213 ret = kickstart_driver();
6214 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006215}
6216#endif /* #ifdef MODULE */
6217
6218/**---------------------------------------------------------------------------
6219
Jeff Johnson295189b2012-06-20 16:38:30 -07006220 \brief hdd_get_conparam() -
6221
6222 This is the driver exit point (invoked when module is unloaded using rmmod)
6223
6224 \param - None
6225
6226 \return - tVOS_CON_MODE
6227
6228 --------------------------------------------------------------------------*/
6229tVOS_CON_MODE hdd_get_conparam ( void )
6230{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006231#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006233#else
6234 return (tVOS_CON_MODE)curr_con_mode;
6235#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006236}
6237void hdd_set_conparam ( v_UINT_t newParam )
6238{
6239 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006240#ifndef MODULE
6241 curr_con_mode = con_mode;
6242#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006243}
6244/**---------------------------------------------------------------------------
6245
6246 \brief hdd_softap_sta_deauth() - function
6247
6248 This to take counter measure to handle deauth req from HDD
6249
6250 \param - pAdapter - Pointer to the HDD
6251
6252 \param - enable - boolean value
6253
6254 \return - None
6255
6256 --------------------------------------------------------------------------*/
6257
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006258VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006259{
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006261 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006262
6263 ENTER();
6264
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306265 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006266
6267 //Ignore request to deauth bcmc station
6268 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006269 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006270
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006271 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006272
6273 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006274 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006275}
6276
6277/**---------------------------------------------------------------------------
6278
6279 \brief hdd_softap_sta_disassoc() - function
6280
6281 This to take counter measure to handle deauth req from HDD
6282
6283 \param - pAdapter - Pointer to the HDD
6284
6285 \param - enable - boolean value
6286
6287 \return - None
6288
6289 --------------------------------------------------------------------------*/
6290
6291void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6292{
6293 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6294
6295 ENTER();
6296
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306297 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
6299 //Ignore request to disassoc bcmc station
6300 if( pDestMacAddress[0] & 0x1 )
6301 return;
6302
6303 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6304}
6305
6306void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6307{
6308 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6309
6310 ENTER();
6311
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306312 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006313
6314 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6315}
6316
Jeff Johnson295189b2012-06-20 16:38:30 -07006317/**---------------------------------------------------------------------------
6318 *
6319 * \brief hdd_get__concurrency_mode() -
6320 *
6321 *
6322 * \param - None
6323 *
6324 * \return - CONCURRENCY MODE
6325 *
6326 * --------------------------------------------------------------------------*/
6327tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6328{
6329 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6330 hdd_context_t *pHddCtx;
6331
6332 if (NULL != pVosContext)
6333 {
6334 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6335 if (NULL != pHddCtx)
6336 {
6337 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6338 }
6339 }
6340
6341 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006342 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006343 return VOS_STA;
6344}
6345
6346/* Decide whether to allow/not the apps power collapse.
6347 * Allow apps power collapse if we are in connected state.
6348 * if not, allow only if we are in IMPS */
6349v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6350{
6351 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006352 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006353 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006354 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6355 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6356 hdd_adapter_t *pAdapter = NULL;
6357 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006358 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006359
Jeff Johnson295189b2012-06-20 16:38:30 -07006360 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6361 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006362
Yathish9f22e662012-12-10 14:21:35 -08006363 concurrent_state = hdd_get_concurrency_mode();
6364
6365#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6366 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6367 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6368 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6369 return TRUE;
6370#endif
6371
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 /*loop through all adapters. TBD fix for Concurrency */
6373 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6374 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6375 {
6376 pAdapter = pAdapterNode->pAdapter;
6377 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6378 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6379 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006380 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006382 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006383 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6384 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006385 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006386 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006387 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6388 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 return FALSE;
6390 }
6391 }
6392 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6393 pAdapterNode = pNext;
6394 }
6395 return TRUE;
6396}
6397
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006398/* Decides whether to send suspend notification to Riva
6399 * if any adapter is in BMPS; then it is required */
6400v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6401{
6402 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6403 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6404
6405 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6406 {
6407 return TRUE;
6408 }
6409 return FALSE;
6410}
6411
Jeff Johnson295189b2012-06-20 16:38:30 -07006412void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6413{
6414 switch(mode)
6415 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006416 case VOS_STA_MODE:
6417 case VOS_P2P_CLIENT_MODE:
6418 case VOS_P2P_GO_MODE:
6419 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006420 pHddCtx->concurrency_mode |= (1 << mode);
6421 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006422 break;
6423 default:
6424 break;
6425
6426 }
6427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6428 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6429}
6430
6431
6432void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6433{
6434 switch(mode)
6435 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006436 case VOS_STA_MODE:
6437 case VOS_P2P_CLIENT_MODE:
6438 case VOS_P2P_GO_MODE:
6439 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006440 pHddCtx->no_of_sessions[mode]--;
6441 if (!(pHddCtx->no_of_sessions[mode]))
6442 pHddCtx->concurrency_mode &= (~(1 << mode));
6443 break;
6444 default:
6445 break;
6446 }
6447 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6448 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6449}
6450
Jeff Johnsone7245742012-09-05 17:12:55 -07006451/**---------------------------------------------------------------------------
6452 *
6453 * \brief wlan_hdd_restart_init
6454 *
6455 * This function initalizes restart timer/flag. An internal function.
6456 *
6457 * \param - pHddCtx
6458 *
6459 * \return - None
6460 *
6461 * --------------------------------------------------------------------------*/
6462
6463static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6464{
6465 /* Initialize */
6466 pHddCtx->hdd_restart_retries = 0;
6467 atomic_set(&pHddCtx->isRestartInProgress, 0);
6468 vos_timer_init(&pHddCtx->hdd_restart_timer,
6469 VOS_TIMER_TYPE_SW,
6470 wlan_hdd_restart_timer_cb,
6471 pHddCtx);
6472}
6473/**---------------------------------------------------------------------------
6474 *
6475 * \brief wlan_hdd_restart_deinit
6476 *
6477 * This function cleans up the resources used. An internal function.
6478 *
6479 * \param - pHddCtx
6480 *
6481 * \return - None
6482 *
6483 * --------------------------------------------------------------------------*/
6484
6485static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6486{
6487
6488 VOS_STATUS vos_status;
6489 /* Block any further calls */
6490 atomic_set(&pHddCtx->isRestartInProgress, 1);
6491 /* Cleanup */
6492 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6493 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006494 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006495 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6496 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006497 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006498
6499}
6500
6501/**---------------------------------------------------------------------------
6502 *
6503 * \brief wlan_hdd_framework_restart
6504 *
6505 * This function uses a cfg80211 API to start a framework initiated WLAN
6506 * driver module unload/load.
6507 *
6508 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6509 *
6510 *
6511 * \param - pHddCtx
6512 *
6513 * \return - VOS_STATUS_SUCCESS: Success
6514 * VOS_STATUS_E_EMPTY: Adapter is Empty
6515 * VOS_STATUS_E_NOMEM: No memory
6516
6517 * --------------------------------------------------------------------------*/
6518
6519static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6520{
6521 VOS_STATUS status = VOS_STATUS_SUCCESS;
6522 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006523 int len = (sizeof (struct ieee80211_mgmt));
6524 struct ieee80211_mgmt *mgmt = NULL;
6525
6526 /* Prepare the DEAUTH managment frame with reason code */
6527 mgmt = kzalloc(len, GFP_KERNEL);
6528 if(mgmt == NULL)
6529 {
6530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6531 "%s: memory allocation failed (%d bytes)", __func__, len);
6532 return VOS_STATUS_E_NOMEM;
6533 }
6534 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006535
6536 /* Iterate over all adapters/devices */
6537 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6538 do
6539 {
6540 if( (status == VOS_STATUS_SUCCESS) &&
6541 pAdapterNode &&
6542 pAdapterNode->pAdapter)
6543 {
6544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6545 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6546 pAdapterNode->pAdapter->dev->name,
6547 pAdapterNode->pAdapter->device_mode,
6548 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006549 /*
6550 * CFG80211 event to restart the driver
6551 *
6552 * 'cfg80211_send_unprot_deauth' sends a
6553 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6554 * of SME(Linux Kernel) state machine.
6555 *
6556 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6557 * the driver.
6558 *
6559 */
6560
6561 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006562 }
6563 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6564 pAdapterNode = pNext;
6565 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6566
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006567
6568 /* Free the allocated management frame */
6569 kfree(mgmt);
6570
Jeff Johnsone7245742012-09-05 17:12:55 -07006571 /* Retry until we unload or reach max count */
6572 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6573 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6574
6575 return status;
6576
6577}
6578/**---------------------------------------------------------------------------
6579 *
6580 * \brief wlan_hdd_restart_timer_cb
6581 *
6582 * Restart timer callback. An internal function.
6583 *
6584 * \param - User data:
6585 *
6586 * \return - None
6587 *
6588 * --------------------------------------------------------------------------*/
6589
6590void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6591{
6592 hdd_context_t *pHddCtx = usrDataForCallback;
6593 wlan_hdd_framework_restart(pHddCtx);
6594 return;
6595
6596}
6597
6598
6599/**---------------------------------------------------------------------------
6600 *
6601 * \brief wlan_hdd_restart_driver
6602 *
6603 * This function sends an event to supplicant to restart the WLAN driver.
6604 *
6605 * This function is called from vos_wlanRestart.
6606 *
6607 * \param - pHddCtx
6608 *
6609 * \return - VOS_STATUS_SUCCESS: Success
6610 * VOS_STATUS_E_EMPTY: Adapter is Empty
6611 * VOS_STATUS_E_ALREADY: Request already in progress
6612
6613 * --------------------------------------------------------------------------*/
6614VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6615{
6616 VOS_STATUS status = VOS_STATUS_SUCCESS;
6617
6618 /* A tight check to make sure reentrancy */
6619 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6620 {
6621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6622 "%s: WLAN restart is already in progress", __func__);
6623
6624 return VOS_STATUS_E_ALREADY;
6625 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006626 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006627#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006628 wcnss_reset_intr();
6629#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006630
Jeff Johnsone7245742012-09-05 17:12:55 -07006631 return status;
6632}
6633
6634
Jeff Johnson295189b2012-06-20 16:38:30 -07006635//Register the module init/exit functions
6636module_init(hdd_module_init);
6637module_exit(hdd_module_exit);
6638
6639MODULE_LICENSE("Dual BSD/GPL");
6640MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6641MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6642
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006643module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6644 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006645
Jeff Johnson76052702013-04-16 13:55:05 -07006646module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006647 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);