blob: 37a5e277c370d088e50ac37ff192bfa6fcc0bec5 [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
1335 /* Fill BSSID (STA mac address) */
1336 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1337
1338 /* Fill source address (STA mac address) */
1339 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1340
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;
1705
1706 hdd_station_ctx_t *pHddStaCtx = NULL;
1707 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1708 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1709
1710 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1711
1712 /* Reassoc command is allowed only if WES mode is enabled */
1713 if (!wesMode)
1714 {
1715 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1716 ret = -EINVAL;
1717 goto exit;
1718 }
1719
1720 /* if not associated, no need to proceed with reassoc */
1721 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1722 {
1723 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1724 ret = -EINVAL;
1725 goto exit;
1726 }
1727
1728 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1729 if (eHAL_STATUS_SUCCESS != status)
1730 {
1731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1732 "%s: Failed to parse reassoc command data", __func__);
1733 ret = -EINVAL;
1734 goto exit;
1735 }
1736
1737 /* if the target bssid is same as currently associated AP,
1738 then no need to proceed with reassoc */
1739 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1740 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1741 {
1742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1743 ret = -EINVAL;
1744 goto exit;
1745 }
1746
1747 /* Check channel number is a valid channel number */
1748 if(VOS_STATUS_SUCCESS !=
1749 wlan_hdd_validate_operation_channel(pAdapter, channel))
1750 {
1751 hddLog(VOS_TRACE_LEVEL_ERROR,
1752 "%s: Invalid Channel [%d] \n", __func__, channel);
1753 return -EINVAL;
1754 }
1755
1756 /* Proceed with reassoc */
1757 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001758#endif
1759#ifdef FEATURE_WLAN_LFR
1760 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1761 {
1762 tANI_U8 *value = command;
1763 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1764
1765 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1766 value = value + 12;
1767 /* Convert the value from ascii to integer */
1768 ret = kstrtou8(value, 10, &lfrMode);
1769 if (ret < 0)
1770 {
1771 /* If the input value is greater than max value of datatype, then also
1772 kstrtou8 fails */
1773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1774 "%s: kstrtou8 failed range [%d - %d]", __func__,
1775 CFG_LFR_FEATURE_ENABLED_MIN,
1776 CFG_LFR_FEATURE_ENABLED_MAX);
1777 ret = -EINVAL;
1778 goto exit;
1779 }
1780
1781 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1782 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1783 {
1784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1785 "lfr mode value %d is out of range"
1786 " (Min: %d Max: %d)", lfrMode,
1787 CFG_LFR_FEATURE_ENABLED_MIN,
1788 CFG_LFR_FEATURE_ENABLED_MAX);
1789 ret = -EINVAL;
1790 goto exit;
1791 }
1792
1793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1794 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1795
1796 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1797 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1798 }
1799#endif
1800#ifdef WLAN_FEATURE_VOWIFI_11R
1801 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1802 {
1803 tANI_U8 *value = command;
1804 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1805
1806 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1807 value = value + 18;
1808 /* Convert the value from ascii to integer */
1809 ret = kstrtou8(value, 10, &ft);
1810 if (ret < 0)
1811 {
1812 /* If the input value is greater than max value of datatype, then also
1813 kstrtou8 fails */
1814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1815 "%s: kstrtou8 failed range [%d - %d]", __func__,
1816 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1817 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1818 ret = -EINVAL;
1819 goto exit;
1820 }
1821
1822 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1823 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1824 {
1825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1826 "ft mode value %d is out of range"
1827 " (Min: %d Max: %d)", ft,
1828 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1829 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1830 ret = -EINVAL;
1831 goto exit;
1832 }
1833
1834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1835 "%s: Received Command to change ft mode = %d", __func__, ft);
1836
1837 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1838 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1839 }
1840#endif
1841#ifdef FEATURE_WLAN_CCX
1842 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1843 {
1844 tANI_U8 *value = command;
1845 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1846
1847 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1848 value = value + 11;
1849 /* Convert the value from ascii to integer */
1850 ret = kstrtou8(value, 10, &ccxMode);
1851 if (ret < 0)
1852 {
1853 /* If the input value is greater than max value of datatype, then also
1854 kstrtou8 fails */
1855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1856 "%s: kstrtou8 failed range [%d - %d]", __func__,
1857 CFG_CCX_FEATURE_ENABLED_MIN,
1858 CFG_CCX_FEATURE_ENABLED_MAX);
1859 ret = -EINVAL;
1860 goto exit;
1861 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001862 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1863 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1864 {
1865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1866 "Ccx mode value %d is out of range"
1867 " (Min: %d Max: %d)", ccxMode,
1868 CFG_CCX_FEATURE_ENABLED_MIN,
1869 CFG_CCX_FEATURE_ENABLED_MAX);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1874 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1875
1876 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1877 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1878 }
1879#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001880 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1881 {
1882 tANI_U8 *value = command;
1883 tANI_BOOLEAN roamScanControl = 0;
1884
1885 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1886 value = value + 19;
1887 /* Convert the value from ascii to integer */
1888 ret = kstrtou8(value, 10, &roamScanControl);
1889 if (ret < 0)
1890 {
1891 /* If the input value is greater than max value of datatype, then also
1892 kstrtou8 fails */
1893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1894 "%s: kstrtou8 failed ", __func__);
1895 ret = -EINVAL;
1896 goto exit;
1897 }
1898
1899 if (0 != roamScanControl)
1900 {
1901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1902 "roam scan control invalid value = %d",
1903 roamScanControl);
1904 ret = -EINVAL;
1905 goto exit;
1906 }
1907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1908 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1909
1910 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1911 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001912#ifdef FEATURE_WLAN_OKC
1913 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1914 {
1915 tANI_U8 *value = command;
1916 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1917
1918 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1919 value = value + 11;
1920 /* Convert the value from ascii to integer */
1921 ret = kstrtou8(value, 10, &okcMode);
1922 if (ret < 0)
1923 {
1924 /* If the input value is greater than max value of datatype, then also
1925 kstrtou8 fails */
1926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1927 "%s: kstrtou8 failed range [%d - %d]", __func__,
1928 CFG_OKC_FEATURE_ENABLED_MIN,
1929 CFG_OKC_FEATURE_ENABLED_MAX);
1930 ret = -EINVAL;
1931 goto exit;
1932 }
1933
1934 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1935 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1936 {
1937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1938 "Okc mode value %d is out of range"
1939 " (Min: %d Max: %d)", okcMode,
1940 CFG_OKC_FEATURE_ENABLED_MIN,
1941 CFG_OKC_FEATURE_ENABLED_MAX);
1942 ret = -EINVAL;
1943 goto exit;
1944 }
1945
1946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1947 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1948
1949 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1950 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001951 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1952 {
1953 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1954 char extra[32];
1955 tANI_U8 len = 0;
1956
1957 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1958 if (copy_to_user(priv_data.buf, &extra, len + 1))
1959 {
1960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1961 "%s: failed to copy data to user buffer", __func__);
1962 ret = -EFAULT;
1963 goto exit;
1964 }
1965 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001966#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001967 else {
1968 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1969 __func__, command);
1970 }
1971
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 }
1973exit:
1974 if (command)
1975 {
1976 kfree(command);
1977 }
1978 return ret;
1979}
1980
Srinivas Girigowdade697412013-02-14 16:31:48 -08001981#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1982void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1983{
1984 eCsrBand band = -1;
1985 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1986 switch (band)
1987 {
1988 case eCSR_BAND_ALL:
1989 *pBand = WLAN_HDD_UI_BAND_AUTO;
1990 break;
1991
1992 case eCSR_BAND_24:
1993 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1994 break;
1995
1996 case eCSR_BAND_5G:
1997 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1998 break;
1999
2000 default:
2001 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2002 *pBand = -1;
2003 break;
2004 }
2005}
2006
2007/**---------------------------------------------------------------------------
2008
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002009 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2010
2011 This function parses the send action frame data passed in the format
2012 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2013
2014 \param - pValue Pointer to input country code revision
2015 \param - pTargetApBssid Pointer to target Ap bssid
2016 \param - pChannel Pointer to the Target AP channel
2017 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2018 \param - pBuf Pointer to data
2019 \param - pBufLen Pointer to data length
2020
2021 \return - 0 for success non-zero for failure
2022
2023 --------------------------------------------------------------------------*/
2024VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2025 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2026{
2027 tANI_U8 *inPtr = pValue;
2028 tANI_U8 *dataEnd;
2029 int tempInt;
2030 int j = 0;
2031 int i = 0;
2032 int v = 0;
2033 tANI_U8 tempBuf[32];
2034 tANI_U8 tempByte = 0;
2035
2036 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2037 /*no argument after the command*/
2038 if (NULL == inPtr)
2039 {
2040 return -EINVAL;
2041 }
2042
2043 /*no space after the command*/
2044 else if (SPACE_ASCII_VALUE != *inPtr)
2045 {
2046 return -EINVAL;
2047 }
2048
2049 /*removing empty spaces*/
2050 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2051
2052 /*no argument followed by spaces*/
2053 if ('\0' == *inPtr)
2054 {
2055 return -EINVAL;
2056 }
2057
2058 /*getting the first argument ie the target AP bssid */
2059 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2060 {
2061 return -EINVAL;
2062 }
2063 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2064 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2065 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2066
2067 /* point to the next argument */
2068 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2069 /*no argument after the command*/
2070 if (NULL == inPtr) return -EINVAL;
2071
2072 /*removing empty spaces*/
2073 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2074
2075 /*no argument followed by spaces*/
2076 if ('\0' == *inPtr)
2077 {
2078 return -EINVAL;
2079 }
2080
2081 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002082 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002083 v = kstrtos32(tempBuf, 10, &tempInt);
2084 if ( v < 0) return -EINVAL;
2085
2086 *pChannel = tempInt;
2087
2088 /* point to the next argument */
2089 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2090 /*no argument after the command*/
2091 if (NULL == inPtr) return -EINVAL;
2092 /*removing empty spaces*/
2093 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2094
2095 /*no argument followed by spaces*/
2096 if ('\0' == *inPtr)
2097 {
2098 return -EINVAL;
2099 }
2100
2101 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002102 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002103 v = kstrtos32(tempBuf, 10, &tempInt);
2104 if ( v < 0) return -EINVAL;
2105
2106 *pDwellTime = tempInt;
2107
2108 /* point to the next argument */
2109 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2110 /*no argument after the command*/
2111 if (NULL == inPtr) return -EINVAL;
2112 /*removing empty spaces*/
2113 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2114
2115 /*no argument followed by spaces*/
2116 if ('\0' == *inPtr)
2117 {
2118 return -EINVAL;
2119 }
2120
2121 /* find the length of data */
2122 dataEnd = inPtr;
2123 while(('\0' != *dataEnd) )
2124 {
2125 dataEnd++;
2126 ++(*pBufLen);
2127 }
2128 if ( *pBufLen <= 0) return -EINVAL;
2129
2130 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
2131 if (NULL == *pBuf)
2132 {
2133 hddLog(VOS_TRACE_LEVEL_FATAL,
2134 "%s: vos_mem_alloc failed ", __func__);
2135 return -EINVAL;
2136 }
2137
2138 /* the buffer received from the upper layer is character buffer,
2139 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2140 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2141 and f0 in 3rd location */
2142 for (i = 0, j = 0; j < *pBufLen; j += 2)
2143 {
2144 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2145 (*pBuf)[i++] = tempByte;
2146 }
2147 *pBufLen = i;
2148 return VOS_STATUS_SUCCESS;
2149}
2150
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002151/**---------------------------------------------------------------------------
2152
Srinivas Girigowdade697412013-02-14 16:31:48 -08002153 \brief hdd_parse_countryrev() - HDD Parse country code revision
2154
2155 This function parses the country code revision passed in the format
2156 SETCOUNTRYREV<space><Country code><space>revision
2157
2158 \param - pValue Pointer to input country code revision
2159 \param - pCountryCode Pointer to local output array to record country code
2160 \param - pRevision Pointer to store revision integer number
2161
2162 \return - 0 for success non-zero for failure
2163
2164 --------------------------------------------------------------------------*/
2165VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2166{
2167 tANI_U8 *inPtr = pValue;
2168 int tempInt;
2169
2170 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2171 /*no argument after the command*/
2172 if (NULL == inPtr)
2173 {
2174 return -EINVAL;
2175 }
2176
2177 /*no space after the command*/
2178 else if (SPACE_ASCII_VALUE != *inPtr)
2179 {
2180 return -EINVAL;
2181 }
2182
2183 /*removing empty spaces*/
2184 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2185
2186 /*no argument followed by spaces*/
2187 if ('\0' == *inPtr)
2188 {
2189 return -EINVAL;
2190 }
2191
2192 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002193 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002194
2195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2196 "Country code is : %s", pCountryCode);
2197
2198 /*inPtr pointing to the beginning of first space after country code */
2199 inPtr = strpbrk( inPtr, " " );
2200 /*no revision number after the country code argument */
2201 if (NULL == inPtr)
2202 {
2203 return -EINVAL;
2204 }
2205
2206 inPtr++;
2207
2208 /*removing empty space*/
2209 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2210
2211 /*no channel list after the number of channels argument and spaces*/
2212 if (0 == strncmp(pCountryCode, "KR", 2))
2213 {
2214 if ('\0' == *inPtr)
2215 {
2216 return -EINVAL;
2217 }
2218
2219 sscanf(inPtr, "%d", &tempInt);
2220 *pRevision = tempInt;
2221 }
2222 else
2223 {
2224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2225 "Revision input is required only for Country KR");
2226 return -EINVAL;
2227 }
2228 return VOS_STATUS_SUCCESS;
2229}
2230
2231/**---------------------------------------------------------------------------
2232
2233 \brief hdd_parse_channellist() - HDD Parse channel list
2234
2235 This function parses the channel list passed in the format
2236 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002237 if the Number of channels (N) does not match with the actual number of channels passed
2238 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2239 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2240 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2241 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002242
2243 \param - pValue Pointer to input channel list
2244 \param - ChannelList Pointer to local output array to record channel list
2245 \param - pNumChannels Pointer to number of roam scan channels
2246
2247 \return - 0 for success non-zero for failure
2248
2249 --------------------------------------------------------------------------*/
2250VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2251{
2252 tANI_U8 *inPtr = pValue;
2253 int tempInt;
2254 int j = 0;
2255 int v = 0;
2256 char buf[32];
2257
2258 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2259 /*no argument after the command*/
2260 if (NULL == inPtr)
2261 {
2262 return -EINVAL;
2263 }
2264
2265 /*no space after the command*/
2266 else if (SPACE_ASCII_VALUE != *inPtr)
2267 {
2268 return -EINVAL;
2269 }
2270
2271 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002272 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002273
2274 /*no argument followed by spaces*/
2275 if ('\0' == *inPtr)
2276 {
2277 return -EINVAL;
2278 }
2279
2280 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002281 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002282 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002283 if ((v < 0) ||
2284 (tempInt <= 0) ||
2285 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2286 {
2287 return -EINVAL;
2288 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002289
2290 *pNumChannels = tempInt;
2291
2292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2293 "Number of channels are: %d", *pNumChannels);
2294
2295 for (j = 0; j < (*pNumChannels); j++)
2296 {
2297 /*inPtr pointing to the beginning of first space after number of channels*/
2298 inPtr = strpbrk( inPtr, " " );
2299 /*no channel list after the number of channels argument*/
2300 if (NULL == inPtr)
2301 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002302 if (0 != j)
2303 {
2304 *pNumChannels = j;
2305 return VOS_STATUS_SUCCESS;
2306 }
2307 else
2308 {
2309 return -EINVAL;
2310 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002311 }
2312
2313 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002314 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002315
2316 /*no channel list after the number of channels argument and spaces*/
2317 if ( '\0' == *inPtr )
2318 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002319 if (0 != j)
2320 {
2321 *pNumChannels = j;
2322 return VOS_STATUS_SUCCESS;
2323 }
2324 else
2325 {
2326 return -EINVAL;
2327 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002328 }
2329
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002330 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002331 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002332 if ((v < 0) ||
2333 (tempInt <= 0) ||
2334 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2335 {
2336 return -EINVAL;
2337 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002338 pChannelList[j] = tempInt;
2339
2340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2341 "Channel %d added to preferred channel list",
2342 pChannelList[j] );
2343 }
2344
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345 return VOS_STATUS_SUCCESS;
2346}
2347
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002348
2349/**---------------------------------------------------------------------------
2350
2351 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2352
2353 This function parses the reasoc command data passed in the format
2354 REASSOC<space><bssid><space><channel>
2355
2356 \param - pValue Pointer to input country code revision
2357 \param - pTargetApBssid Pointer to target Ap bssid
2358 \param - pChannel Pointer to the Target AP channel
2359
2360 \return - 0 for success non-zero for failure
2361
2362 --------------------------------------------------------------------------*/
2363VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2364{
2365 tANI_U8 *inPtr = pValue;
2366 int tempInt;
2367 int v = 0;
2368 tANI_U8 tempBuf[32];
2369
2370 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2371 /*no argument after the command*/
2372 if (NULL == inPtr)
2373 {
2374 return -EINVAL;
2375 }
2376
2377 /*no space after the command*/
2378 else if (SPACE_ASCII_VALUE != *inPtr)
2379 {
2380 return -EINVAL;
2381 }
2382
2383 /*removing empty spaces*/
2384 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2385
2386 /*no argument followed by spaces*/
2387 if ('\0' == *inPtr)
2388 {
2389 return -EINVAL;
2390 }
2391
2392 /*getting the first argument ie the target AP bssid */
2393 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2394 {
2395 return -EINVAL;
2396 }
2397 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2398 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2399 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2400
2401 /* point to the next argument */
2402 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2403 /*no argument after the command*/
2404 if (NULL == inPtr) return -EINVAL;
2405
2406 /*removing empty spaces*/
2407 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2408
2409 /*no argument followed by spaces*/
2410 if ('\0' == *inPtr)
2411 {
2412 return -EINVAL;
2413 }
2414
2415 /*getting the next argument ie the channel number */
2416 sscanf(inPtr, "%s ", tempBuf);
2417 v = kstrtos32(tempBuf, 10, &tempInt);
2418 if ( v < 0) return -EINVAL;
2419
2420 *pChannel = tempInt;
2421 return VOS_STATUS_SUCCESS;
2422}
2423
2424#endif
2425
Jeff Johnson295189b2012-06-20 16:38:30 -07002426/**---------------------------------------------------------------------------
2427
2428 \brief hdd_open() - HDD Open function
2429
2430 This is called in response to ifconfig up
2431
2432 \param - dev Pointer to net_device structure
2433
2434 \return - 0 for success non-zero for failure
2435
2436 --------------------------------------------------------------------------*/
2437int hdd_open (struct net_device *dev)
2438{
2439 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2440 hdd_context_t *pHddCtx;
2441 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2442 VOS_STATUS status;
2443 v_BOOL_t in_standby = TRUE;
2444
2445 if (NULL == pAdapter)
2446 {
2447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002448 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002449 return -ENODEV;
2450 }
2451
2452 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2453 if (NULL == pHddCtx)
2454 {
2455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002456 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002457 return -ENODEV;
2458 }
2459
2460 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2461 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2462 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002463 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2464 {
2465 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302466 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002467 in_standby = FALSE;
2468 break;
2469 }
2470 else
2471 {
2472 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2473 pAdapterNode = pNext;
2474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002475 }
2476
2477 if (TRUE == in_standby)
2478 {
2479 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2480 {
2481 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2482 "wlan out of power save", __func__);
2483 return -EINVAL;
2484 }
2485 }
2486
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002487 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002488 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2489 {
2490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002491 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002492 /* Enable TX queues only when we are connected */
2493 netif_tx_start_all_queues(dev);
2494 }
2495
2496 return 0;
2497}
2498
2499int hdd_mon_open (struct net_device *dev)
2500{
2501 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2502
2503 if(pAdapter == NULL) {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002505 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002506 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002507 }
2508
2509 netif_start_queue(dev);
2510
2511 return 0;
2512}
2513/**---------------------------------------------------------------------------
2514
2515 \brief hdd_stop() - HDD stop function
2516
2517 This is called in response to ifconfig down
2518
2519 \param - dev Pointer to net_device structure
2520
2521 \return - 0 for success non-zero for failure
2522
2523 --------------------------------------------------------------------------*/
2524
2525int hdd_stop (struct net_device *dev)
2526{
2527 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2528 hdd_context_t *pHddCtx;
2529 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2530 VOS_STATUS status;
2531 v_BOOL_t enter_standby = TRUE;
2532
2533 ENTER();
2534
2535 if (NULL == pAdapter)
2536 {
2537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002538 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002539 return -ENODEV;
2540 }
2541
2542 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2543 if (NULL == pHddCtx)
2544 {
2545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002546 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002547 return -ENODEV;
2548 }
2549
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002550 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002551 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2552 netif_tx_disable(pAdapter->dev);
2553 netif_carrier_off(pAdapter->dev);
2554
2555
2556 /* SoftAP ifaces should never go in power save mode
2557 making sure same here. */
2558 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2559 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002561 )
2562 {
2563 /* SoftAP mode, so return from here */
2564 EXIT();
2565 return 0;
2566 }
2567
2568 /* Find if any iface is up then
2569 if any iface is up then can't put device to sleep/ power save mode. */
2570 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2571 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2572 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002573 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2574 {
2575 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302576 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002577 enter_standby = FALSE;
2578 break;
2579 }
2580 else
2581 {
2582 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2583 pAdapterNode = pNext;
2584 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002585 }
2586
2587 if (TRUE == enter_standby)
2588 {
2589 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2590 "entering standby", __func__);
2591 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2592 {
2593 /*log and return success*/
2594 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2595 "wlan in power save", __func__);
2596 }
2597 }
2598
2599 EXIT();
2600 return 0;
2601}
2602
2603/**---------------------------------------------------------------------------
2604
2605 \brief hdd_uninit() - HDD uninit function
2606
2607 This is called during the netdev unregister to uninitialize all data
2608associated with the device
2609
2610 \param - dev Pointer to net_device structure
2611
2612 \return - void
2613
2614 --------------------------------------------------------------------------*/
2615static void hdd_uninit (struct net_device *dev)
2616{
2617 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2618
2619 ENTER();
2620
2621 do
2622 {
2623 if (NULL == pAdapter)
2624 {
2625 hddLog(VOS_TRACE_LEVEL_FATAL,
2626 "%s: NULL pAdapter", __func__);
2627 break;
2628 }
2629
2630 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2631 {
2632 hddLog(VOS_TRACE_LEVEL_FATAL,
2633 "%s: Invalid magic", __func__);
2634 break;
2635 }
2636
2637 if (NULL == pAdapter->pHddCtx)
2638 {
2639 hddLog(VOS_TRACE_LEVEL_FATAL,
2640 "%s: NULL pHddCtx", __func__);
2641 break;
2642 }
2643
2644 if (dev != pAdapter->dev)
2645 {
2646 hddLog(VOS_TRACE_LEVEL_FATAL,
2647 "%s: Invalid device reference", __func__);
2648 /* we haven't validated all cases so let this go for now */
2649 }
2650
2651 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2652
2653 /* after uninit our adapter structure will no longer be valid */
2654 pAdapter->dev = NULL;
2655 pAdapter->magic = 0;
2656 } while (0);
2657
2658 EXIT();
2659}
2660
2661/**---------------------------------------------------------------------------
2662
2663 \brief hdd_release_firmware() -
2664
2665 This function calls the release firmware API to free the firmware buffer.
2666
2667 \param - pFileName Pointer to the File Name.
2668 pCtx - Pointer to the adapter .
2669
2670
2671 \return - 0 for success, non zero for failure
2672
2673 --------------------------------------------------------------------------*/
2674
2675VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2676{
2677 VOS_STATUS status = VOS_STATUS_SUCCESS;
2678 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2679 ENTER();
2680
2681
2682 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2683
2684 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2685
2686 if(pHddCtx->fw) {
2687 release_firmware(pHddCtx->fw);
2688 pHddCtx->fw = NULL;
2689 }
2690 else
2691 status = VOS_STATUS_E_FAILURE;
2692 }
2693 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2694 if(pHddCtx->nv) {
2695 release_firmware(pHddCtx->nv);
2696 pHddCtx->nv = NULL;
2697 }
2698 else
2699 status = VOS_STATUS_E_FAILURE;
2700
2701 }
2702
2703 EXIT();
2704 return status;
2705}
2706
2707/**---------------------------------------------------------------------------
2708
2709 \brief hdd_request_firmware() -
2710
2711 This function reads the firmware file using the request firmware
2712 API and returns the the firmware data and the firmware file size.
2713
2714 \param - pfileName - Pointer to the file name.
2715 - pCtx - Pointer to the adapter .
2716 - ppfw_data - Pointer to the pointer of the firmware data.
2717 - pSize - Pointer to the file size.
2718
2719 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2720
2721 --------------------------------------------------------------------------*/
2722
2723
2724VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2725{
2726 int status;
2727 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2728 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2729 ENTER();
2730
2731 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2732
2733 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2734
2735 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2736 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2737 __func__, pfileName);
2738 retval = VOS_STATUS_E_FAILURE;
2739 }
2740
2741 else {
2742 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2743 *pSize = pHddCtx->fw->size;
2744 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2745 __func__, *pSize);
2746 }
2747 }
2748 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2749
2750 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2751
2752 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2753 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2754 __func__, pfileName);
2755 retval = VOS_STATUS_E_FAILURE;
2756 }
2757
2758 else {
2759 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2760 *pSize = pHddCtx->nv->size;
2761 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2762 __func__, *pSize);
2763 }
2764 }
2765
2766 EXIT();
2767 return retval;
2768}
2769/**---------------------------------------------------------------------------
2770 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2771
2772 This is the function invoked by SME to inform the result of a full power
2773 request issued by HDD
2774
2775 \param - callbackcontext - Pointer to cookie
2776 status - result of request
2777
2778 \return - None
2779
2780--------------------------------------------------------------------------*/
2781void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2782{
2783 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2784
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002785 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 if(&pHddCtx->full_pwr_comp_var)
2787 {
2788 complete(&pHddCtx->full_pwr_comp_var);
2789 }
2790}
2791
2792/**---------------------------------------------------------------------------
2793
2794 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2795
2796 This is the function invoked by SME to inform the result of BMPS
2797 request issued by HDD
2798
2799 \param - callbackcontext - Pointer to cookie
2800 status - result of request
2801
2802 \return - None
2803
2804--------------------------------------------------------------------------*/
2805void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2806{
2807
2808 struct completion *completion_var = (struct completion*) callbackContext;
2809
2810 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2811 if(completion_var != NULL)
2812 {
2813 complete(completion_var);
2814 }
2815}
2816
2817/**---------------------------------------------------------------------------
2818
2819 \brief hdd_get_cfg_file_size() -
2820
2821 This function reads the configuration file using the request firmware
2822 API and returns the configuration file size.
2823
2824 \param - pCtx - Pointer to the adapter .
2825 - pFileName - Pointer to the file name.
2826 - pBufSize - Pointer to the buffer size.
2827
2828 \return - 0 for success, non zero for failure
2829
2830 --------------------------------------------------------------------------*/
2831
2832VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2833{
2834 int status;
2835 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2836
2837 ENTER();
2838
2839 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2840
2841 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2842 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2843 status = VOS_STATUS_E_FAILURE;
2844 }
2845 else {
2846 *pBufSize = pHddCtx->fw->size;
2847 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2848 release_firmware(pHddCtx->fw);
2849 pHddCtx->fw = NULL;
2850 }
2851
2852 EXIT();
2853 return VOS_STATUS_SUCCESS;
2854}
2855
2856/**---------------------------------------------------------------------------
2857
2858 \brief hdd_read_cfg_file() -
2859
2860 This function reads the configuration file using the request firmware
2861 API and returns the cfg data and the buffer size of the configuration file.
2862
2863 \param - pCtx - Pointer to the adapter .
2864 - pFileName - Pointer to the file name.
2865 - pBuffer - Pointer to the data buffer.
2866 - pBufSize - Pointer to the buffer size.
2867
2868 \return - 0 for success, non zero for failure
2869
2870 --------------------------------------------------------------------------*/
2871
2872VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2873 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2874{
2875 int status;
2876 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2877
2878 ENTER();
2879
2880 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2881
2882 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2884 return VOS_STATUS_E_FAILURE;
2885 }
2886 else {
2887 if(*pBufSize != pHddCtx->fw->size) {
2888 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2889 "file size", __func__);
2890 release_firmware(pHddCtx->fw);
2891 pHddCtx->fw = NULL;
2892 return VOS_STATUS_E_FAILURE;
2893 }
2894 else {
2895 if(pBuffer) {
2896 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2897 }
2898 release_firmware(pHddCtx->fw);
2899 pHddCtx->fw = NULL;
2900 }
2901 }
2902
2903 EXIT();
2904
2905 return VOS_STATUS_SUCCESS;
2906}
2907
2908/**---------------------------------------------------------------------------
2909
Jeff Johnson295189b2012-06-20 16:38:30 -07002910 \brief hdd_set_mac_address() -
2911
2912 This function sets the user specified mac address using
2913 the command ifconfig wlanX hw ether <mac adress>.
2914
2915 \param - dev - Pointer to the net device.
2916 - addr - Pointer to the sockaddr.
2917 \return - 0 for success, non zero for failure
2918
2919 --------------------------------------------------------------------------*/
2920
2921static int hdd_set_mac_address(struct net_device *dev, void *addr)
2922{
2923 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2924 struct sockaddr *psta_mac_addr = addr;
2925 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2926
2927 ENTER();
2928
2929 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2930
2931#ifdef HDD_SESSIONIZE
2932 // set the MAC address though the STA ID CFG.
2933 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2934 (v_U8_t *)&pAdapter->macAddressCurrent,
2935 sizeof( pAdapter->macAddressCurrent ),
2936 hdd_set_mac_addr_cb, VOS_FALSE );
2937#endif
2938
2939 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2940
2941 EXIT();
2942 return halStatus;
2943}
2944
2945tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2946{
2947 int i;
2948 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2949 {
2950 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2951 break;
2952 }
2953
2954 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2955 return NULL;
2956
2957 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2958 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2959}
2960
2961void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2962{
2963 int i;
2964 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2965 {
2966 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2967 {
2968 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2969 break;
2970 }
2971 }
2972 return;
2973}
2974
2975#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2976 static struct net_device_ops wlan_drv_ops = {
2977 .ndo_open = hdd_open,
2978 .ndo_stop = hdd_stop,
2979 .ndo_uninit = hdd_uninit,
2980 .ndo_start_xmit = hdd_hard_start_xmit,
2981 .ndo_tx_timeout = hdd_tx_timeout,
2982 .ndo_get_stats = hdd_stats,
2983 .ndo_do_ioctl = hdd_ioctl,
2984 .ndo_set_mac_address = hdd_set_mac_address,
2985 .ndo_select_queue = hdd_select_queue,
2986#ifdef WLAN_FEATURE_PACKET_FILTERING
2987#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2988 .ndo_set_rx_mode = hdd_set_multicast_list,
2989#else
2990 .ndo_set_multicast_list = hdd_set_multicast_list,
2991#endif //LINUX_VERSION_CODE
2992#endif
2993 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002994 static struct net_device_ops wlan_mon_drv_ops = {
2995 .ndo_open = hdd_mon_open,
2996 .ndo_stop = hdd_stop,
2997 .ndo_uninit = hdd_uninit,
2998 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2999 .ndo_tx_timeout = hdd_tx_timeout,
3000 .ndo_get_stats = hdd_stats,
3001 .ndo_do_ioctl = hdd_ioctl,
3002 .ndo_set_mac_address = hdd_set_mac_address,
3003 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003004
3005#endif
3006
3007void hdd_set_station_ops( struct net_device *pWlanDev )
3008{
3009#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3010 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3011 pWlanDev->netdev_ops = &wlan_drv_ops;
3012#else
3013 pWlanDev->open = hdd_open;
3014 pWlanDev->stop = hdd_stop;
3015 pWlanDev->uninit = hdd_uninit;
3016 pWlanDev->hard_start_xmit = NULL;
3017 pWlanDev->tx_timeout = hdd_tx_timeout;
3018 pWlanDev->get_stats = hdd_stats;
3019 pWlanDev->do_ioctl = hdd_ioctl;
3020 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3021 pWlanDev->set_mac_address = hdd_set_mac_address;
3022#endif
3023}
3024
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003025static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003026{
3027 struct net_device *pWlanDev = NULL;
3028 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003029 /*
3030 * cfg80211 initialization and registration....
3031 */
3032 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3033
Jeff Johnson295189b2012-06-20 16:38:30 -07003034 if(pWlanDev != NULL)
3035 {
3036
3037 //Save the pointer to the net_device in the HDD adapter
3038 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3039
Jeff Johnson295189b2012-06-20 16:38:30 -07003040 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3041
3042 pAdapter->dev = pWlanDev;
3043 pAdapter->pHddCtx = pHddCtx;
3044 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3045
3046 init_completion(&pAdapter->session_open_comp_var);
3047 init_completion(&pAdapter->session_close_comp_var);
3048 init_completion(&pAdapter->disconnect_comp_var);
3049 init_completion(&pAdapter->linkup_event_var);
3050 init_completion(&pAdapter->cancel_rem_on_chan_var);
3051 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003052#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3053 init_completion(&pAdapter->offchannel_tx_event);
3054#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003055 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003056#ifdef FEATURE_WLAN_TDLS
3057 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003058 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003059 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003060#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003061 init_completion(&pHddCtx->mc_sus_event_var);
3062 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003063 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003064
Jeff Johnson295189b2012-06-20 16:38:30 -07003065 pAdapter->isLinkUpSvcNeeded = FALSE;
3066 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3067 //Init the net_device structure
3068 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3069
3070 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3071 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3072 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3073 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3074
3075 hdd_set_station_ops( pAdapter->dev );
3076
3077 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3079 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3080 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003081 /* set pWlanDev's parent to underlying device */
3082 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3083 }
3084
3085 return pAdapter;
3086}
3087
3088VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3089{
3090 struct net_device *pWlanDev = pAdapter->dev;
3091 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3092 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3093 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3094
3095 if( rtnl_lock_held )
3096 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003097 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003098 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3099 {
3100 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3101 return VOS_STATUS_E_FAILURE;
3102 }
3103 }
3104 if (register_netdevice(pWlanDev))
3105 {
3106 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3107 return VOS_STATUS_E_FAILURE;
3108 }
3109 }
3110 else
3111 {
3112 if(register_netdev(pWlanDev))
3113 {
3114 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3115 return VOS_STATUS_E_FAILURE;
3116 }
3117 }
3118 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3119
3120 return VOS_STATUS_SUCCESS;
3121}
3122
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003123static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003124{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003125 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003126
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003127 if (NULL == pAdapter)
3128 {
3129 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3130 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003131 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003132
3133 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3134 {
3135 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3136 return eHAL_STATUS_NOT_INITIALIZED;
3137 }
3138
3139 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3140
3141 /* need to make sure all of our scheduled work has completed.
3142 * This callback is called from MC thread context, so it is safe to
3143 * to call below flush workqueue API from here.
3144 */
3145 flush_scheduled_work();
3146
3147 /* We can be blocked while waiting for scheduled work to be
3148 * flushed, and the adapter structure can potentially be freed, in
3149 * which case the magic will have been reset. So make sure the
3150 * magic is still good, and hence the adapter structure is still
3151 * valid, before signaling completion */
3152 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3153 {
3154 complete(&pAdapter->session_close_comp_var);
3155 }
3156
Jeff Johnson295189b2012-06-20 16:38:30 -07003157 return eHAL_STATUS_SUCCESS;
3158}
3159
3160VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3161{
3162 struct net_device *pWlanDev = pAdapter->dev;
3163 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3164 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3165 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3166 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3167 int rc = 0;
3168
3169 INIT_COMPLETION(pAdapter->session_open_comp_var);
3170 //Open a SME session for future operation
3171 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
3172 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
3173 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3174 {
3175 hddLog(VOS_TRACE_LEVEL_FATAL,
3176 "sme_OpenSession() failed with status code %08d [x%08lx]",
3177 halStatus, halStatus );
3178 status = VOS_STATUS_E_FAILURE;
3179 goto error_sme_open;
3180 }
3181
3182 //Block on a completion variable. Can't wait forever though.
3183 rc = wait_for_completion_interruptible_timeout(
3184 &pAdapter->session_open_comp_var,
3185 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3186 if (!rc)
3187 {
3188 hddLog(VOS_TRACE_LEVEL_FATAL,
3189 "Session is not opened within timeout period code %08d", rc );
3190 status = VOS_STATUS_E_FAILURE;
3191 goto error_sme_open;
3192 }
3193
3194 // Register wireless extensions
3195 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3196 {
3197 hddLog(VOS_TRACE_LEVEL_FATAL,
3198 "hdd_register_wext() failed with status code %08d [x%08lx]",
3199 halStatus, halStatus );
3200 status = VOS_STATUS_E_FAILURE;
3201 goto error_register_wext;
3202 }
3203 //Safe to register the hard_start_xmit function again
3204#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3205 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3206#else
3207 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3208#endif
3209
3210 //Set the Connection State to Not Connected
3211 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3212
3213 //Set the default operation channel
3214 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3215
3216 /* Make the default Auth Type as OPEN*/
3217 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3218
3219 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3220 {
3221 hddLog(VOS_TRACE_LEVEL_FATAL,
3222 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3223 status, status );
3224 goto error_init_txrx;
3225 }
3226
3227 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3228
3229 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3230 {
3231 hddLog(VOS_TRACE_LEVEL_FATAL,
3232 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3233 status, status );
3234 goto error_wmm_init;
3235 }
3236
3237 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3238
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003239#ifdef FEATURE_WLAN_TDLS
3240 if(0 != wlan_hdd_tdls_init(pAdapter))
3241 {
3242 status = VOS_STATUS_E_FAILURE;
3243 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3244 goto error_tdls_init;
3245 }
3246 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3247#endif
3248
Jeff Johnson295189b2012-06-20 16:38:30 -07003249 return VOS_STATUS_SUCCESS;
3250
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003251#ifdef FEATURE_WLAN_TDLS
3252error_tdls_init:
3253 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3254 hdd_wmm_adapter_close(pAdapter);
3255#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003256error_wmm_init:
3257 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3258 hdd_deinit_tx_rx(pAdapter);
3259error_init_txrx:
3260 hdd_UnregisterWext(pWlanDev);
3261error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003262 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003263 {
3264 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003265 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003266 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003267 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003268 {
3269 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003270 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003272 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003273 }
3274}
3275error_sme_open:
3276 return status;
3277}
3278
Jeff Johnson295189b2012-06-20 16:38:30 -07003279void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3280{
3281 hdd_cfg80211_state_t *cfgState;
3282
3283 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3284
3285 if( NULL != cfgState->buf )
3286 {
3287 int rc;
3288 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3289 rc = wait_for_completion_interruptible_timeout(
3290 &pAdapter->tx_action_cnf_event,
3291 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3292 if(!rc)
3293 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003295 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3296 }
3297 }
3298 return;
3299}
Jeff Johnson295189b2012-06-20 16:38:30 -07003300
3301void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3302{
3303 ENTER();
3304 switch ( pAdapter->device_mode )
3305 {
3306 case WLAN_HDD_INFRA_STATION:
3307 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003308 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003309 {
3310 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3311 {
3312 hdd_deinit_tx_rx( pAdapter );
3313 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3314 }
3315
3316 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3317 {
3318 hdd_wmm_adapter_close( pAdapter );
3319 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3320 }
3321
Jeff Johnson295189b2012-06-20 16:38:30 -07003322 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003323#ifdef FEATURE_WLAN_TDLS
3324 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3325 {
3326 wlan_hdd_tdls_exit(pAdapter);
3327 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3328 }
3329#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003330
3331 break;
3332 }
3333
3334 case WLAN_HDD_SOFTAP:
3335 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003336 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003337 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003338
3339 hdd_unregister_hostapd(pAdapter);
3340 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003341 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003342 break;
3343 }
3344
3345 case WLAN_HDD_MONITOR:
3346 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3349 {
3350 hdd_deinit_tx_rx( pAdapter );
3351 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3352 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003353 if(NULL != pAdapterforTx)
3354 {
3355 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003357 break;
3358 }
3359
3360
3361 default:
3362 break;
3363 }
3364
3365 EXIT();
3366}
3367
3368void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3369{
3370 struct net_device *pWlanDev = pAdapter->dev;
3371
3372 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3373 if( rtnl_held )
3374 {
3375 unregister_netdevice(pWlanDev);
3376 }
3377 else
3378 {
3379 unregister_netdev(pWlanDev);
3380 }
3381 // note that the pAdapter is no longer valid at this point
3382 // since the memory has been reclaimed
3383 }
3384
3385}
3386
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003387void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3388{
3389 tSirSetPowerParamsReq powerRequest = { 0 };
3390
3391 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -07003392 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003393
3394 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3395 {
3396 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3397 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3398 }
3399 else
3400 {
3401 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3402 }
3403
3404 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3405 *specified during Enter/Exit BMPS when LCD off*/
3406 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3407 NULL, eANI_BOOLEAN_FALSE);
3408 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3409 NULL, eANI_BOOLEAN_FALSE);
3410
3411 /* switch to the DTIM specified in cfg.ini */
3412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3413 "Switch to DTIM%d", powerRequest.uListenInterval);
3414 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3415
3416}
3417
3418void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3419{
3420 /*Switch back to DTIM 1*/
3421 tSirSetPowerParamsReq powerRequest = { 0 };
3422
3423 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3424 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003425 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003426
3427 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3428 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3429 NULL, eANI_BOOLEAN_FALSE);
3430 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3431 NULL, eANI_BOOLEAN_FALSE);
3432
3433 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3434 "Switch to DTIM%d",powerRequest.uListenInterval);
3435 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3436
3437}
3438
Jeff Johnson295189b2012-06-20 16:38:30 -07003439VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3440{
3441 VOS_STATUS status = VOS_STATUS_SUCCESS;
3442
3443 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3444 {
3445 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3446 }
3447
3448 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3449 {
3450 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3451 }
3452
3453 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3454 {
3455 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3456 }
3457
3458 return status;
3459}
3460
3461VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3462{
3463 hdd_adapter_t *pAdapter = NULL;
3464 eHalStatus halStatus;
3465 VOS_STATUS status = VOS_STATUS_E_INVAL;
3466 v_BOOL_t disableBmps = FALSE;
3467 v_BOOL_t disableImps = FALSE;
3468
3469 switch(session_type)
3470 {
3471 case WLAN_HDD_INFRA_STATION:
3472 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003473 case WLAN_HDD_P2P_CLIENT:
3474 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003475 //Exit BMPS -> Is Sta/P2P Client is already connected
3476 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3477 if((NULL != pAdapter)&&
3478 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3479 {
3480 disableBmps = TRUE;
3481 }
3482
3483 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3484 if((NULL != pAdapter)&&
3485 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3486 {
3487 disableBmps = TRUE;
3488 }
3489
3490 //Exit both Bmps and Imps incase of Go/SAP Mode
3491 if((WLAN_HDD_SOFTAP == session_type) ||
3492 (WLAN_HDD_P2P_GO == session_type))
3493 {
3494 disableBmps = TRUE;
3495 disableImps = TRUE;
3496 }
3497
3498 if(TRUE == disableImps)
3499 {
3500 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3501 {
3502 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3503 }
3504 }
3505
3506 if(TRUE == disableBmps)
3507 {
3508 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3509 {
3510 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3511
3512 if(eHAL_STATUS_SUCCESS != halStatus)
3513 {
3514 status = VOS_STATUS_E_FAILURE;
3515 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3516 VOS_ASSERT(0);
3517 return status;
3518 }
3519 }
3520
3521 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3522 {
3523 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3524
3525 if(eHAL_STATUS_SUCCESS != halStatus)
3526 {
3527 status = VOS_STATUS_E_FAILURE;
3528 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3529 VOS_ASSERT(0);
3530 return status;
3531 }
3532 }
3533 }
3534
3535 if((TRUE == disableBmps) ||
3536 (TRUE == disableImps))
3537 {
3538 /* Now, get the chip into Full Power now */
3539 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3540 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3541 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3542
3543 if(halStatus != eHAL_STATUS_SUCCESS)
3544 {
3545 if(halStatus == eHAL_STATUS_PMC_PENDING)
3546 {
3547 //Block on a completion variable. Can't wait forever though
3548 wait_for_completion_interruptible_timeout(
3549 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3550 }
3551 else
3552 {
3553 status = VOS_STATUS_E_FAILURE;
3554 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3555 VOS_ASSERT(0);
3556 return status;
3557 }
3558 }
3559
3560 status = VOS_STATUS_SUCCESS;
3561 }
3562
3563 break;
3564 }
3565 return status;
3566}
3567
3568hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003569 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003570 tANI_U8 rtnl_held )
3571{
3572 hdd_adapter_t *pAdapter = NULL;
3573 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3574 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3575 VOS_STATUS exitbmpsStatus;
3576
3577 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3578
3579 //Disable BMPS incase of Concurrency
3580 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3581
3582 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3583 {
3584 //Fail to Exit BMPS
3585 VOS_ASSERT(0);
3586 return NULL;
3587 }
3588
3589 switch(session_type)
3590 {
3591 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003592 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003593 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 {
3595 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3596
3597 if( NULL == pAdapter )
3598 return NULL;
3599
Jeff Johnsone7245742012-09-05 17:12:55 -07003600 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3601 NL80211_IFTYPE_P2P_CLIENT:
3602 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003603
Jeff Johnson295189b2012-06-20 16:38:30 -07003604 pAdapter->device_mode = session_type;
3605
3606 status = hdd_init_station_mode( pAdapter );
3607 if( VOS_STATUS_SUCCESS != status )
3608 goto err_free_netdev;
3609
3610 status = hdd_register_interface( pAdapter, rtnl_held );
3611 if( VOS_STATUS_SUCCESS != status )
3612 {
3613 hdd_deinit_adapter(pHddCtx, pAdapter);
3614 goto err_free_netdev;
3615 }
3616 //Stop the Interface TX queue.
3617 netif_tx_disable(pAdapter->dev);
3618 //netif_tx_disable(pWlanDev);
3619 netif_carrier_off(pAdapter->dev);
3620
3621 break;
3622 }
3623
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003625 case WLAN_HDD_SOFTAP:
3626 {
3627 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3628 if( NULL == pAdapter )
3629 return NULL;
3630
Jeff Johnson295189b2012-06-20 16:38:30 -07003631 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3632 NL80211_IFTYPE_AP:
3633 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003634 pAdapter->device_mode = session_type;
3635
3636 status = hdd_init_ap_mode(pAdapter);
3637 if( VOS_STATUS_SUCCESS != status )
3638 goto err_free_netdev;
3639
3640 status = hdd_register_hostapd( pAdapter, rtnl_held );
3641 if( VOS_STATUS_SUCCESS != status )
3642 {
3643 hdd_deinit_adapter(pHddCtx, pAdapter);
3644 goto err_free_netdev;
3645 }
3646
3647 netif_tx_disable(pAdapter->dev);
3648 netif_carrier_off(pAdapter->dev);
3649
3650 hdd_set_conparam( 1 );
3651 break;
3652 }
3653 case WLAN_HDD_MONITOR:
3654 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003655 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3656 if( NULL == pAdapter )
3657 return NULL;
3658
3659 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3660 pAdapter->device_mode = session_type;
3661 status = hdd_register_interface( pAdapter, rtnl_held );
3662#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3663 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3664#else
3665 pAdapter->dev->open = hdd_mon_open;
3666 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3667#endif
3668 hdd_init_tx_rx( pAdapter );
3669 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3670 //Set adapter to be used for data tx. It will use either GO or softap.
3671 pAdapter->sessionCtx.monitor.pAdapterForTx =
3672 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003673 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3674 {
3675 pAdapter->sessionCtx.monitor.pAdapterForTx =
3676 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3677 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003678 /* This workqueue will be used to transmit management packet over
3679 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003680 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3681 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3682 return NULL;
3683 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003684
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3686 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003687 }
3688 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 case WLAN_HDD_FTM:
3690 {
3691 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3692
3693 if( NULL == pAdapter )
3694 return NULL;
3695 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3696 * message while loading driver in FTM mode. */
3697 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3698 pAdapter->device_mode = session_type;
3699 status = hdd_register_interface( pAdapter, rtnl_held );
3700 }
3701 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 default:
3703 {
3704 VOS_ASSERT(0);
3705 return NULL;
3706 }
3707 }
3708
3709
3710 if( VOS_STATUS_SUCCESS == status )
3711 {
3712 //Add it to the hdd's session list.
3713 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3714 if( NULL == pHddAdapterNode )
3715 {
3716 status = VOS_STATUS_E_NOMEM;
3717 }
3718 else
3719 {
3720 pHddAdapterNode->pAdapter = pAdapter;
3721 status = hdd_add_adapter_back ( pHddCtx,
3722 pHddAdapterNode );
3723 }
3724 }
3725
3726 if( VOS_STATUS_SUCCESS != status )
3727 {
3728 if( NULL != pAdapter )
3729 {
3730 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3731 pAdapter = NULL;
3732 }
3733 if( NULL != pHddAdapterNode )
3734 {
3735 vos_mem_free( pHddAdapterNode );
3736 }
3737
3738 goto resume_bmps;
3739 }
3740
3741 if(VOS_STATUS_SUCCESS == status)
3742 {
3743 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3744
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003745 //Initialize the WoWL service
3746 if(!hdd_init_wowl(pAdapter))
3747 {
3748 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3749 goto err_free_netdev;
3750 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 return pAdapter;
3753
3754err_free_netdev:
3755 free_netdev(pAdapter->dev);
3756 wlan_hdd_release_intf_addr( pHddCtx,
3757 pAdapter->macAddressCurrent.bytes );
3758
3759resume_bmps:
3760 //If bmps disabled enable it
3761 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3762 {
3763 hdd_enable_bmps_imps(pHddCtx);
3764 }
3765 return NULL;
3766}
3767
3768VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3769 tANI_U8 rtnl_held )
3770{
3771 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3772 VOS_STATUS status;
3773
3774 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3775 if( VOS_STATUS_SUCCESS != status )
3776 return status;
3777
3778 while ( pCurrent->pAdapter != pAdapter )
3779 {
3780 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3781 if( VOS_STATUS_SUCCESS != status )
3782 break;
3783
3784 pCurrent = pNext;
3785 }
3786 pAdapterNode = pCurrent;
3787 if( VOS_STATUS_SUCCESS == status )
3788 {
3789 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3790 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3791 hdd_remove_adapter( pHddCtx, pAdapterNode );
3792 vos_mem_free( pAdapterNode );
3793
Jeff Johnson295189b2012-06-20 16:38:30 -07003794
3795 /* If there is a single session of STA/P2P client, re-enable BMPS */
3796 if ((!vos_concurrent_sessions_running()) &&
3797 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3798 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3799 {
3800 hdd_enable_bmps_imps(pHddCtx);
3801 }
3802
3803 return VOS_STATUS_SUCCESS;
3804 }
3805
3806 return VOS_STATUS_E_FAILURE;
3807}
3808
3809VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3810{
3811 hdd_adapter_list_node_t *pHddAdapterNode;
3812 VOS_STATUS status;
3813
3814 ENTER();
3815
3816 do
3817 {
3818 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3819 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3820 {
3821 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3822 vos_mem_free( pHddAdapterNode );
3823 }
3824 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3825
3826 EXIT();
3827
3828 return VOS_STATUS_SUCCESS;
3829}
3830
3831void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3832{
3833 v_U8_t addIE[1] = {0};
3834
3835 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3836 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3837 eANI_BOOLEAN_FALSE) )
3838 {
3839 hddLog(LOGE,
3840 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3841 }
3842
3843 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3844 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3845 eANI_BOOLEAN_FALSE) )
3846 {
3847 hddLog(LOGE,
3848 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3849 }
3850
3851 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3852 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3853 eANI_BOOLEAN_FALSE) )
3854 {
3855 hddLog(LOGE,
3856 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3857 }
3858}
3859
3860VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3861{
3862 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3863 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3864 union iwreq_data wrqu;
3865
3866 ENTER();
3867
3868 switch(pAdapter->device_mode)
3869 {
3870 case WLAN_HDD_INFRA_STATION:
3871 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003872 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003873 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3874 {
3875 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3876 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3877 pAdapter->sessionId,
3878 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3879 else
3880 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3881 pAdapter->sessionId,
3882 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3883 //success implies disconnect command got queued up successfully
3884 if(halStatus == eHAL_STATUS_SUCCESS)
3885 {
3886 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3887 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3888 }
3889 memset(&wrqu, '\0', sizeof(wrqu));
3890 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3891 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3892 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3893 }
3894 else
3895 {
3896 hdd_abort_mac_scan(pHddCtx);
3897 }
3898
3899 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3900 {
3901 INIT_COMPLETION(pAdapter->session_close_comp_var);
3902 if (eHAL_STATUS_SUCCESS ==
3903 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3904 hdd_smeCloseSessionCallback, pAdapter))
3905 {
3906 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003907 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003908 &pAdapter->session_close_comp_var,
3909 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3910 }
3911 }
3912
3913 break;
3914
3915 case WLAN_HDD_SOFTAP:
3916 case WLAN_HDD_P2P_GO:
3917 //Any softap specific cleanup here...
3918 mutex_lock(&pHddCtx->sap_lock);
3919 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3920 {
3921 VOS_STATUS status;
3922 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3923
3924 //Stop Bss.
3925 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3926 if (VOS_IS_STATUS_SUCCESS(status))
3927 {
3928 hdd_hostapd_state_t *pHostapdState =
3929 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3930
3931 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3932
3933 if (!VOS_IS_STATUS_SUCCESS(status))
3934 {
3935 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003936 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 }
3938 }
3939 else
3940 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003941 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003942 }
3943 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3944
3945 if (eHAL_STATUS_FAILURE ==
3946 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3947 0, NULL, eANI_BOOLEAN_FALSE))
3948 {
3949 hddLog(LOGE,
3950 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003951 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003952 }
3953
3954 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3955 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3956 eANI_BOOLEAN_FALSE) )
3957 {
3958 hddLog(LOGE,
3959 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3960 }
3961
3962 // Reset WNI_CFG_PROBE_RSP Flags
3963 wlan_hdd_reset_prob_rspies(pAdapter);
3964 kfree(pAdapter->sessionCtx.ap.beacon);
3965 pAdapter->sessionCtx.ap.beacon = NULL;
3966 }
3967 mutex_unlock(&pHddCtx->sap_lock);
3968 break;
3969 case WLAN_HDD_MONITOR:
3970 break;
3971 default:
3972 break;
3973 }
3974
3975 EXIT();
3976 return VOS_STATUS_SUCCESS;
3977}
3978
3979VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3980{
3981 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3982 VOS_STATUS status;
3983 hdd_adapter_t *pAdapter;
3984
3985 ENTER();
3986
3987 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3988
3989 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3990 {
3991 pAdapter = pAdapterNode->pAdapter;
3992 netif_tx_disable(pAdapter->dev);
3993 netif_carrier_off(pAdapter->dev);
3994
3995 hdd_stop_adapter( pHddCtx, pAdapter );
3996
3997 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3998 pAdapterNode = pNext;
3999 }
4000
4001 EXIT();
4002
4003 return VOS_STATUS_SUCCESS;
4004}
4005
4006VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4007{
4008 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4009 VOS_STATUS status;
4010 hdd_adapter_t *pAdapter;
4011
4012 ENTER();
4013
4014 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4015
4016 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4017 {
4018 pAdapter = pAdapterNode->pAdapter;
4019 netif_tx_disable(pAdapter->dev);
4020 netif_carrier_off(pAdapter->dev);
4021
4022 //Record whether STA is associated
4023 pAdapter->sessionCtx.station.bSendDisconnect =
4024 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
4025 VOS_TRUE : VOS_FALSE;
4026
4027 hdd_deinit_tx_rx(pAdapter);
4028 hdd_wmm_adapter_close(pAdapter);
4029
4030 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4031 pAdapterNode = pNext;
4032 }
4033
4034 EXIT();
4035
4036 return VOS_STATUS_SUCCESS;
4037}
4038
4039VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4040{
4041 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4042 VOS_STATUS status;
4043 hdd_adapter_t *pAdapter;
4044 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
4045
4046 ENTER();
4047
4048 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4049
4050 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4051 {
4052 pAdapter = pAdapterNode->pAdapter;
4053
4054 switch(pAdapter->device_mode)
4055 {
4056 case WLAN_HDD_INFRA_STATION:
4057 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004058 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 hdd_init_station_mode(pAdapter);
4060 /* Open the gates for HDD to receive Wext commands */
4061 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004062 pHddCtx->scan_info.mScanPending = FALSE;
4063 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004064
4065 //Trigger the initial scan
4066 hdd_wlan_initial_scan(pAdapter);
4067
4068 //Indicate disconnect event to supplicant if associated previously
4069 if(pAdapter->sessionCtx.station.bSendDisconnect)
4070 {
4071 union iwreq_data wrqu;
4072 memset(&wrqu, '\0', sizeof(wrqu));
4073 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4074 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4075 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4076 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
4077
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 /* indicate disconnected event to nl80211 */
4079 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4080 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 }
4082 break;
4083
4084 case WLAN_HDD_SOFTAP:
4085 /* softAP can handle SSR */
4086 break;
4087
4088 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004089 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4090 __func__);
4091 /* event supplicant to restart */
4092 cfg80211_del_sta(pAdapter->dev,
4093 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004094 break;
4095
4096 case WLAN_HDD_MONITOR:
4097 /* monitor interface start */
4098 break;
4099 default:
4100 break;
4101 }
4102
4103 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4104 pAdapterNode = pNext;
4105 }
4106
4107 EXIT();
4108
4109 return VOS_STATUS_SUCCESS;
4110}
4111
4112VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4113{
4114 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4115 hdd_adapter_t *pAdapter;
4116 VOS_STATUS status;
4117 v_U32_t roamId;
4118
4119 ENTER();
4120
4121 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4122
4123 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4124 {
4125 pAdapter = pAdapterNode->pAdapter;
4126
4127 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4128 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4129 {
4130 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4131 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4132
4133 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4134 init_completion(&pAdapter->disconnect_comp_var);
4135 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4136 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4137
4138 wait_for_completion_interruptible_timeout(
4139 &pAdapter->disconnect_comp_var,
4140 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4141
4142 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4143 pHddCtx->isAmpAllowed = VOS_FALSE;
4144 sme_RoamConnect(pHddCtx->hHal,
4145 pAdapter->sessionId, &(pWextState->roamProfile),
4146 &roamId);
4147 }
4148
4149 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4150 pAdapterNode = pNext;
4151 }
4152
4153 EXIT();
4154
4155 return VOS_STATUS_SUCCESS;
4156}
4157
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004158void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4159{
4160 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4161 VOS_STATUS status;
4162 hdd_adapter_t *pAdapter;
4163 hdd_station_ctx_t *pHddStaCtx;
4164 hdd_ap_ctx_t *pHddApCtx;
4165 hdd_hostapd_state_t * pHostapdState;
4166 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4167 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4168 const char *p2pMode = "DEV";
4169 const char *ccMode = "Standalone";
4170 int n;
4171
4172 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4173 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4174 {
4175 pAdapter = pAdapterNode->pAdapter;
4176 switch (pAdapter->device_mode) {
4177 case WLAN_HDD_INFRA_STATION:
4178 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4179 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4180 staChannel = pHddStaCtx->conn_info.operationChannel;
4181 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4182 }
4183 break;
4184 case WLAN_HDD_P2P_CLIENT:
4185 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4186 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4187 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4188 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4189 p2pMode = "CLI";
4190 }
4191 break;
4192 case WLAN_HDD_P2P_GO:
4193 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4194 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4195 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4196 p2pChannel = pHddApCtx->operatingChannel;
4197 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4198 }
4199 p2pMode = "GO";
4200 break;
4201 case WLAN_HDD_SOFTAP:
4202 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4203 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4204 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4205 apChannel = pHddApCtx->operatingChannel;
4206 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4207 }
4208 break;
4209 default:
4210 break;
4211 }
4212 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4213 pAdapterNode = pNext;
4214 }
4215 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4216 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4217 }
4218 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4219 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4220 if (p2pChannel > 0) {
4221 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4222 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4223 }
4224 if (apChannel > 0) {
4225 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4226 apChannel, MAC_ADDR_ARRAY(apBssid));
4227 }
4228
4229 if (p2pChannel > 0 && apChannel > 0) {
4230 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4231 }
4232}
4233
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004234bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004235{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004236 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004237}
4238
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004239/* Once SSR is disabled then it cannot be set. */
4240void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004241{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004242 if (HDD_SSR_DISABLED == isSsrRequired)
4243 return;
4244
Jeff Johnson295189b2012-06-20 16:38:30 -07004245 isSsrRequired = value;
4246}
4247
4248VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4249 hdd_adapter_list_node_t** ppAdapterNode)
4250{
4251 VOS_STATUS status;
4252 spin_lock(&pHddCtx->hddAdapters.lock);
4253 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4254 (hdd_list_node_t**) ppAdapterNode );
4255 spin_unlock(&pHddCtx->hddAdapters.lock);
4256 return status;
4257}
4258
4259VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4260 hdd_adapter_list_node_t* pAdapterNode,
4261 hdd_adapter_list_node_t** pNextAdapterNode)
4262{
4263 VOS_STATUS status;
4264 spin_lock(&pHddCtx->hddAdapters.lock);
4265 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4266 (hdd_list_node_t*) pAdapterNode,
4267 (hdd_list_node_t**)pNextAdapterNode );
4268
4269 spin_unlock(&pHddCtx->hddAdapters.lock);
4270 return status;
4271}
4272
4273VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4274 hdd_adapter_list_node_t* pAdapterNode)
4275{
4276 VOS_STATUS status;
4277 spin_lock(&pHddCtx->hddAdapters.lock);
4278 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4279 &pAdapterNode->node );
4280 spin_unlock(&pHddCtx->hddAdapters.lock);
4281 return status;
4282}
4283
4284VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4285 hdd_adapter_list_node_t** ppAdapterNode)
4286{
4287 VOS_STATUS status;
4288 spin_lock(&pHddCtx->hddAdapters.lock);
4289 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4290 (hdd_list_node_t**) ppAdapterNode );
4291 spin_unlock(&pHddCtx->hddAdapters.lock);
4292 return status;
4293}
4294
4295VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4296 hdd_adapter_list_node_t* pAdapterNode)
4297{
4298 VOS_STATUS status;
4299 spin_lock(&pHddCtx->hddAdapters.lock);
4300 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4301 (hdd_list_node_t*) pAdapterNode );
4302 spin_unlock(&pHddCtx->hddAdapters.lock);
4303 return status;
4304}
4305
4306VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4307 hdd_adapter_list_node_t* pAdapterNode)
4308{
4309 VOS_STATUS status;
4310 spin_lock(&pHddCtx->hddAdapters.lock);
4311 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4312 (hdd_list_node_t*) pAdapterNode );
4313 spin_unlock(&pHddCtx->hddAdapters.lock);
4314 return status;
4315}
4316
4317hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4318 tSirMacAddr macAddr )
4319{
4320 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4321 hdd_adapter_t *pAdapter;
4322 VOS_STATUS status;
4323
4324 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4325
4326 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4327 {
4328 pAdapter = pAdapterNode->pAdapter;
4329
4330 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4331 macAddr, sizeof(tSirMacAddr) ) )
4332 {
4333 return pAdapter;
4334 }
4335 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4336 pAdapterNode = pNext;
4337 }
4338
4339 return NULL;
4340
4341}
4342
4343hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4344{
4345 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4346 hdd_adapter_t *pAdapter;
4347 VOS_STATUS status;
4348
4349 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4350
4351 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4352 {
4353 pAdapter = pAdapterNode->pAdapter;
4354
4355 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4356 IFNAMSIZ ) )
4357 {
4358 return pAdapter;
4359 }
4360 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4361 pAdapterNode = pNext;
4362 }
4363
4364 return NULL;
4365
4366}
4367
4368hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4369{
4370 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4371 hdd_adapter_t *pAdapter;
4372 VOS_STATUS status;
4373
4374 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4375
4376 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4377 {
4378 pAdapter = pAdapterNode->pAdapter;
4379
4380 if( pAdapter && (mode == pAdapter->device_mode) )
4381 {
4382 return pAdapter;
4383 }
4384 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4385 pAdapterNode = pNext;
4386 }
4387
4388 return NULL;
4389
4390}
4391
4392//Remove this function later
4393hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4394{
4395 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4396 hdd_adapter_t *pAdapter;
4397 VOS_STATUS status;
4398
4399 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4400
4401 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4402 {
4403 pAdapter = pAdapterNode->pAdapter;
4404
4405 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4406 {
4407 return pAdapter;
4408 }
4409
4410 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4411 pAdapterNode = pNext;
4412 }
4413
4414 return NULL;
4415
4416}
4417
Jeff Johnson295189b2012-06-20 16:38:30 -07004418/**---------------------------------------------------------------------------
4419
4420 \brief hdd_set_monitor_tx_adapter() -
4421
4422 This API initializes the adapter to be used while transmitting on monitor
4423 adapter.
4424
4425 \param - pHddCtx - Pointer to the HDD context.
4426 pAdapter - Adapter that will used for TX. This can be NULL.
4427 \return - None.
4428 --------------------------------------------------------------------------*/
4429void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4430{
4431 hdd_adapter_t *pMonAdapter;
4432
4433 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4434
4435 if( NULL != pMonAdapter )
4436 {
4437 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4438 }
4439}
Jeff Johnson295189b2012-06-20 16:38:30 -07004440/**---------------------------------------------------------------------------
4441
4442 \brief hdd_select_queue() -
4443
4444 This API returns the operating channel of the requested device mode
4445
4446 \param - pHddCtx - Pointer to the HDD context.
4447 - mode - Device mode for which operating channel is required
4448 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4449 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4450 \return - channel number. "0" id the requested device is not found OR it is not connected.
4451 --------------------------------------------------------------------------*/
4452v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4453{
4454 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4455 VOS_STATUS status;
4456 hdd_adapter_t *pAdapter;
4457 v_U8_t operatingChannel = 0;
4458
4459 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4460
4461 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4462 {
4463 pAdapter = pAdapterNode->pAdapter;
4464
4465 if( mode == pAdapter->device_mode )
4466 {
4467 switch(pAdapter->device_mode)
4468 {
4469 case WLAN_HDD_INFRA_STATION:
4470 case WLAN_HDD_P2P_CLIENT:
4471 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4472 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4473 break;
4474 case WLAN_HDD_SOFTAP:
4475 case WLAN_HDD_P2P_GO:
4476 /*softap connection info */
4477 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4478 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4479 break;
4480 default:
4481 break;
4482 }
4483
4484 break; //Found the device of interest. break the loop
4485 }
4486
4487 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4488 pAdapterNode = pNext;
4489 }
4490 return operatingChannel;
4491}
4492
4493#ifdef WLAN_FEATURE_PACKET_FILTERING
4494/**---------------------------------------------------------------------------
4495
4496 \brief hdd_set_multicast_list() -
4497
4498 This used to set the multicast address list.
4499
4500 \param - dev - Pointer to the WLAN device.
4501 - skb - Pointer to OS packet (sk_buff).
4502 \return - success/fail
4503
4504 --------------------------------------------------------------------------*/
4505static void hdd_set_multicast_list(struct net_device *dev)
4506{
4507 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004508 int mc_count;
4509 int i = 0;
4510 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304511
4512 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 {
4514 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304515 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 return;
4517 }
4518
4519 if (dev->flags & IFF_ALLMULTI)
4520 {
4521 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004522 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304523 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004524 }
4525 else
4526 {
4527 mc_count = netdev_mc_count(dev);
4528 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004529 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4531 {
4532 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004533 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304534 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004535 return;
4536 }
4537
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304538 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004539
4540 netdev_for_each_mc_addr(ha, dev) {
4541 if (i == mc_count)
4542 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304543 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4544 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4545 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004546 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304547 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 i++;
4549 }
4550 }
4551 return;
4552}
4553#endif
4554
4555/**---------------------------------------------------------------------------
4556
4557 \brief hdd_select_queue() -
4558
4559 This function is registered with the Linux OS for network
4560 core to decide which queue to use first.
4561
4562 \param - dev - Pointer to the WLAN device.
4563 - skb - Pointer to OS packet (sk_buff).
4564 \return - ac, Queue Index/access category corresponding to UP in IP header
4565
4566 --------------------------------------------------------------------------*/
4567v_U16_t hdd_select_queue(struct net_device *dev,
4568 struct sk_buff *skb)
4569{
4570 return hdd_wmm_select_queue(dev, skb);
4571}
4572
4573
4574/**---------------------------------------------------------------------------
4575
4576 \brief hdd_wlan_initial_scan() -
4577
4578 This function triggers the initial scan
4579
4580 \param - pAdapter - Pointer to the HDD adapter.
4581
4582 --------------------------------------------------------------------------*/
4583void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4584{
4585 tCsrScanRequest scanReq;
4586 tCsrChannelInfo channelInfo;
4587 eHalStatus halStatus;
4588 unsigned long scanId;
4589 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4590
4591 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4592 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4593 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4594
4595 if(sme_Is11dSupported(pHddCtx->hHal))
4596 {
4597 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4598 if ( HAL_STATUS_SUCCESS( halStatus ) )
4599 {
4600 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4601 if( !scanReq.ChannelInfo.ChannelList )
4602 {
4603 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4604 vos_mem_free(channelInfo.ChannelList);
4605 return;
4606 }
4607 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4608 channelInfo.numOfChannels);
4609 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4610 vos_mem_free(channelInfo.ChannelList);
4611 }
4612
4613 scanReq.scanType = eSIR_PASSIVE_SCAN;
4614 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4615 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4616 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4617 }
4618 else
4619 {
4620 scanReq.scanType = eSIR_ACTIVE_SCAN;
4621 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4622 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4623 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4624 }
4625
4626 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4627 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4628 {
4629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4630 __func__, halStatus );
4631 }
4632
4633 if(sme_Is11dSupported(pHddCtx->hHal))
4634 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4635}
4636
4637struct fullPowerContext
4638{
4639 struct completion completion;
4640 unsigned int magic;
4641};
4642#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4643
4644/**---------------------------------------------------------------------------
4645
4646 \brief hdd_full_power_callback() - HDD full power callback function
4647
4648 This is the function invoked by SME to inform the result of a full power
4649 request issued by HDD
4650
4651 \param - callbackcontext - Pointer to cookie
4652 \param - status - result of request
4653
4654 \return - None
4655
4656 --------------------------------------------------------------------------*/
4657static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4658{
4659 struct fullPowerContext *pContext = callbackContext;
4660
4661 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304662 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004663
4664 if (NULL == callbackContext)
4665 {
4666 hddLog(VOS_TRACE_LEVEL_ERROR,
4667 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004668 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 return;
4670 }
4671
4672 /* there is a race condition that exists between this callback function
4673 and the caller since the caller could time out either before or
4674 while this code is executing. we'll assume the timeout hasn't
4675 occurred, but we'll verify that right before we save our work */
4676
4677 if (POWER_CONTEXT_MAGIC != pContext->magic)
4678 {
4679 /* the caller presumably timed out so there is nothing we can do */
4680 hddLog(VOS_TRACE_LEVEL_WARN,
4681 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004682 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004683 return;
4684 }
4685
4686 /* the race is on. caller could have timed out immediately after
4687 we verified the magic, but if so, caller will wait a short time
4688 for us to notify the caller, so the context will stay valid */
4689 complete(&pContext->completion);
4690}
4691
4692/**---------------------------------------------------------------------------
4693
4694 \brief hdd_wlan_exit() - HDD WLAN exit function
4695
4696 This is the driver exit point (invoked during rmmod)
4697
4698 \param - pHddCtx - Pointer to the HDD Context
4699
4700 \return - None
4701
4702 --------------------------------------------------------------------------*/
4703void hdd_wlan_exit(hdd_context_t *pHddCtx)
4704{
4705 eHalStatus halStatus;
4706 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4707 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304708 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004709 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 struct fullPowerContext powerContext;
4711 long lrc;
4712
4713 ENTER();
4714
Jeff Johnson88ba7742013-02-27 14:36:02 -08004715 if (VOS_FTM_MODE != hdd_get_conparam())
4716 {
4717 // Unloading, restart logic is no more required.
4718 wlan_hdd_restart_deinit(pHddCtx);
4719 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004720
Jeff Johnson295189b2012-06-20 16:38:30 -07004721 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004722 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004724 {
4725 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4726 WLAN_HDD_INFRA_STATION);
4727 if (pAdapter == NULL)
4728 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4729
4730 if (pAdapter != NULL)
4731 {
4732 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4733 hdd_UnregisterWext(pAdapter->dev);
4734 }
4735 }
4736 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004737
Jeff Johnson295189b2012-06-20 16:38:30 -07004738 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004739 {
4740 wlan_hdd_ftm_close(pHddCtx);
4741 goto free_hdd_ctx;
4742 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004743 //Stop the Interface TX queue.
4744 //netif_tx_disable(pWlanDev);
4745 //netif_carrier_off(pWlanDev);
4746
Jeff Johnson295189b2012-06-20 16:38:30 -07004747 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4748 {
4749 pAdapter = hdd_get_adapter(pHddCtx,
4750 WLAN_HDD_SOFTAP);
4751 }
4752 else
4753 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004754 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 {
4756 pAdapter = hdd_get_adapter(pHddCtx,
4757 WLAN_HDD_INFRA_STATION);
4758 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004759 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004760 /* DeRegister with platform driver as client for Suspend/Resume */
4761 vosStatus = hddDeregisterPmOps(pHddCtx);
4762 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4763 {
4764 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4765 VOS_ASSERT(0);
4766 }
4767
4768 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4769 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4770 {
4771 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4772 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004773
4774 // Cancel any outstanding scan requests. We are about to close all
4775 // of our adapters, but an adapter structure is what SME passes back
4776 // to our callback function. Hence if there are any outstanding scan
4777 // requests then there is a race condition between when the adapter
4778 // is closed and when the callback is invoked. We try to resolve that
4779 // race condition here by canceling any outstanding scans before we
4780 // close the adapters.
4781 // Note that the scans may be cancelled in an asynchronous manner, so
4782 // ideally there needs to be some kind of synchronization. Rather than
4783 // introduce a new synchronization here, we will utilize the fact that
4784 // we are about to Request Full Power, and since that is synchronized,
4785 // the expectation is that by the time Request Full Power has completed,
4786 // all scans will be cancelled.
4787 hdd_abort_mac_scan( pHddCtx );
4788
4789 //Disable IMPS/BMPS as we do not want the device to enter any power
4790 //save mode during shutdown
4791 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4792 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4793 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4794
4795 //Ensure that device is in full power as we will touch H/W during vos_Stop
4796 init_completion(&powerContext.completion);
4797 powerContext.magic = POWER_CONTEXT_MAGIC;
4798
4799 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4800 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4801
4802 if (eHAL_STATUS_SUCCESS != halStatus)
4803 {
4804 if (eHAL_STATUS_PMC_PENDING == halStatus)
4805 {
4806 /* request was sent -- wait for the response */
4807 lrc = wait_for_completion_interruptible_timeout(
4808 &powerContext.completion,
4809 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4810 /* either we have a response or we timed out
4811 either way, first invalidate our magic */
4812 powerContext.magic = 0;
4813 if (lrc <= 0)
4814 {
4815 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004816 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004817 /* there is a race condition such that the callback
4818 function could be executing at the same time we are. of
4819 primary concern is if the callback function had already
4820 verified the "magic" but hasn't yet set the completion
4821 variable. Since the completion variable is on our
4822 stack, we'll delay just a bit to make sure the data is
4823 still valid if that is the case */
4824 msleep(50);
4825 }
4826 }
4827 else
4828 {
4829 hddLog(VOS_TRACE_LEVEL_ERROR,
4830 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004831 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004832 VOS_ASSERT(0);
4833 /* continue -- need to clean up as much as possible */
4834 }
4835 }
4836
4837 // Unregister the Net Device Notifier
4838 unregister_netdevice_notifier(&hdd_netdev_notifier);
4839
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 hdd_stop_all_adapters( pHddCtx );
4841
Jeff Johnson295189b2012-06-20 16:38:30 -07004842#ifdef WLAN_BTAMP_FEATURE
4843 vosStatus = WLANBAP_Stop(pVosContext);
4844 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4845 {
4846 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4847 "%s: Failed to stop BAP",__func__);
4848 }
4849#endif //WLAN_BTAMP_FEATURE
4850
4851 //Stop all the modules
4852 vosStatus = vos_stop( pVosContext );
4853 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4854 {
4855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4856 "%s: Failed to stop VOSS",__func__);
4857 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4858 }
4859
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 //Assert Deep sleep signal now to put Libra HW in lowest power state
4861 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4862 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4863
4864 //Vote off any PMIC voltage supplies
4865 vos_chipPowerDown(NULL, NULL, NULL);
4866
4867 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4868
4869 //Clean up HDD Nlink Service
4870 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4871 nl_srv_exit();
4872
4873 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004875
4876 //Close the scheduler before calling vos_close to make sure no thread is
4877 // scheduled after the each module close is called i.e after all the data
4878 // structures are freed.
4879 vosStatus = vos_sched_close( pVosContext );
4880 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4881 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4882 "%s: Failed to close VOSS Scheduler",__func__);
4883 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4884 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004885#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004886#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4887 /* Destroy the wake lock */
4888 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4889#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004890 /* Destroy the wake lock */
4891 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004892#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004893
4894 //Close VOSS
4895 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4896 vos_close(pVosContext);
4897
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 //Close Watchdog
4899 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4900 vos_watchdog_close(pVosContext);
4901
4902 /* Cancel the vote for XO Core ON.
4903 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4904 * exited at this point
4905 */
4906 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4907 " when WLAN is turned OFF\n");
4908 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4909 {
4910 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4911 " Not returning failure."
4912 " Power consumed will be high\n");
4913 }
4914
4915 hdd_close_all_adapters( pHddCtx );
4916
4917
4918 //Free up dynamically allocated members inside HDD Adapter
4919 kfree(pHddCtx->cfg_ini);
4920 pHddCtx->cfg_ini= NULL;
4921
4922 /* free the power on lock from platform driver */
4923 if (free_riva_power_on_lock("wlan"))
4924 {
4925 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4926 __func__);
4927 }
4928
Jeff Johnson88ba7742013-02-27 14:36:02 -08004929free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004930 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 if (hdd_is_ssr_required())
4933 {
4934 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004935 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004936 msleep(5000);
4937 }
4938 hdd_set_ssr_required (VOS_FALSE);
4939}
4940
4941
4942/**---------------------------------------------------------------------------
4943
4944 \brief hdd_update_config_from_nv() - Function to update the contents of
4945 the running configuration with parameters taken from NV storage
4946
4947 \param - pHddCtx - Pointer to the HDD global context
4948
4949 \return - VOS_STATUS_SUCCESS if successful
4950
4951 --------------------------------------------------------------------------*/
4952static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4953{
Jeff Johnson295189b2012-06-20 16:38:30 -07004954 v_BOOL_t itemIsValid = VOS_FALSE;
4955 VOS_STATUS status;
4956 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4957 v_U8_t macLoop;
4958
4959 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4960 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4961 if(status != VOS_STATUS_SUCCESS)
4962 {
4963 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4964 return VOS_STATUS_E_FAILURE;
4965 }
4966
4967 if (itemIsValid == VOS_TRUE)
4968 {
4969 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4970 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4971 VOS_MAX_CONCURRENCY_PERSONA);
4972 if(status != VOS_STATUS_SUCCESS)
4973 {
4974 /* Get MAC from NV fail, not update CFG info
4975 * INI MAC value will be used for MAC setting */
4976 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4977 return VOS_STATUS_E_FAILURE;
4978 }
4979
4980 /* If first MAC is not valid, treat all others are not valid
4981 * Then all MACs will be got from ini file */
4982 if(vos_is_macaddr_zero(&macFromNV[0]))
4983 {
4984 /* MAC address in NV file is not configured yet */
4985 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4986 return VOS_STATUS_E_INVAL;
4987 }
4988
4989 /* Get MAC address from NV, update CFG info */
4990 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4991 {
4992 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4993 {
4994 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4995 /* This MAC is not valid, skip it
4996 * This MAC will be got from ini file */
4997 }
4998 else
4999 {
5000 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5001 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5002 VOS_MAC_ADDR_SIZE);
5003 }
5004 }
5005 }
5006 else
5007 {
5008 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5009 return VOS_STATUS_E_FAILURE;
5010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005011
Jeff Johnson295189b2012-06-20 16:38:30 -07005012
5013 return VOS_STATUS_SUCCESS;
5014}
5015
5016/**---------------------------------------------------------------------------
5017
5018 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5019
5020 \param - pAdapter - Pointer to the HDD
5021
5022 \return - None
5023
5024 --------------------------------------------------------------------------*/
5025VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5026{
5027 eHalStatus halStatus;
5028 v_U32_t listenInterval;
5029
Jeff Johnson295189b2012-06-20 16:38:30 -07005030
5031 // Send ready indication to the HDD. This will kick off the MAC
5032 // into a 'running' state and should kick off an initial scan.
5033 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5034 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5035 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305036 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 "code %08d [x%08x]",__func__, halStatus, halStatus );
5038 return VOS_STATUS_E_FAILURE;
5039 }
5040
5041 // Set default LI into HDD context,
5042 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5043 // And RIVA will crash
5044 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5045 pHddCtx->hdd_actual_LI_value = listenInterval;
5046
5047 return VOS_STATUS_SUCCESS;
5048}
5049
Jeff Johnson295189b2012-06-20 16:38:30 -07005050/* wake lock APIs for HDD */
5051void hdd_prevent_suspend(void)
5052{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005053#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005055#else
5056 wcnss_prevent_suspend();
5057#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005058}
5059
5060void hdd_allow_suspend(void)
5061{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005062#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005063 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005064#else
5065 wcnss_allow_suspend();
5066#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005067}
5068
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005069void hdd_allow_suspend_timeout(v_U32_t timeout)
5070{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005071#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005072 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005073#else
5074 /* Do nothing as there is no API in wcnss for timeout*/
5075#endif
5076}
5077
Jeff Johnson295189b2012-06-20 16:38:30 -07005078/**---------------------------------------------------------------------------
5079
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005080 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5081 information between Host and Riva
5082
5083 This function gets reported version of FW
5084 It also finds the version of Riva headers used to compile the host
5085 It compares the above two and prints a warning if they are different
5086 It gets the SW and HW version string
5087 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5088 indicating the features they support through a bitmap
5089
5090 \param - pHddCtx - Pointer to HDD context
5091
5092 \return - void
5093
5094 --------------------------------------------------------------------------*/
5095
5096void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5097{
5098
5099 tSirVersionType versionCompiled;
5100 tSirVersionType versionReported;
5101 tSirVersionString versionString;
5102 tANI_U8 fwFeatCapsMsgSupported = 0;
5103 VOS_STATUS vstatus;
5104
5105 /* retrieve and display WCNSS version information */
5106 do {
5107
5108 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5109 &versionCompiled);
5110 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5111 {
5112 hddLog(VOS_TRACE_LEVEL_FATAL,
5113 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005114 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005115 break;
5116 }
5117
5118 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5119 &versionReported);
5120 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5121 {
5122 hddLog(VOS_TRACE_LEVEL_FATAL,
5123 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005124 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005125 break;
5126 }
5127
5128 if ((versionCompiled.major != versionReported.major) ||
5129 (versionCompiled.minor != versionReported.minor) ||
5130 (versionCompiled.version != versionReported.version) ||
5131 (versionCompiled.revision != versionReported.revision))
5132 {
5133 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5134 "Host expected %u.%u.%u.%u\n",
5135 WLAN_MODULE_NAME,
5136 (int)versionReported.major,
5137 (int)versionReported.minor,
5138 (int)versionReported.version,
5139 (int)versionReported.revision,
5140 (int)versionCompiled.major,
5141 (int)versionCompiled.minor,
5142 (int)versionCompiled.version,
5143 (int)versionCompiled.revision);
5144 }
5145 else
5146 {
5147 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5148 WLAN_MODULE_NAME,
5149 (int)versionReported.major,
5150 (int)versionReported.minor,
5151 (int)versionReported.version,
5152 (int)versionReported.revision);
5153 }
5154
5155 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5156 versionString,
5157 sizeof(versionString));
5158 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5159 {
5160 hddLog(VOS_TRACE_LEVEL_FATAL,
5161 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005162 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005163 break;
5164 }
5165
5166 pr_info("%s: WCNSS software version %s\n",
5167 WLAN_MODULE_NAME, versionString);
5168
5169 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5170 versionString,
5171 sizeof(versionString));
5172 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5173 {
5174 hddLog(VOS_TRACE_LEVEL_FATAL,
5175 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005176 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005177 break;
5178 }
5179
5180 pr_info("%s: WCNSS hardware version %s\n",
5181 WLAN_MODULE_NAME, versionString);
5182
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005183 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5184 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005185 send the message only if it the riva is 1.1
5186 minor numbers for different riva branches:
5187 0 -> (1.0)Mainline Build
5188 1 -> (1.1)Mainline Build
5189 2->(1.04) Stability Build
5190 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005191 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005192 ((versionReported.minor>=1) && (versionReported.version>=1)))
5193 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5194 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005195
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005196 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005197 {
5198#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5199 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5200 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5201#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005202 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005203 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005204
5205 } while (0);
5206
5207}
5208
5209/**---------------------------------------------------------------------------
5210
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 \brief hdd_wlan_startup() - HDD init function
5212
5213 This is the driver startup code executed once a WLAN device has been detected
5214
5215 \param - dev - Pointer to the underlying device
5216
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005217 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005218
5219 --------------------------------------------------------------------------*/
5220
5221int hdd_wlan_startup(struct device *dev )
5222{
5223 VOS_STATUS status;
5224 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005225 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005226 hdd_context_t *pHddCtx = NULL;
5227 v_CONTEXT_t pVosContext= NULL;
5228#ifdef WLAN_BTAMP_FEATURE
5229 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5230 WLANBAP_ConfigType btAmpConfig;
5231 hdd_config_t *pConfig;
5232#endif
5233 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005235
5236 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 /*
5238 * cfg80211: wiphy allocation
5239 */
5240 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5241
5242 if(wiphy == NULL)
5243 {
5244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005245 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 }
5247
5248 pHddCtx = wiphy_priv(wiphy);
5249
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 //Initialize the adapter context to zeros.
5251 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5252
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005254 hdd_prevent_suspend();
5255 pHddCtx->isLoadUnloadInProgress = TRUE;
5256
5257 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5258
5259 /*Get vos context here bcoz vos_open requires it*/
5260 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5261
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005262 if(pVosContext == NULL)
5263 {
5264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5265 goto err_free_hdd_context;
5266 }
5267
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 //Save the Global VOSS context in adapter context for future.
5269 pHddCtx->pvosContext = pVosContext;
5270
5271 //Save the adapter context in global context for future.
5272 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5273
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 pHddCtx->parent_dev = dev;
5275
5276 init_completion(&pHddCtx->full_pwr_comp_var);
5277 init_completion(&pHddCtx->standby_comp_var);
5278 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005279 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005280 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005281
5282 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5283
5284 // Load all config first as TL config is needed during vos_open
5285 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5286 if(pHddCtx->cfg_ini == NULL)
5287 {
5288 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5289 goto err_free_hdd_context;
5290 }
5291
5292 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5293
5294 // Read and parse the qcom_cfg.ini file
5295 status = hdd_parse_config_ini( pHddCtx );
5296 if ( VOS_STATUS_SUCCESS != status )
5297 {
5298 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5299 __func__, WLAN_INI_FILE);
5300 goto err_config;
5301 }
5302
Jeff Johnson295189b2012-06-20 16:38:30 -07005303 /*
5304 * cfg80211: Initialization and registration ...
5305 */
5306 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5307 {
5308 hddLog(VOS_TRACE_LEVEL_FATAL,
5309 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5310 goto err_wiphy_reg;
5311 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005312
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005313 // Update VOS trace levels based upon the cfg.ini
5314 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5315 pHddCtx->cfg_ini->vosTraceEnableBAP);
5316 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5317 pHddCtx->cfg_ini->vosTraceEnableTL);
5318 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5319 pHddCtx->cfg_ini->vosTraceEnableWDI);
5320 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5321 pHddCtx->cfg_ini->vosTraceEnableHDD);
5322 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5323 pHddCtx->cfg_ini->vosTraceEnableSME);
5324 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5325 pHddCtx->cfg_ini->vosTraceEnablePE);
5326 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5327 pHddCtx->cfg_ini->vosTraceEnableWDA);
5328 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5329 pHddCtx->cfg_ini->vosTraceEnableSYS);
5330 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5331 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005332 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5333 pHddCtx->cfg_ini->vosTraceEnableSAP);
5334 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5335 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005336
Jeff Johnson295189b2012-06-20 16:38:30 -07005337 // Update WDI trace levels based upon the cfg.ini
5338 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5339 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5340 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5341 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5342 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5343 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5344 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5345 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005346
Jeff Johnson88ba7742013-02-27 14:36:02 -08005347 if (VOS_FTM_MODE == hdd_get_conparam())
5348 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005349 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5350 {
5351 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5352 goto err_free_hdd_context;
5353 }
5354 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5355 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005357
Jeff Johnson88ba7742013-02-27 14:36:02 -08005358 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5360 {
5361 status = vos_watchdog_open(pVosContext,
5362 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5363
5364 if(!VOS_IS_STATUS_SUCCESS( status ))
5365 {
5366 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005367 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 }
5369 }
5370
5371 pHddCtx->isLogpInProgress = FALSE;
5372 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5373
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5375 if(!VOS_IS_STATUS_SUCCESS(status))
5376 {
5377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 }
5380
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 status = vos_open( &pVosContext, 0);
5382 if ( !VOS_IS_STATUS_SUCCESS( status ))
5383 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005384 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5385 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 }
5387
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5389
5390 if ( NULL == pHddCtx->hHal )
5391 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005392 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 goto err_vosclose;
5394 }
5395
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005396 status = vos_preStart( pHddCtx->pvosContext );
5397 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5398 {
5399 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5400 goto err_vosclose;
5401 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005402
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005403 /* Note that the vos_preStart() sequence triggers the cfg download.
5404 The cfg download must occur before we update the SME config
5405 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 status = hdd_set_sme_config( pHddCtx );
5407
5408 if ( VOS_STATUS_SUCCESS != status )
5409 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005410 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5411 goto err_vosclose;
5412 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005413
5414 //Initialize the WMM module
5415 status = hdd_wmm_init(pHddCtx);
5416 if (!VOS_IS_STATUS_SUCCESS(status))
5417 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005418 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 goto err_vosclose;
5420 }
5421
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 /* In the integrated architecture we update the configuration from
5423 the INI file and from NV before vOSS has been started so that
5424 the final contents are available to send down to the cCPU */
5425
5426 // Apply the cfg.ini to cfg.dat
5427 if (FALSE == hdd_update_config_dat(pHddCtx))
5428 {
5429 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5430 goto err_vosclose;
5431 }
5432
5433 // Apply the NV to cfg.dat
5434 /* Prima Update MAC address only at here */
5435 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5436 {
5437#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5438 /* There was not a valid set of MAC Addresses in NV. See if the
5439 default addresses were modified by the cfg.ini settings. If so,
5440 we'll use them, but if not, we'll autogenerate a set of MAC
5441 addresses based upon the device serial number */
5442
5443 static const v_MACADDR_t default_address =
5444 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5445 unsigned int serialno;
5446 int i;
5447
5448 serialno = wcnss_get_serial_number();
5449 if ((0 != serialno) &&
5450 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5451 sizeof(default_address))))
5452 {
5453 /* cfg.ini has the default address, invoke autogen logic */
5454
5455 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5456 bytes of the serial number that can be used to generate
5457 the other 3 bytes of the MAC address. Mask off all but
5458 the lower 3 bytes (this will also make sure we don't
5459 overflow in the next step) */
5460 serialno &= 0x00FFFFFF;
5461
5462 /* we need a unique address for each session */
5463 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5464
5465 /* autogen all addresses */
5466 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5467 {
5468 /* start with the entire default address */
5469 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5470 /* then replace the lower 3 bytes */
5471 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5472 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5473 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5474
5475 serialno++;
5476 }
5477
5478 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5479 MAC_ADDRESS_STR,
5480 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5481 }
5482 else
5483#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5484 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005485 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 "%s: Invalid MAC address in NV, using MAC from ini file "
5487 MAC_ADDRESS_STR, __func__,
5488 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5489 }
5490 }
5491 {
5492 eHalStatus halStatus;
5493 // Set the MAC Address
5494 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5495 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5496 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5497 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5498
5499 if (!HAL_STATUS_SUCCESS( halStatus ))
5500 {
5501 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5502 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005503 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 }
5505 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005506
5507 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5508 Note: Firmware image will be read and downloaded inside vos_start API */
5509 status = vos_start( pHddCtx->pvosContext );
5510 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5511 {
5512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5513 goto err_vosclose;
5514 }
5515
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005516 /* Exchange capability info between Host and FW and also get versioning info from FW */
5517 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005518
5519 status = hdd_post_voss_start_config( pHddCtx );
5520 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5521 {
5522 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5523 __func__);
5524 goto err_vosstop;
5525 }
5526
Jeff Johnson295189b2012-06-20 16:38:30 -07005527 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5528 {
5529 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5530 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5531 }
5532 else
5533 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5535 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5536 if (pAdapter != NULL)
5537 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305538 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305540 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5541 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5542 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005543
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305544 /* Generate the P2P Device Address. This consists of the device's
5545 * primary MAC address with the locally administered bit set.
5546 */
5547 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005548 }
5549 else
5550 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305551 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5552 if (p2p_dev_addr != NULL)
5553 {
5554 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5555 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5556 }
5557 else
5558 {
5559 hddLog(VOS_TRACE_LEVEL_FATAL,
5560 "%s: Failed to allocate mac_address for p2p_device",
5561 __func__);
5562 goto err_close_adapter;
5563 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005565
5566 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5567 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5568 if ( NULL == pP2pAdapter )
5569 {
5570 hddLog(VOS_TRACE_LEVEL_FATAL,
5571 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005572 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005573 goto err_close_adapter;
5574 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005575 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005577
5578 if( pAdapter == NULL )
5579 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5581 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005582 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005583
Jeff Johnson295189b2012-06-20 16:38:30 -07005584#ifdef WLAN_BTAMP_FEATURE
5585 vStatus = WLANBAP_Open(pVosContext);
5586 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5587 {
5588 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5589 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005590 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 }
5592
5593 vStatus = BSL_Init(pVosContext);
5594 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5595 {
5596 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5597 "%s: Failed to Init BSL",__func__);
5598 goto err_bap_close;
5599 }
5600 vStatus = WLANBAP_Start(pVosContext);
5601 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5602 {
5603 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5604 "%s: Failed to start TL",__func__);
5605 goto err_bap_close;
5606 }
5607
5608 pConfig = pHddCtx->cfg_ini;
5609 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5610 status = WLANBAP_SetConfig(&btAmpConfig);
5611
5612#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005613
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005614#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5615 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5616 {
5617 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5618 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5619 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5620 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5621 }
5622#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005623#ifdef FEATURE_WLAN_SCAN_PNO
5624 /*SME must send channel update configuration to RIVA*/
5625 sme_UpdateChannelConfig(pHddCtx->hHal);
5626#endif
5627
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 /* Register with platform driver as client for Suspend/Resume */
5629 status = hddRegisterPmOps(pHddCtx);
5630 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5631 {
5632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5633#ifdef WLAN_BTAMP_FEATURE
5634 goto err_bap_stop;
5635#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005636 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005637#endif //WLAN_BTAMP_FEATURE
5638 }
5639
5640 /* Register TM level change handler function to the platform */
5641 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5642 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5643 {
5644 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5645 goto err_unregister_pmops;
5646 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005647
5648 /* register for riva power on lock to platform driver */
5649 if (req_riva_power_on_lock("wlan"))
5650 {
5651 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5652 __func__);
5653 goto err_unregister_pmops;
5654 }
5655
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 // register net device notifier for device change notification
5657 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5658
5659 if(ret < 0)
5660 {
5661 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5662 goto err_free_power_on_lock;
5663 }
5664
5665 //Initialize the nlink service
5666 if(nl_srv_init() != 0)
5667 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305668 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 goto err_reg_netdev;
5670 }
5671
5672 //Initialize the BTC service
5673 if(btc_activate_service(pHddCtx) != 0)
5674 {
5675 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5676 goto err_nl_srv;
5677 }
5678
5679#ifdef PTT_SOCK_SVC_ENABLE
5680 //Initialize the PTT service
5681 if(ptt_sock_activate_svc(pHddCtx) != 0)
5682 {
5683 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5684 goto err_nl_srv;
5685 }
5686#endif
5687
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005689 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005690 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005691 /* Action frame registered in one adapter which will
5692 * applicable to all interfaces
5693 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005694 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005695 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005696
5697 mutex_init(&pHddCtx->sap_lock);
5698
5699 pHddCtx->isLoadUnloadInProgress = FALSE;
5700
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005701#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005702#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5703 /* Initialize the wake lcok */
5704 wake_lock_init(&pHddCtx->rx_wake_lock,
5705 WAKE_LOCK_SUSPEND,
5706 "qcom_rx_wakelock");
5707#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005708 /* Initialize the wake lcok */
5709 wake_lock_init(&pHddCtx->sap_wake_lock,
5710 WAKE_LOCK_SUSPEND,
5711 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005712#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005713
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005714 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5715 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005716
5717 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5718 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005719
5720 // Initialize the restart logic
5721 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305722
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 goto success;
5724
5725err_nl_srv:
5726 nl_srv_exit();
5727
5728err_reg_netdev:
5729 unregister_netdevice_notifier(&hdd_netdev_notifier);
5730
5731err_free_power_on_lock:
5732 free_riva_power_on_lock("wlan");
5733
5734err_unregister_pmops:
5735 hddDevTmUnregisterNotifyCallback(pHddCtx);
5736 hddDeregisterPmOps(pHddCtx);
5737
5738#ifdef WLAN_BTAMP_FEATURE
5739err_bap_stop:
5740 WLANBAP_Stop(pVosContext);
5741#endif
5742
5743#ifdef WLAN_BTAMP_FEATURE
5744err_bap_close:
5745 WLANBAP_Close(pVosContext);
5746#endif
5747
Jeff Johnson295189b2012-06-20 16:38:30 -07005748err_close_adapter:
5749 hdd_close_all_adapters( pHddCtx );
5750
5751err_vosstop:
5752 vos_stop(pVosContext);
5753
5754err_vosclose:
5755 status = vos_sched_close( pVosContext );
5756 if (!VOS_IS_STATUS_SUCCESS(status)) {
5757 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5758 "%s: Failed to close VOSS Scheduler", __func__);
5759 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5760 }
5761 vos_close(pVosContext );
5762
Jeff Johnson295189b2012-06-20 16:38:30 -07005763err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005764 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005765
5766err_wdclose:
5767 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5768 vos_watchdog_close(pVosContext);
5769
Jeff Johnson295189b2012-06-20 16:38:30 -07005770err_wiphy_reg:
5771 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005772
5773err_config:
5774 kfree(pHddCtx->cfg_ini);
5775 pHddCtx->cfg_ini= NULL;
5776
5777err_free_hdd_context:
5778 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005779 wiphy_free(wiphy) ;
5780 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 VOS_BUG(1);
5782
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005783 if (hdd_is_ssr_required())
5784 {
5785 /* WDI timeout had happened during load, so SSR is needed here */
5786 subsystem_restart("wcnss");
5787 msleep(5000);
5788 }
5789 hdd_set_ssr_required (VOS_FALSE);
5790
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005791 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005792
5793success:
5794 EXIT();
5795 return 0;
5796}
5797
5798/**---------------------------------------------------------------------------
5799
Jeff Johnson32d95a32012-09-10 13:15:23 -07005800 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005801
Jeff Johnson32d95a32012-09-10 13:15:23 -07005802 This is the driver entry point - called in different timeline depending
5803 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005804
5805 \param - None
5806
5807 \return - 0 for success, non zero for failure
5808
5809 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005810static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005811{
5812 VOS_STATUS status;
5813 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 struct device *dev = NULL;
5815 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005816#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5817 int max_retries = 0;
5818#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005819
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305820#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5821 vos_wconn_trace_init();
5822#endif
5823
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 ENTER();
5825
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005826#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005828#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005829
5830 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5831 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5832
5833 //Power Up Libra WLAN card first if not already powered up
5834 status = vos_chipPowerUp(NULL,NULL,NULL);
5835 if (!VOS_IS_STATUS_SUCCESS(status))
5836 {
5837 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5838 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005839 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 }
5841
Jeff Johnson295189b2012-06-20 16:38:30 -07005842#ifdef ANI_BUS_TYPE_PCI
5843
5844 dev = wcnss_wlan_get_device();
5845
5846#endif // ANI_BUS_TYPE_PCI
5847
5848#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005849
5850#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5851 /* wait until WCNSS driver downloads NV */
5852 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5853 msleep(1000);
5854 }
5855 if (max_retries >= 5) {
5856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5857 return -ENODEV;
5858 }
5859#endif
5860
Jeff Johnson295189b2012-06-20 16:38:30 -07005861 dev = wcnss_wlan_get_device();
5862#endif // ANI_BUS_TYPE_PLATFORM
5863
5864
5865 do {
5866 if (NULL == dev) {
5867 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5868 ret_status = -1;
5869 break;
5870 }
5871
5872#ifdef MEMORY_DEBUG
5873 vos_mem_init();
5874#endif
5875
5876#ifdef TIMER_MANAGER
5877 vos_timer_manager_init();
5878#endif
5879
5880 /* Preopen VOSS so that it is ready to start at least SAL */
5881 status = vos_preOpen(&pVosContext);
5882
5883 if (!VOS_IS_STATUS_SUCCESS(status))
5884 {
5885 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5886 ret_status = -1;
5887 break;
5888 }
5889
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005890#ifndef MODULE
5891 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5892 */
5893 hdd_set_conparam((v_UINT_t)con_mode);
5894#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005895
5896 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005897 if (hdd_wlan_startup(dev))
5898 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005900 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 vos_preClose( &pVosContext );
5902 ret_status = -1;
5903 break;
5904 }
5905
5906 /* Cancel the vote for XO Core ON
5907 * This is done here for safety purposes in case we re-initialize without turning
5908 * it OFF in any error scenario.
5909 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005910 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005912 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005913 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5914 {
5915 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5916 " Power consumed will be high\n");
5917 }
5918 } while (0);
5919
5920 if (0 != ret_status)
5921 {
5922 //Assert Deep sleep signal now to put Libra HW in lowest power state
5923 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5924 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5925
5926 //Vote off any PMIC voltage supplies
5927 vos_chipPowerDown(NULL, NULL, NULL);
5928#ifdef TIMER_MANAGER
5929 vos_timer_exit();
5930#endif
5931#ifdef MEMORY_DEBUG
5932 vos_mem_exit();
5933#endif
5934
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005935#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005936 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005937#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5939 }
5940 else
5941 {
5942 //Send WLAN UP indication to Nlink Service
5943 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5944
5945 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5946
5947 }
5948
5949 EXIT();
5950
5951 return ret_status;
5952}
5953
Jeff Johnson32d95a32012-09-10 13:15:23 -07005954/**---------------------------------------------------------------------------
5955
5956 \brief hdd_module_init() - Init Function
5957
5958 This is the driver entry point (invoked when module is loaded using insmod)
5959
5960 \param - None
5961
5962 \return - 0 for success, non zero for failure
5963
5964 --------------------------------------------------------------------------*/
5965#ifdef MODULE
5966static int __init hdd_module_init ( void)
5967{
5968 return hdd_driver_init();
5969}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005970#else /* #ifdef MODULE */
5971static int __init hdd_module_init ( void)
5972{
5973 /* Driver initialization is delayed to fwpath_changed_handler */
5974 return 0;
5975}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005976#endif /* #ifdef MODULE */
5977
Jeff Johnson295189b2012-06-20 16:38:30 -07005978
5979/**---------------------------------------------------------------------------
5980
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005981 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005982
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005983 This is the driver exit point (invoked when module is unloaded using rmmod
5984 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005985
5986 \param - None
5987
5988 \return - None
5989
5990 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005991static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005992{
5993 hdd_context_t *pHddCtx = NULL;
5994 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005995
5996 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5997
5998 //Get the global vos context
5999 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6000
6001 if(!pVosContext)
6002 {
6003 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6004 goto done;
6005 }
6006
6007 //Get the HDD context.
6008 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6009
6010 if(!pHddCtx)
6011 {
6012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6013 }
6014 else
6015 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006016 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07006018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
6019 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 }
6021
6022 pHddCtx->isLoadUnloadInProgress = TRUE;
6023 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6024
6025 //Do all the cleanup before deregistering the driver
6026 hdd_wlan_exit(pHddCtx);
6027 }
6028
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 vos_preClose( &pVosContext );
6030
6031#ifdef TIMER_MANAGER
6032 vos_timer_exit();
6033#endif
6034#ifdef MEMORY_DEBUG
6035 vos_mem_exit();
6036#endif
6037
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306038#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6039 vos_wconn_trace_exit();
6040#endif
6041
Jeff Johnson295189b2012-06-20 16:38:30 -07006042done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006043#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006045#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6047}
6048
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006049/**---------------------------------------------------------------------------
6050
6051 \brief hdd_module_exit() - Exit function
6052
6053 This is the driver exit point (invoked when module is unloaded using rmmod)
6054
6055 \param - None
6056
6057 \return - None
6058
6059 --------------------------------------------------------------------------*/
6060static void __exit hdd_module_exit(void)
6061{
6062 hdd_driver_exit();
6063}
6064
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006065#ifdef MODULE
6066static int fwpath_changed_handler(const char *kmessage,
6067 struct kernel_param *kp)
6068{
Jeff Johnson76052702013-04-16 13:55:05 -07006069 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006070}
6071
6072static int con_mode_handler(const char *kmessage,
6073 struct kernel_param *kp)
6074{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006075 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006076}
6077#else /* #ifdef MODULE */
6078/**---------------------------------------------------------------------------
6079
Jeff Johnson76052702013-04-16 13:55:05 -07006080 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006081
Jeff Johnson76052702013-04-16 13:55:05 -07006082 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006083 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006084 - invoked when module parameter fwpath is modified from userspace to signal
6085 initializing the WLAN driver or when con_mode is modified from userspace
6086 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006087
6088 \return - 0 for success, non zero for failure
6089
6090 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006091static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006092{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006093 int ret_status;
6094
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006095 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006096 ret_status = hdd_driver_init();
6097 wlan_hdd_inited = ret_status ? 0 : 1;
6098 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006099 }
6100
6101 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006102
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006103 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006104
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006105 ret_status = hdd_driver_init();
6106 wlan_hdd_inited = ret_status ? 0 : 1;
6107 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006108}
6109
Jeff Johnson295189b2012-06-20 16:38:30 -07006110/**---------------------------------------------------------------------------
6111
Jeff Johnson76052702013-04-16 13:55:05 -07006112 \brief fwpath_changed_handler() - Handler Function
6113
6114 Handle changes to the fwpath parameter
6115
6116 \return - 0 for success, non zero for failure
6117
6118 --------------------------------------------------------------------------*/
6119static int fwpath_changed_handler(const char *kmessage,
6120 struct kernel_param *kp)
6121{
6122 int ret;
6123
6124 ret = param_set_copystring(kmessage, kp);
6125 if (0 == ret)
6126 ret = kickstart_driver();
6127 return ret;
6128}
6129
6130/**---------------------------------------------------------------------------
6131
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006132 \brief con_mode_handler() -
6133
6134 Handler function for module param con_mode when it is changed by userspace
6135 Dynamically linked - do nothing
6136 Statically linked - exit and init driver, as in rmmod and insmod
6137
Jeff Johnson76052702013-04-16 13:55:05 -07006138 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006139
Jeff Johnson76052702013-04-16 13:55:05 -07006140 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006141
6142 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006143static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006144{
Jeff Johnson76052702013-04-16 13:55:05 -07006145 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006146
Jeff Johnson76052702013-04-16 13:55:05 -07006147 ret = param_set_int(kmessage, kp);
6148 if (0 == ret)
6149 ret = kickstart_driver();
6150 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006151}
6152#endif /* #ifdef MODULE */
6153
6154/**---------------------------------------------------------------------------
6155
Jeff Johnson295189b2012-06-20 16:38:30 -07006156 \brief hdd_get_conparam() -
6157
6158 This is the driver exit point (invoked when module is unloaded using rmmod)
6159
6160 \param - None
6161
6162 \return - tVOS_CON_MODE
6163
6164 --------------------------------------------------------------------------*/
6165tVOS_CON_MODE hdd_get_conparam ( void )
6166{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006167#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006168 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006169#else
6170 return (tVOS_CON_MODE)curr_con_mode;
6171#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006172}
6173void hdd_set_conparam ( v_UINT_t newParam )
6174{
6175 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006176#ifndef MODULE
6177 curr_con_mode = con_mode;
6178#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006179}
6180/**---------------------------------------------------------------------------
6181
6182 \brief hdd_softap_sta_deauth() - function
6183
6184 This to take counter measure to handle deauth req from HDD
6185
6186 \param - pAdapter - Pointer to the HDD
6187
6188 \param - enable - boolean value
6189
6190 \return - None
6191
6192 --------------------------------------------------------------------------*/
6193
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006194VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006195{
Jeff Johnson295189b2012-06-20 16:38:30 -07006196 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006197 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006198
6199 ENTER();
6200
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306201 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006202
6203 //Ignore request to deauth bcmc station
6204 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006205 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006206
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006207 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006208
6209 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006210 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006211}
6212
6213/**---------------------------------------------------------------------------
6214
6215 \brief hdd_softap_sta_disassoc() - function
6216
6217 This to take counter measure to handle deauth req from HDD
6218
6219 \param - pAdapter - Pointer to the HDD
6220
6221 \param - enable - boolean value
6222
6223 \return - None
6224
6225 --------------------------------------------------------------------------*/
6226
6227void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6228{
6229 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6230
6231 ENTER();
6232
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306233 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006234
6235 //Ignore request to disassoc bcmc station
6236 if( pDestMacAddress[0] & 0x1 )
6237 return;
6238
6239 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6240}
6241
6242void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6243{
6244 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6245
6246 ENTER();
6247
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306248 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006249
6250 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6251}
6252
Jeff Johnson295189b2012-06-20 16:38:30 -07006253/**---------------------------------------------------------------------------
6254 *
6255 * \brief hdd_get__concurrency_mode() -
6256 *
6257 *
6258 * \param - None
6259 *
6260 * \return - CONCURRENCY MODE
6261 *
6262 * --------------------------------------------------------------------------*/
6263tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6264{
6265 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6266 hdd_context_t *pHddCtx;
6267
6268 if (NULL != pVosContext)
6269 {
6270 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6271 if (NULL != pHddCtx)
6272 {
6273 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6274 }
6275 }
6276
6277 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006278 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 return VOS_STA;
6280}
6281
6282/* Decide whether to allow/not the apps power collapse.
6283 * Allow apps power collapse if we are in connected state.
6284 * if not, allow only if we are in IMPS */
6285v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6286{
6287 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006288 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006289 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6291 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6292 hdd_adapter_t *pAdapter = NULL;
6293 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006294 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006295
Jeff Johnson295189b2012-06-20 16:38:30 -07006296 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6297 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
Yathish9f22e662012-12-10 14:21:35 -08006299 concurrent_state = hdd_get_concurrency_mode();
6300
6301#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6302 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6303 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6304 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6305 return TRUE;
6306#endif
6307
Jeff Johnson295189b2012-06-20 16:38:30 -07006308 /*loop through all adapters. TBD fix for Concurrency */
6309 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6310 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6311 {
6312 pAdapter = pAdapterNode->pAdapter;
6313 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6314 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6315 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006316 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006317 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006318 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006319 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6320 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006321 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006322 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006323 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6324 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 return FALSE;
6326 }
6327 }
6328 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6329 pAdapterNode = pNext;
6330 }
6331 return TRUE;
6332}
6333
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006334/* Decides whether to send suspend notification to Riva
6335 * if any adapter is in BMPS; then it is required */
6336v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6337{
6338 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6339 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6340
6341 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6342 {
6343 return TRUE;
6344 }
6345 return FALSE;
6346}
6347
Jeff Johnson295189b2012-06-20 16:38:30 -07006348void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6349{
6350 switch(mode)
6351 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006352 case VOS_STA_MODE:
6353 case VOS_P2P_CLIENT_MODE:
6354 case VOS_P2P_GO_MODE:
6355 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006356 pHddCtx->concurrency_mode |= (1 << mode);
6357 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006358 break;
6359 default:
6360 break;
6361
6362 }
6363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6364 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6365}
6366
6367
6368void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6369{
6370 switch(mode)
6371 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006372 case VOS_STA_MODE:
6373 case VOS_P2P_CLIENT_MODE:
6374 case VOS_P2P_GO_MODE:
6375 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006376 pHddCtx->no_of_sessions[mode]--;
6377 if (!(pHddCtx->no_of_sessions[mode]))
6378 pHddCtx->concurrency_mode &= (~(1 << mode));
6379 break;
6380 default:
6381 break;
6382 }
6383 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6384 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6385}
6386
Jeff Johnsone7245742012-09-05 17:12:55 -07006387/**---------------------------------------------------------------------------
6388 *
6389 * \brief wlan_hdd_restart_init
6390 *
6391 * This function initalizes restart timer/flag. An internal function.
6392 *
6393 * \param - pHddCtx
6394 *
6395 * \return - None
6396 *
6397 * --------------------------------------------------------------------------*/
6398
6399static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6400{
6401 /* Initialize */
6402 pHddCtx->hdd_restart_retries = 0;
6403 atomic_set(&pHddCtx->isRestartInProgress, 0);
6404 vos_timer_init(&pHddCtx->hdd_restart_timer,
6405 VOS_TIMER_TYPE_SW,
6406 wlan_hdd_restart_timer_cb,
6407 pHddCtx);
6408}
6409/**---------------------------------------------------------------------------
6410 *
6411 * \brief wlan_hdd_restart_deinit
6412 *
6413 * This function cleans up the resources used. An internal function.
6414 *
6415 * \param - pHddCtx
6416 *
6417 * \return - None
6418 *
6419 * --------------------------------------------------------------------------*/
6420
6421static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6422{
6423
6424 VOS_STATUS vos_status;
6425 /* Block any further calls */
6426 atomic_set(&pHddCtx->isRestartInProgress, 1);
6427 /* Cleanup */
6428 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6429 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006430 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006431 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6432 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006433 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006434
6435}
6436
6437/**---------------------------------------------------------------------------
6438 *
6439 * \brief wlan_hdd_framework_restart
6440 *
6441 * This function uses a cfg80211 API to start a framework initiated WLAN
6442 * driver module unload/load.
6443 *
6444 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6445 *
6446 *
6447 * \param - pHddCtx
6448 *
6449 * \return - VOS_STATUS_SUCCESS: Success
6450 * VOS_STATUS_E_EMPTY: Adapter is Empty
6451 * VOS_STATUS_E_NOMEM: No memory
6452
6453 * --------------------------------------------------------------------------*/
6454
6455static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6456{
6457 VOS_STATUS status = VOS_STATUS_SUCCESS;
6458 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006459 int len = (sizeof (struct ieee80211_mgmt));
6460 struct ieee80211_mgmt *mgmt = NULL;
6461
6462 /* Prepare the DEAUTH managment frame with reason code */
6463 mgmt = kzalloc(len, GFP_KERNEL);
6464 if(mgmt == NULL)
6465 {
6466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6467 "%s: memory allocation failed (%d bytes)", __func__, len);
6468 return VOS_STATUS_E_NOMEM;
6469 }
6470 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006471
6472 /* Iterate over all adapters/devices */
6473 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6474 do
6475 {
6476 if( (status == VOS_STATUS_SUCCESS) &&
6477 pAdapterNode &&
6478 pAdapterNode->pAdapter)
6479 {
6480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6481 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6482 pAdapterNode->pAdapter->dev->name,
6483 pAdapterNode->pAdapter->device_mode,
6484 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006485 /*
6486 * CFG80211 event to restart the driver
6487 *
6488 * 'cfg80211_send_unprot_deauth' sends a
6489 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6490 * of SME(Linux Kernel) state machine.
6491 *
6492 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6493 * the driver.
6494 *
6495 */
6496
6497 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006498 }
6499 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6500 pAdapterNode = pNext;
6501 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6502
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006503
6504 /* Free the allocated management frame */
6505 kfree(mgmt);
6506
Jeff Johnsone7245742012-09-05 17:12:55 -07006507 /* Retry until we unload or reach max count */
6508 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6509 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6510
6511 return status;
6512
6513}
6514/**---------------------------------------------------------------------------
6515 *
6516 * \brief wlan_hdd_restart_timer_cb
6517 *
6518 * Restart timer callback. An internal function.
6519 *
6520 * \param - User data:
6521 *
6522 * \return - None
6523 *
6524 * --------------------------------------------------------------------------*/
6525
6526void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6527{
6528 hdd_context_t *pHddCtx = usrDataForCallback;
6529 wlan_hdd_framework_restart(pHddCtx);
6530 return;
6531
6532}
6533
6534
6535/**---------------------------------------------------------------------------
6536 *
6537 * \brief wlan_hdd_restart_driver
6538 *
6539 * This function sends an event to supplicant to restart the WLAN driver.
6540 *
6541 * This function is called from vos_wlanRestart.
6542 *
6543 * \param - pHddCtx
6544 *
6545 * \return - VOS_STATUS_SUCCESS: Success
6546 * VOS_STATUS_E_EMPTY: Adapter is Empty
6547 * VOS_STATUS_E_ALREADY: Request already in progress
6548
6549 * --------------------------------------------------------------------------*/
6550VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6551{
6552 VOS_STATUS status = VOS_STATUS_SUCCESS;
6553
6554 /* A tight check to make sure reentrancy */
6555 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6556 {
6557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6558 "%s: WLAN restart is already in progress", __func__);
6559
6560 return VOS_STATUS_E_ALREADY;
6561 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006562 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006563#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006564 wcnss_reset_intr();
6565#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006566
Jeff Johnsone7245742012-09-05 17:12:55 -07006567 return status;
6568}
6569
6570
Jeff Johnson295189b2012-06-20 16:38:30 -07006571//Register the module init/exit functions
6572module_init(hdd_module_init);
6573module_exit(hdd_module_exit);
6574
6575MODULE_LICENSE("Dual BSD/GPL");
6576MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6577MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6578
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006579module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6580 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006581
Jeff Johnson76052702013-04-16 13:55:05 -07006582module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006583 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);