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