blob: b297e96b805a9bc9e1dc2991ce341bc1d0b302a0 [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;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700733 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800734 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
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700740 /* Convert the value from ascii to integer */
741 ret = kstrtos8(value, 10, &rssi);
742 if (ret < 0)
743 {
744 /* If the input value is greater than max value of datatype, then also
745 kstrtou8 fails */
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
Srinivas Girigowdade697412013-02-14 16:31:48 -0800754 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
757 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
758 {
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "Neighbor lookup threshold value %d is out of range"
761 " (Min: %d Max: %d)", lookUpThreshold,
762 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
763 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
764 ret = -EINVAL;
765 goto exit;
766 }
767
768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
769 "%s: Received Command to Set Roam trigger"
770 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
771
772 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
773 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
774 if (eHAL_STATUS_SUCCESS != status)
775 {
776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
777 "%s: Failed to set roam trigger, try again", __func__);
778 ret = -EPERM;
779 goto exit;
780 }
781
782 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
783 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
784 }
785 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
786 {
787 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
788 int rssi = (-1) * lookUpThreshold;
789 char extra[32];
790 tANI_U8 len = 0;
791
792 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
793 if (copy_to_user(priv_data.buf, &extra, len + 1))
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: failed to copy data to user buffer", __func__);
797 ret = -EFAULT;
798 goto exit;
799 }
800 }
801 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
802 {
803 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700804 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700806
Srinivas Girigowdade697412013-02-14 16:31:48 -0800807 /* input refresh period is in terms of seconds */
808 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
809 value = value + 18;
810 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700811 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800812 if (ret < 0)
813 {
814 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700815 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700817 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800818 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700819 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
820 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800821 ret = -EINVAL;
822 goto exit;
823 }
824
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
826 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829 "Roam scan period value %d is out of range"
830 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700831 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
832 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800833 ret = -EINVAL;
834 goto exit;
835 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700836 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800837
838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
839 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700840 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800841
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700842 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
843 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800844 }
845 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
846 {
847 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
848 char extra[32];
849 tANI_U8 len = 0;
850
851 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
852 /* Returned value is in units of seconds */
853 if (copy_to_user(priv_data.buf, &extra, len + 1))
854 {
855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
856 "%s: failed to copy data to user buffer", __func__);
857 ret = -EFAULT;
858 goto exit;
859 }
860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700861 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
862 {
863 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700864 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700866
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700867 /* input refresh period is in terms of seconds */
868 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
869 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700871 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700872 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700873 if (ret < 0)
874 {
875 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700876 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700878 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700879 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700880 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
881 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
882 ret = -EINVAL;
883 goto exit;
884 }
885
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700886 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
887 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
888 {
889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
890 "Neighbor scan results refresh period value %d is out of range"
891 " (Min: %d Max: %d)", roamScanRefreshPeriod,
892 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
893 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
894 ret = -EINVAL;
895 goto exit;
896 }
897 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
898
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700901 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700902
903 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
904 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
905 }
906 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
907 {
908 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
909 char extra[32];
910 tANI_U8 len = 0;
911
912 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
913 /* Returned value is in units of seconds */
914 if (copy_to_user(priv_data.buf, &extra, len + 1))
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: failed to copy data to user buffer", __func__);
918 ret = -EFAULT;
919 goto exit;
920 }
921 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700922#ifdef FEATURE_WLAN_LFR
923 /* SETROAMMODE */
924 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
925 {
926 tANI_U8 *value = command;
927 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
928
929 /* Move pointer to ahead of SETROAMMODE<delimiter> */
930 value = value + SIZE_OF_SETROAMMODE + 1;
931
932 /* Convert the value from ascii to integer */
933 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
934 if (ret < 0)
935 {
936 /* If the input value is greater than max value of datatype, then also
937 kstrtou8 fails */
938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
939 "%s: kstrtou8 failed range [%d - %d]", __func__,
940 CFG_LFR_FEATURE_ENABLED_MIN,
941 CFG_LFR_FEATURE_ENABLED_MAX);
942 ret = -EINVAL;
943 goto exit;
944 }
945 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
946 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
947 {
948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
949 "Roam Mode value %d is out of range"
950 " (Min: %d Max: %d)", roamMode,
951 CFG_LFR_FEATURE_ENABLED_MIN,
952 CFG_LFR_FEATURE_ENABLED_MAX);
953 ret = -EINVAL;
954 goto exit;
955 }
956
957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
958 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
959 /*
960 * Note that
961 * SETROAMMODE 0 is to enable LFR while
962 * SETROAMMODE 1 is to disable LFR, but
963 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
964 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
965 */
966 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
967 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
968 else
969 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
970
971 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
972 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
973 }
974 /* GETROAMMODE */
975 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
976 {
977 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
978 char extra[32];
979 tANI_U8 len = 0;
980
981 /*
982 * roamMode value shall be inverted because the sementics is different.
983 */
984 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
985 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
986 else
987 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
988
989 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
990 if (copy_to_user(priv_data.buf, &extra, len + 1))
991 {
992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
993 "%s: failed to copy data to user buffer", __func__);
994 ret = -EFAULT;
995 goto exit;
996 }
997 }
998#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1002 {
1003 tANI_U8 *value = command;
1004 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1005
1006 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1007 value = value + 13;
1008 /* Convert the value from ascii to integer */
1009 ret = kstrtou8(value, 10, &roamRssiDiff);
1010 if (ret < 0)
1011 {
1012 /* If the input value is greater than max value of datatype, then also
1013 kstrtou8 fails */
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: kstrtou8 failed range [%d - %d]", __func__,
1016 CFG_ROAM_RSSI_DIFF_MIN,
1017 CFG_ROAM_RSSI_DIFF_MAX);
1018 ret = -EINVAL;
1019 goto exit;
1020 }
1021
1022 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1023 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1024 {
1025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "Roam rssi diff value %d is out of range"
1027 " (Min: %d Max: %d)", roamRssiDiff,
1028 CFG_ROAM_RSSI_DIFF_MIN,
1029 CFG_ROAM_RSSI_DIFF_MAX);
1030 ret = -EINVAL;
1031 goto exit;
1032 }
1033
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1035 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1036
1037 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1038 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1039 }
1040 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1041 {
1042 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1043 char extra[32];
1044 tANI_U8 len = 0;
1045
1046 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1047 if (copy_to_user(priv_data.buf, &extra, len + 1))
1048 {
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: failed to copy data to user buffer", __func__);
1051 ret = -EFAULT;
1052 goto exit;
1053 }
1054 }
1055#endif
1056#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1057 else if (strncmp(command, "GETBAND", 7) == 0)
1058 {
1059 int band = -1;
1060 char extra[32];
1061 tANI_U8 len = 0;
1062 hdd_getBand_helper(pHddCtx, &band);
1063
1064 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1065 if (copy_to_user(priv_data.buf, &extra, len + 1))
1066 {
1067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1068 "%s: failed to copy data to user buffer", __func__);
1069 ret = -EFAULT;
1070 goto exit;
1071 }
1072 }
1073 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1074 {
1075 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1076 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1077 tANI_U8 revision = 0;
1078 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1079 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1080 char extra[32] = {0};
1081 tANI_U8 len = 0;
1082
1083 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1086 "%s: failed to get country code", __func__);
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090 pBuf[uBufLen] = '\0';
1091 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1092
1093 if (0 == strncmp(pBuf, "KR", 2))
1094 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1095 else
1096 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1097
1098 if (copy_to_user(priv_data.buf, &extra, len + 1))
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: failed to copy data to user buffer", __func__);
1102 ret = -EFAULT;
1103 goto exit;
1104 }
1105 }
1106 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1107 {
1108 tANI_U8 *value = command;
1109 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1110 tANI_U8 numChannels = 0;
1111 eHalStatus status = eHAL_STATUS_SUCCESS;
1112
1113 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1114 if (eHAL_STATUS_SUCCESS != status)
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1117 "%s: Failed to parse channel list information", __func__);
1118 ret = -EINVAL;
1119 goto exit;
1120 }
1121
1122 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1125 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1126 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1127 ret = -EINVAL;
1128 goto exit;
1129 }
1130 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1131 numChannels);
1132 if (eHAL_STATUS_SUCCESS != status)
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: Failed to update channel list information", __func__);
1136 ret = -EINVAL;
1137 goto exit;
1138 }
1139 }
1140 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1141 {
1142 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1143 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001144 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001145 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001146 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001147
1148 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1149 ChannelList, &numChannels ))
1150 {
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1152 "%s: failed to get roam scan channel list", __func__);
1153 ret = -EFAULT;
1154 goto exit;
1155 }
1156 /* output channel list is of the format
1157 [Number of roam scan channels][Channel1][Channel2]... */
1158 /* copy the number of channels in the 0th index */
1159 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1160 for (j = 0; (j < numChannels); j++)
1161 {
1162 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1163 }
1164
1165 if (copy_to_user(priv_data.buf, &extra, len + 1))
1166 {
1167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: failed to copy data to user buffer", __func__);
1169 ret = -EFAULT;
1170 goto exit;
1171 }
1172 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001173 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1174 {
1175 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1176 char extra[32];
1177 tANI_U8 len = 0;
1178
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001179 /* Check if the features OKC/CCX/11R are supported simultaneously,
1180 then this operation is not permitted (return FAILURE) */
1181 if (ccxMode &&
1182 hdd_is_okc_mode_enabled(pHddCtx) &&
1183 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1184 {
1185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1186 "%s: OKC/CCX/11R are supported simultaneously"
1187 " hence this operation is not permitted!", __func__);
1188 ret = -EPERM;
1189 goto exit;
1190 }
1191
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001192 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
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, "GETOKCMODE", 10) == 0)
1202 {
1203 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1204 char extra[32];
1205 tANI_U8 len = 0;
1206
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001207 /* Check if the features OKC/CCX/11R are supported simultaneously,
1208 then this operation is not permitted (return FAILURE) */
1209 if (okcMode &&
1210 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1211 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1212 {
1213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1214 "%s: OKC/CCX/11R are supported simultaneously"
1215 " hence this operation is not permitted!", __func__);
1216 ret = -EPERM;
1217 goto exit;
1218 }
1219
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001220 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1221 if (copy_to_user(priv_data.buf, &extra, len + 1))
1222 {
1223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "%s: failed to copy data to user buffer", __func__);
1225 ret = -EFAULT;
1226 goto exit;
1227 }
1228 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001229 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001230 {
1231 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1232 char extra[32];
1233 tANI_U8 len = 0;
1234
1235 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1236 if (copy_to_user(priv_data.buf, &extra, len + 1))
1237 {
1238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "%s: failed to copy data to user buffer", __func__);
1240 ret = -EFAULT;
1241 goto exit;
1242 }
1243 }
1244 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1245 {
1246 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1247 char extra[32];
1248 tANI_U8 len = 0;
1249
1250 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1251 if (copy_to_user(priv_data.buf, &extra, len + 1))
1252 {
1253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1254 "%s: failed to copy data to user buffer", __func__);
1255 ret = -EFAULT;
1256 goto exit;
1257 }
1258 }
1259 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1260 {
1261 tANI_U8 *value = command;
1262 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1263
1264 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1265 value = value + 26;
1266 /* Convert the value from ascii to integer */
1267 ret = kstrtou8(value, 10, &minTime);
1268 if (ret < 0)
1269 {
1270 /* If the input value is greater than max value of datatype, then also
1271 kstrtou8 fails */
1272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1273 "%s: kstrtou8 failed range [%d - %d]", __func__,
1274 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1275 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1276 ret = -EINVAL;
1277 goto exit;
1278 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001279 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1280 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1281 {
1282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1283 "scan min channel time value %d is out of range"
1284 " (Min: %d Max: %d)", minTime,
1285 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1286 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1287 ret = -EINVAL;
1288 goto exit;
1289 }
1290
1291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1292 "%s: Received Command to change channel min time = %d", __func__, minTime);
1293
1294 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1295 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1296 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1298 {
1299 tANI_U8 *value = command;
1300 tANI_U8 channel = 0;
1301 tANI_U8 dwellTime = 0;
1302 tANI_U8 bufLen = 0;
1303 tANI_U8 *buf = NULL;
1304 tSirMacAddr targetApBssid;
1305 eHalStatus status = eHAL_STATUS_SUCCESS;
1306 struct ieee80211_channel chan;
1307 tANI_U8 finalLen = 0;
1308 tANI_U8 *finalBuf = NULL;
1309 tANI_U8 temp = 0;
1310 u64 cookie;
1311 hdd_station_ctx_t *pHddStaCtx = NULL;
1312 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1313
1314 /* if not associated, no need to send action frame */
1315 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1318 ret = -EINVAL;
1319 goto exit;
1320 }
1321
1322 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1323 &dwellTime, &buf, &bufLen);
1324 if (eHAL_STATUS_SUCCESS != status)
1325 {
1326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1327 "%s: Failed to parse send action frame data", __func__);
1328 ret = -EINVAL;
1329 goto exit;
1330 }
1331
1332 /* if the target bssid is different from currently associated AP,
1333 then no need to send action frame */
1334 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1335 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1336 {
1337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1338 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001339 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340 goto exit;
1341 }
1342
1343 /* if the channel number is different from operating channel then
1344 no need to send action frame */
1345 if (channel != pHddStaCtx->conn_info.operationChannel)
1346 {
1347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1348 "%s: channel(%d) is different from operating channel(%d)",
1349 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1350 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001351 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001352 goto exit;
1353 }
1354 chan.center_freq = sme_ChnToFreq(channel);
1355
1356 finalLen = bufLen + 24;
1357 finalBuf = vos_mem_malloc(finalLen);
1358 if (NULL == finalBuf)
1359 {
1360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1361 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001362 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001363 goto exit;
1364 }
1365 vos_mem_zero(finalBuf, finalLen);
1366
1367 /* Fill subtype */
1368 temp = SIR_MAC_MGMT_ACTION << 4;
1369 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1370
1371 /* Fill type */
1372 temp = SIR_MAC_MGMT_FRAME;
1373 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1374
1375 /* Fill destination address (bssid of the AP) */
1376 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1377
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001378 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001379 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1380
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001381 /* Fill BSSID (AP mac address) */
1382 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001383
1384 /* Fill received buffer from 24th address */
1385 vos_mem_copy(finalBuf + 24, buf, bufLen);
1386
Jeff Johnson11c33152013-04-16 17:52:40 -07001387 /* done with the parsed buffer */
1388 vos_mem_free(buf);
1389
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001390 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1391 1, dwellTime, finalBuf, finalLen, 1,
1392 1, &cookie );
1393 vos_mem_free(finalBuf);
1394 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001395 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1396 {
1397 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1398 char extra[32];
1399 tANI_U8 len = 0;
1400
1401 /* value is interms of msec */
1402 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1403 if (copy_to_user(priv_data.buf, &extra, len + 1))
1404 {
1405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1406 "%s: failed to copy data to user buffer", __func__);
1407 ret = -EFAULT;
1408 goto exit;
1409 }
1410 }
1411 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1412 {
1413 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001414 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001415 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001416
1417 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1418 value = value + 19;
1419 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001420 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001421 if (ret < 0)
1422 {
1423 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001424 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001426 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001427 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1428 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1429 ret = -EINVAL;
1430 goto exit;
1431 }
1432
1433 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1434 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1435 {
1436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1437 "lfr mode value %d is out of range"
1438 " (Min: %d Max: %d)", maxTime,
1439 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1440 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1441 ret = -EINVAL;
1442 goto exit;
1443 }
1444
1445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1446 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1447
1448 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001449
1450 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1451 * where RFS is the RF Switching time. It is twice RFS to consider the
1452 * time to go off channel and return to the home channel. */
1453 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1454 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1455 {
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1457 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1458 " Hence enforcing home away time to disable (0)",
1459 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1460 homeAwayTime = 0;
1461 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1462 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1463 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001464 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1465 }
1466 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1467 {
1468 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1469 char extra[32];
1470 tANI_U8 len = 0;
1471
1472 /* value is interms of msec */
1473 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1474 if (copy_to_user(priv_data.buf, &extra, len + 1))
1475 {
1476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1477 "%s: failed to copy data to user buffer", __func__);
1478 ret = -EFAULT;
1479 goto exit;
1480 }
1481 }
1482 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1483 {
1484 tANI_U8 *value = command;
1485 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1486
1487 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1488 value = value + 16;
1489 /* Convert the value from ascii to integer */
1490 ret = kstrtou16(value, 10, &val);
1491 if (ret < 0)
1492 {
1493 /* If the input value is greater than max value of datatype, then also
1494 kstrtou16 fails */
1495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1496 "%s: kstrtou16 failed range [%d - %d]", __func__,
1497 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1498 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1499 ret = -EINVAL;
1500 goto exit;
1501 }
1502
1503 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1504 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1505 {
1506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1507 "scan home time value %d is out of range"
1508 " (Min: %d Max: %d)", val,
1509 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1510 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514
1515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1516 "%s: Received Command to change scan home time = %d", __func__, val);
1517
1518 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1519 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1520 }
1521 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1522 {
1523 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1524 char extra[32];
1525 tANI_U8 len = 0;
1526
1527 /* value is interms of msec */
1528 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1529 if (copy_to_user(priv_data.buf, &extra, len + 1))
1530 {
1531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1532 "%s: failed to copy data to user buffer", __func__);
1533 ret = -EFAULT;
1534 goto exit;
1535 }
1536 }
1537 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1538 {
1539 tANI_U8 *value = command;
1540 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1541
1542 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1543 value = value + 17;
1544 /* Convert the value from ascii to integer */
1545 ret = kstrtou8(value, 10, &val);
1546 if (ret < 0)
1547 {
1548 /* If the input value is greater than max value of datatype, then also
1549 kstrtou8 fails */
1550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1551 "%s: kstrtou8 failed range [%d - %d]", __func__,
1552 CFG_ROAM_INTRA_BAND_MIN,
1553 CFG_ROAM_INTRA_BAND_MAX);
1554 ret = -EINVAL;
1555 goto exit;
1556 }
1557
1558 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1559 (val > CFG_ROAM_INTRA_BAND_MAX))
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "intra band mode value %d is out of range"
1563 " (Min: %d Max: %d)", val,
1564 CFG_ROAM_INTRA_BAND_MIN,
1565 CFG_ROAM_INTRA_BAND_MAX);
1566 ret = -EINVAL;
1567 goto exit;
1568 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1570 "%s: Received Command to change intra band = %d", __func__, val);
1571
1572 pHddCtx->cfg_ini->nRoamIntraBand = val;
1573 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1574 }
1575 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1576 {
1577 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1578 char extra[32];
1579 tANI_U8 len = 0;
1580
1581 /* value is interms of msec */
1582 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1583 if (copy_to_user(priv_data.buf, &extra, len + 1))
1584 {
1585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1586 "%s: failed to copy data to user buffer", __func__);
1587 ret = -EFAULT;
1588 goto exit;
1589 }
1590 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001591 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1592 {
1593 tANI_U8 *value = command;
1594 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1595
1596 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1597 value = value + 15;
1598 /* Convert the value from ascii to integer */
1599 ret = kstrtou8(value, 10, &nProbes);
1600 if (ret < 0)
1601 {
1602 /* If the input value is greater than max value of datatype, then also
1603 kstrtou8 fails */
1604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1605 "%s: kstrtou8 failed range [%d - %d]", __func__,
1606 CFG_ROAM_SCAN_N_PROBES_MIN,
1607 CFG_ROAM_SCAN_N_PROBES_MAX);
1608 ret = -EINVAL;
1609 goto exit;
1610 }
1611
1612 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1613 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1614 {
1615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1616 "NProbes value %d is out of range"
1617 " (Min: %d Max: %d)", nProbes,
1618 CFG_ROAM_SCAN_N_PROBES_MIN,
1619 CFG_ROAM_SCAN_N_PROBES_MAX);
1620 ret = -EINVAL;
1621 goto exit;
1622 }
1623
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1625 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1626
1627 pHddCtx->cfg_ini->nProbes = nProbes;
1628 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1629 }
1630 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1631 {
1632 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1633 char extra[32];
1634 tANI_U8 len = 0;
1635
1636 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1637 if (copy_to_user(priv_data.buf, &extra, len + 1))
1638 {
1639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1640 "%s: failed to copy data to user buffer", __func__);
1641 ret = -EFAULT;
1642 goto exit;
1643 }
1644 }
1645 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1646 {
1647 tANI_U8 *value = command;
1648 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001649 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001650
1651 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1652 /* input value is in units of msec */
1653 value = value + 20;
1654 /* Convert the value from ascii to integer */
1655 ret = kstrtou16(value, 10, &homeAwayTime);
1656 if (ret < 0)
1657 {
1658 /* If the input value is greater than max value of datatype, then also
1659 kstrtou8 fails */
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: kstrtou8 failed range [%d - %d]", __func__,
1662 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1663 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1664 ret = -EINVAL;
1665 goto exit;
1666 }
1667
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001668 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1669 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1670 {
1671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1672 "homeAwayTime value %d is out of range"
1673 " (Min: %d Max: %d)", homeAwayTime,
1674 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1675 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1676 ret = -EINVAL;
1677 goto exit;
1678 }
1679
1680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1681 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1682
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001683 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1684 * where RFS is the RF Switching time. It is twice RFS to consider the
1685 * time to go off channel and return to the home channel. */
1686 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1687 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1688 {
1689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1690 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1691 " Hence enforcing home away time to disable (0)",
1692 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1693 homeAwayTime = 0;
1694 }
1695
1696 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1697 {
1698 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1699 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1700 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001701 }
1702 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1703 {
1704 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1705 char extra[32];
1706 tANI_U8 len = 0;
1707
1708 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1709 if (copy_to_user(priv_data.buf, &extra, len + 1))
1710 {
1711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1712 "%s: failed to copy data to user buffer", __func__);
1713 ret = -EFAULT;
1714 goto exit;
1715 }
1716 }
1717 else if (strncmp(command, "REASSOC", 7) == 0)
1718 {
1719 tANI_U8 *value = command;
1720 tANI_U8 channel = 0;
1721 tSirMacAddr targetApBssid;
1722 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001723#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1724 tCsrHandoffRequest handoffInfo;
1725#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001726 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001727 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1728
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001729 /* if not associated, no need to proceed with reassoc */
1730 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1731 {
1732 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1733 ret = -EINVAL;
1734 goto exit;
1735 }
1736
1737 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1738 if (eHAL_STATUS_SUCCESS != status)
1739 {
1740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1741 "%s: Failed to parse reassoc command data", __func__);
1742 ret = -EINVAL;
1743 goto exit;
1744 }
1745
1746 /* if the target bssid is same as currently associated AP,
1747 then no need to proceed with reassoc */
1748 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1749 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1750 {
1751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 /* Check channel number is a valid channel number */
1757 if(VOS_STATUS_SUCCESS !=
1758 wlan_hdd_validate_operation_channel(pAdapter, channel))
1759 {
1760 hddLog(VOS_TRACE_LEVEL_ERROR,
1761 "%s: Invalid Channel [%d] \n", __func__, channel);
1762 return -EINVAL;
1763 }
1764
1765 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001766#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1767 handoffInfo.channel = channel;
1768 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1769 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1770#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001771 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001772#endif
1773#ifdef FEATURE_WLAN_LFR
1774 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1775 {
1776 tANI_U8 *value = command;
1777 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1778
1779 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1780 value = value + 12;
1781 /* Convert the value from ascii to integer */
1782 ret = kstrtou8(value, 10, &lfrMode);
1783 if (ret < 0)
1784 {
1785 /* If the input value is greater than max value of datatype, then also
1786 kstrtou8 fails */
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s: kstrtou8 failed range [%d - %d]", __func__,
1789 CFG_LFR_FEATURE_ENABLED_MIN,
1790 CFG_LFR_FEATURE_ENABLED_MAX);
1791 ret = -EINVAL;
1792 goto exit;
1793 }
1794
1795 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1796 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1797 {
1798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "lfr mode value %d is out of range"
1800 " (Min: %d Max: %d)", lfrMode,
1801 CFG_LFR_FEATURE_ENABLED_MIN,
1802 CFG_LFR_FEATURE_ENABLED_MAX);
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
1807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1808 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1809
1810 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1811 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1812 }
1813#endif
1814#ifdef WLAN_FEATURE_VOWIFI_11R
1815 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1816 {
1817 tANI_U8 *value = command;
1818 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1819
1820 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1821 value = value + 18;
1822 /* Convert the value from ascii to integer */
1823 ret = kstrtou8(value, 10, &ft);
1824 if (ret < 0)
1825 {
1826 /* If the input value is greater than max value of datatype, then also
1827 kstrtou8 fails */
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1829 "%s: kstrtou8 failed range [%d - %d]", __func__,
1830 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1831 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1832 ret = -EINVAL;
1833 goto exit;
1834 }
1835
1836 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1837 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1838 {
1839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1840 "ft mode value %d is out of range"
1841 " (Min: %d Max: %d)", ft,
1842 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1843 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1844 ret = -EINVAL;
1845 goto exit;
1846 }
1847
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1849 "%s: Received Command to change ft mode = %d", __func__, ft);
1850
1851 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1852 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1853 }
1854#endif
1855#ifdef FEATURE_WLAN_CCX
1856 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1857 {
1858 tANI_U8 *value = command;
1859 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1860
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001861 /* Check if the features OKC/CCX/11R are supported simultaneously,
1862 then this operation is not permitted (return FAILURE) */
1863 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1864 hdd_is_okc_mode_enabled(pHddCtx) &&
1865 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1868 "%s: OKC/CCX/11R are supported simultaneously"
1869 " hence this operation is not permitted!", __func__);
1870 ret = -EPERM;
1871 goto exit;
1872 }
1873
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001874 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1875 value = value + 11;
1876 /* Convert the value from ascii to integer */
1877 ret = kstrtou8(value, 10, &ccxMode);
1878 if (ret < 0)
1879 {
1880 /* If the input value is greater than max value of datatype, then also
1881 kstrtou8 fails */
1882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1883 "%s: kstrtou8 failed range [%d - %d]", __func__,
1884 CFG_CCX_FEATURE_ENABLED_MIN,
1885 CFG_CCX_FEATURE_ENABLED_MAX);
1886 ret = -EINVAL;
1887 goto exit;
1888 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001889 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1890 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1891 {
1892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "Ccx mode value %d is out of range"
1894 " (Min: %d Max: %d)", ccxMode,
1895 CFG_CCX_FEATURE_ENABLED_MIN,
1896 CFG_CCX_FEATURE_ENABLED_MAX);
1897 ret = -EINVAL;
1898 goto exit;
1899 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1901 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1902
1903 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1904 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1905 }
1906#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001907 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1908 {
1909 tANI_U8 *value = command;
1910 tANI_BOOLEAN roamScanControl = 0;
1911
1912 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1913 value = value + 19;
1914 /* Convert the value from ascii to integer */
1915 ret = kstrtou8(value, 10, &roamScanControl);
1916 if (ret < 0)
1917 {
1918 /* If the input value is greater than max value of datatype, then also
1919 kstrtou8 fails */
1920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 "%s: kstrtou8 failed ", __func__);
1922 ret = -EINVAL;
1923 goto exit;
1924 }
1925
1926 if (0 != roamScanControl)
1927 {
1928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "roam scan control invalid value = %d",
1930 roamScanControl);
1931 ret = -EINVAL;
1932 goto exit;
1933 }
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1935 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1936
1937 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1938 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001939#ifdef FEATURE_WLAN_OKC
1940 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1941 {
1942 tANI_U8 *value = command;
1943 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1944
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001945 /* Check if the features OKC/CCX/11R are supported simultaneously,
1946 then this operation is not permitted (return FAILURE) */
1947 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1948 hdd_is_okc_mode_enabled(pHddCtx) &&
1949 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1952 "%s: OKC/CCX/11R are supported simultaneously"
1953 " hence this operation is not permitted!", __func__);
1954 ret = -EPERM;
1955 goto exit;
1956 }
1957
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001958 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1959 value = value + 11;
1960 /* Convert the value from ascii to integer */
1961 ret = kstrtou8(value, 10, &okcMode);
1962 if (ret < 0)
1963 {
1964 /* If the input value is greater than max value of datatype, then also
1965 kstrtou8 fails */
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1967 "%s: kstrtou8 failed range [%d - %d]", __func__,
1968 CFG_OKC_FEATURE_ENABLED_MIN,
1969 CFG_OKC_FEATURE_ENABLED_MAX);
1970 ret = -EINVAL;
1971 goto exit;
1972 }
1973
1974 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1975 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1976 {
1977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1978 "Okc mode value %d is out of range"
1979 " (Min: %d Max: %d)", okcMode,
1980 CFG_OKC_FEATURE_ENABLED_MIN,
1981 CFG_OKC_FEATURE_ENABLED_MAX);
1982 ret = -EINVAL;
1983 goto exit;
1984 }
1985
1986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1987 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1988
1989 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1990 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001991 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1992 {
1993 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1994 char extra[32];
1995 tANI_U8 len = 0;
1996
1997 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1998 if (copy_to_user(priv_data.buf, &extra, len + 1))
1999 {
2000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2001 "%s: failed to copy data to user buffer", __func__);
2002 ret = -EFAULT;
2003 goto exit;
2004 }
2005 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002006#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302007#ifdef WLAN_FEATURE_PACKET_FILTERING
2008 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2009 {
2010 tANI_U8 filterType = 0;
2011 tANI_U8 *value = command;
2012
2013 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2014 value = value + 22;
2015
2016 /* Convert the value from ascii to integer */
2017 ret = kstrtou8(value, 10, &filterType);
2018 if (ret < 0)
2019 {
2020 /* If the input value is greater than max value of datatype,
2021 * then also kstrtou8 fails
2022 */
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2024 "%s: kstrtou8 failed range ", __func__);
2025 ret = -EINVAL;
2026 goto exit;
2027 }
2028
2029 if (filterType != 0 && filterType != 1)
2030 {
2031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2032 "%s: Accepted Values are 0 and 1 ", __func__);
2033 ret = -EINVAL;
2034 goto exit;
2035 }
2036 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2037 pAdapter->sessionId);
2038 }
2039#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302040 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2041 {
2042 char *dhcpPhase;
2043 dhcpPhase = command + 12;
2044 if ('1' == *dhcpPhase)
2045 {
2046 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2047 pAdapter->macAddressCurrent.bytes);
2048 }
2049 else if ('2' == *dhcpPhase)
2050 {
2051 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2052 pAdapter->macAddressCurrent.bytes);
2053 }
2054 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002055 else {
2056 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2057 __func__, command);
2058 }
2059
Jeff Johnson295189b2012-06-20 16:38:30 -07002060 }
2061exit:
2062 if (command)
2063 {
2064 kfree(command);
2065 }
2066 return ret;
2067}
2068
Srinivas Girigowdade697412013-02-14 16:31:48 -08002069#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2070void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2071{
2072 eCsrBand band = -1;
2073 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2074 switch (band)
2075 {
2076 case eCSR_BAND_ALL:
2077 *pBand = WLAN_HDD_UI_BAND_AUTO;
2078 break;
2079
2080 case eCSR_BAND_24:
2081 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2082 break;
2083
2084 case eCSR_BAND_5G:
2085 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2086 break;
2087
2088 default:
2089 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2090 *pBand = -1;
2091 break;
2092 }
2093}
2094
2095/**---------------------------------------------------------------------------
2096
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002097 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2098
2099 This function parses the send action frame data passed in the format
2100 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2101
2102 \param - pValue Pointer to input country code revision
2103 \param - pTargetApBssid Pointer to target Ap bssid
2104 \param - pChannel Pointer to the Target AP channel
2105 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2106 \param - pBuf Pointer to data
2107 \param - pBufLen Pointer to data length
2108
2109 \return - 0 for success non-zero for failure
2110
2111 --------------------------------------------------------------------------*/
2112VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2113 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2114{
2115 tANI_U8 *inPtr = pValue;
2116 tANI_U8 *dataEnd;
2117 int tempInt;
2118 int j = 0;
2119 int i = 0;
2120 int v = 0;
2121 tANI_U8 tempBuf[32];
2122 tANI_U8 tempByte = 0;
2123
2124 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2125 /*no argument after the command*/
2126 if (NULL == inPtr)
2127 {
2128 return -EINVAL;
2129 }
2130
2131 /*no space after the command*/
2132 else if (SPACE_ASCII_VALUE != *inPtr)
2133 {
2134 return -EINVAL;
2135 }
2136
2137 /*removing empty spaces*/
2138 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2139
2140 /*no argument followed by spaces*/
2141 if ('\0' == *inPtr)
2142 {
2143 return -EINVAL;
2144 }
2145
2146 /*getting the first argument ie the target AP bssid */
2147 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2148 {
2149 return -EINVAL;
2150 }
2151 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2152 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2153 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2154
2155 /* point to the next argument */
2156 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2157 /*no argument after the command*/
2158 if (NULL == inPtr) return -EINVAL;
2159
2160 /*removing empty spaces*/
2161 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2162
2163 /*no argument followed by spaces*/
2164 if ('\0' == *inPtr)
2165 {
2166 return -EINVAL;
2167 }
2168
2169 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002170 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002171 v = kstrtos32(tempBuf, 10, &tempInt);
2172 if ( v < 0) return -EINVAL;
2173
2174 *pChannel = tempInt;
2175
2176 /* point to the next argument */
2177 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2178 /*no argument after the command*/
2179 if (NULL == inPtr) return -EINVAL;
2180 /*removing empty spaces*/
2181 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2182
2183 /*no argument followed by spaces*/
2184 if ('\0' == *inPtr)
2185 {
2186 return -EINVAL;
2187 }
2188
2189 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002190 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002191 v = kstrtos32(tempBuf, 10, &tempInt);
2192 if ( v < 0) return -EINVAL;
2193
2194 *pDwellTime = tempInt;
2195
2196 /* point to the next argument */
2197 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2198 /*no argument after the command*/
2199 if (NULL == inPtr) return -EINVAL;
2200 /*removing empty spaces*/
2201 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2202
2203 /*no argument followed by spaces*/
2204 if ('\0' == *inPtr)
2205 {
2206 return -EINVAL;
2207 }
2208
2209 /* find the length of data */
2210 dataEnd = inPtr;
2211 while(('\0' != *dataEnd) )
2212 {
2213 dataEnd++;
2214 ++(*pBufLen);
2215 }
2216 if ( *pBufLen <= 0) return -EINVAL;
2217
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002218 /* Allocate the number of bytes based on the number of input characters
2219 whether it is even or odd.
2220 if the number of input characters are even, then we need N/2 byte.
2221 if the number of input characters are odd, then we need do (N+1)/2 to
2222 compensate rounding off.
2223 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2224 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2225 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002226 if (NULL == *pBuf)
2227 {
2228 hddLog(VOS_TRACE_LEVEL_FATAL,
2229 "%s: vos_mem_alloc failed ", __func__);
2230 return -EINVAL;
2231 }
2232
2233 /* the buffer received from the upper layer is character buffer,
2234 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2235 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2236 and f0 in 3rd location */
2237 for (i = 0, j = 0; j < *pBufLen; j += 2)
2238 {
2239 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2240 (*pBuf)[i++] = tempByte;
2241 }
2242 *pBufLen = i;
2243 return VOS_STATUS_SUCCESS;
2244}
2245
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002246/**---------------------------------------------------------------------------
2247
Srinivas Girigowdade697412013-02-14 16:31:48 -08002248 \brief hdd_parse_countryrev() - HDD Parse country code revision
2249
2250 This function parses the country code revision passed in the format
2251 SETCOUNTRYREV<space><Country code><space>revision
2252
2253 \param - pValue Pointer to input country code revision
2254 \param - pCountryCode Pointer to local output array to record country code
2255 \param - pRevision Pointer to store revision integer number
2256
2257 \return - 0 for success non-zero for failure
2258
2259 --------------------------------------------------------------------------*/
2260VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2261{
2262 tANI_U8 *inPtr = pValue;
2263 int tempInt;
2264
2265 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2266 /*no argument after the command*/
2267 if (NULL == inPtr)
2268 {
2269 return -EINVAL;
2270 }
2271
2272 /*no space after the command*/
2273 else if (SPACE_ASCII_VALUE != *inPtr)
2274 {
2275 return -EINVAL;
2276 }
2277
2278 /*removing empty spaces*/
2279 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2280
2281 /*no argument followed by spaces*/
2282 if ('\0' == *inPtr)
2283 {
2284 return -EINVAL;
2285 }
2286
2287 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002288 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002289
2290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2291 "Country code is : %s", pCountryCode);
2292
2293 /*inPtr pointing to the beginning of first space after country code */
2294 inPtr = strpbrk( inPtr, " " );
2295 /*no revision number after the country code argument */
2296 if (NULL == inPtr)
2297 {
2298 return -EINVAL;
2299 }
2300
2301 inPtr++;
2302
2303 /*removing empty space*/
2304 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2305
2306 /*no channel list after the number of channels argument and spaces*/
2307 if (0 == strncmp(pCountryCode, "KR", 2))
2308 {
2309 if ('\0' == *inPtr)
2310 {
2311 return -EINVAL;
2312 }
2313
2314 sscanf(inPtr, "%d", &tempInt);
2315 *pRevision = tempInt;
2316 }
2317 else
2318 {
2319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2320 "Revision input is required only for Country KR");
2321 return -EINVAL;
2322 }
2323 return VOS_STATUS_SUCCESS;
2324}
2325
2326/**---------------------------------------------------------------------------
2327
2328 \brief hdd_parse_channellist() - HDD Parse channel list
2329
2330 This function parses the channel list passed in the format
2331 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002332 if the Number of channels (N) does not match with the actual number of channels passed
2333 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2334 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2335 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2336 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337
2338 \param - pValue Pointer to input channel list
2339 \param - ChannelList Pointer to local output array to record channel list
2340 \param - pNumChannels Pointer to number of roam scan channels
2341
2342 \return - 0 for success non-zero for failure
2343
2344 --------------------------------------------------------------------------*/
2345VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2346{
2347 tANI_U8 *inPtr = pValue;
2348 int tempInt;
2349 int j = 0;
2350 int v = 0;
2351 char buf[32];
2352
2353 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2354 /*no argument after the command*/
2355 if (NULL == inPtr)
2356 {
2357 return -EINVAL;
2358 }
2359
2360 /*no space after the command*/
2361 else if (SPACE_ASCII_VALUE != *inPtr)
2362 {
2363 return -EINVAL;
2364 }
2365
2366 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002367 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368
2369 /*no argument followed by spaces*/
2370 if ('\0' == *inPtr)
2371 {
2372 return -EINVAL;
2373 }
2374
2375 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002376 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002378 if ((v < 0) ||
2379 (tempInt <= 0) ||
2380 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2381 {
2382 return -EINVAL;
2383 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384
2385 *pNumChannels = tempInt;
2386
2387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2388 "Number of channels are: %d", *pNumChannels);
2389
2390 for (j = 0; j < (*pNumChannels); j++)
2391 {
2392 /*inPtr pointing to the beginning of first space after number of channels*/
2393 inPtr = strpbrk( inPtr, " " );
2394 /*no channel list after the number of channels argument*/
2395 if (NULL == inPtr)
2396 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002397 if (0 != j)
2398 {
2399 *pNumChannels = j;
2400 return VOS_STATUS_SUCCESS;
2401 }
2402 else
2403 {
2404 return -EINVAL;
2405 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002406 }
2407
2408 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002409 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002410
2411 /*no channel list after the number of channels argument and spaces*/
2412 if ( '\0' == *inPtr )
2413 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002414 if (0 != j)
2415 {
2416 *pNumChannels = j;
2417 return VOS_STATUS_SUCCESS;
2418 }
2419 else
2420 {
2421 return -EINVAL;
2422 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002423 }
2424
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002425 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002426 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002427 if ((v < 0) ||
2428 (tempInt <= 0) ||
2429 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2430 {
2431 return -EINVAL;
2432 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002433 pChannelList[j] = tempInt;
2434
2435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2436 "Channel %d added to preferred channel list",
2437 pChannelList[j] );
2438 }
2439
Srinivas Girigowdade697412013-02-14 16:31:48 -08002440 return VOS_STATUS_SUCCESS;
2441}
2442
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002443
2444/**---------------------------------------------------------------------------
2445
2446 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2447
2448 This function parses the reasoc command data passed in the format
2449 REASSOC<space><bssid><space><channel>
2450
2451 \param - pValue Pointer to input country code revision
2452 \param - pTargetApBssid Pointer to target Ap bssid
2453 \param - pChannel Pointer to the Target AP channel
2454
2455 \return - 0 for success non-zero for failure
2456
2457 --------------------------------------------------------------------------*/
2458VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2459{
2460 tANI_U8 *inPtr = pValue;
2461 int tempInt;
2462 int v = 0;
2463 tANI_U8 tempBuf[32];
2464
2465 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2466 /*no argument after the command*/
2467 if (NULL == inPtr)
2468 {
2469 return -EINVAL;
2470 }
2471
2472 /*no space after the command*/
2473 else if (SPACE_ASCII_VALUE != *inPtr)
2474 {
2475 return -EINVAL;
2476 }
2477
2478 /*removing empty spaces*/
2479 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2480
2481 /*no argument followed by spaces*/
2482 if ('\0' == *inPtr)
2483 {
2484 return -EINVAL;
2485 }
2486
2487 /*getting the first argument ie the target AP bssid */
2488 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2489 {
2490 return -EINVAL;
2491 }
2492 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2493 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2494 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2495
2496 /* point to the next argument */
2497 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2498 /*no argument after the command*/
2499 if (NULL == inPtr) return -EINVAL;
2500
2501 /*removing empty spaces*/
2502 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2503
2504 /*no argument followed by spaces*/
2505 if ('\0' == *inPtr)
2506 {
2507 return -EINVAL;
2508 }
2509
2510 /*getting the next argument ie the channel number */
2511 sscanf(inPtr, "%s ", tempBuf);
2512 v = kstrtos32(tempBuf, 10, &tempInt);
2513 if ( v < 0) return -EINVAL;
2514
2515 *pChannel = tempInt;
2516 return VOS_STATUS_SUCCESS;
2517}
2518
2519#endif
2520
Jeff Johnson295189b2012-06-20 16:38:30 -07002521/**---------------------------------------------------------------------------
2522
2523 \brief hdd_open() - HDD Open function
2524
2525 This is called in response to ifconfig up
2526
2527 \param - dev Pointer to net_device structure
2528
2529 \return - 0 for success non-zero for failure
2530
2531 --------------------------------------------------------------------------*/
2532int hdd_open (struct net_device *dev)
2533{
2534 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2535 hdd_context_t *pHddCtx;
2536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2537 VOS_STATUS status;
2538 v_BOOL_t in_standby = TRUE;
2539
2540 if (NULL == pAdapter)
2541 {
2542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002543 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002544 return -ENODEV;
2545 }
2546
2547 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2548 if (NULL == pHddCtx)
2549 {
2550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002551 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 return -ENODEV;
2553 }
2554
2555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2556 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2557 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002558 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2559 {
2560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302561 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002562 in_standby = FALSE;
2563 break;
2564 }
2565 else
2566 {
2567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2568 pAdapterNode = pNext;
2569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 }
2571
2572 if (TRUE == in_standby)
2573 {
2574 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2575 {
2576 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2577 "wlan out of power save", __func__);
2578 return -EINVAL;
2579 }
2580 }
2581
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002582 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002583 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2584 {
2585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002586 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002587 /* Enable TX queues only when we are connected */
2588 netif_tx_start_all_queues(dev);
2589 }
2590
2591 return 0;
2592}
2593
2594int hdd_mon_open (struct net_device *dev)
2595{
2596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2597
2598 if(pAdapter == NULL) {
2599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002600 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002601 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 }
2603
2604 netif_start_queue(dev);
2605
2606 return 0;
2607}
2608/**---------------------------------------------------------------------------
2609
2610 \brief hdd_stop() - HDD stop function
2611
2612 This is called in response to ifconfig down
2613
2614 \param - dev Pointer to net_device structure
2615
2616 \return - 0 for success non-zero for failure
2617
2618 --------------------------------------------------------------------------*/
2619
2620int hdd_stop (struct net_device *dev)
2621{
2622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2623 hdd_context_t *pHddCtx;
2624 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2625 VOS_STATUS status;
2626 v_BOOL_t enter_standby = TRUE;
2627
2628 ENTER();
2629
2630 if (NULL == pAdapter)
2631 {
2632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002633 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002634 return -ENODEV;
2635 }
2636
2637 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2638 if (NULL == pHddCtx)
2639 {
2640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002641 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 return -ENODEV;
2643 }
2644
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002645 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2647 netif_tx_disable(pAdapter->dev);
2648 netif_carrier_off(pAdapter->dev);
2649
2650
2651 /* SoftAP ifaces should never go in power save mode
2652 making sure same here. */
2653 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2654 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002656 )
2657 {
2658 /* SoftAP mode, so return from here */
2659 EXIT();
2660 return 0;
2661 }
2662
2663 /* Find if any iface is up then
2664 if any iface is up then can't put device to sleep/ power save mode. */
2665 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2666 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2667 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002668 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2669 {
2670 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302671 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002672 enter_standby = FALSE;
2673 break;
2674 }
2675 else
2676 {
2677 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2678 pAdapterNode = pNext;
2679 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002680 }
2681
2682 if (TRUE == enter_standby)
2683 {
2684 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2685 "entering standby", __func__);
2686 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2687 {
2688 /*log and return success*/
2689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2690 "wlan in power save", __func__);
2691 }
2692 }
2693
2694 EXIT();
2695 return 0;
2696}
2697
2698/**---------------------------------------------------------------------------
2699
2700 \brief hdd_uninit() - HDD uninit function
2701
2702 This is called during the netdev unregister to uninitialize all data
2703associated with the device
2704
2705 \param - dev Pointer to net_device structure
2706
2707 \return - void
2708
2709 --------------------------------------------------------------------------*/
2710static void hdd_uninit (struct net_device *dev)
2711{
2712 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2713
2714 ENTER();
2715
2716 do
2717 {
2718 if (NULL == pAdapter)
2719 {
2720 hddLog(VOS_TRACE_LEVEL_FATAL,
2721 "%s: NULL pAdapter", __func__);
2722 break;
2723 }
2724
2725 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2726 {
2727 hddLog(VOS_TRACE_LEVEL_FATAL,
2728 "%s: Invalid magic", __func__);
2729 break;
2730 }
2731
2732 if (NULL == pAdapter->pHddCtx)
2733 {
2734 hddLog(VOS_TRACE_LEVEL_FATAL,
2735 "%s: NULL pHddCtx", __func__);
2736 break;
2737 }
2738
2739 if (dev != pAdapter->dev)
2740 {
2741 hddLog(VOS_TRACE_LEVEL_FATAL,
2742 "%s: Invalid device reference", __func__);
2743 /* we haven't validated all cases so let this go for now */
2744 }
2745
2746 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2747
2748 /* after uninit our adapter structure will no longer be valid */
2749 pAdapter->dev = NULL;
2750 pAdapter->magic = 0;
2751 } while (0);
2752
2753 EXIT();
2754}
2755
2756/**---------------------------------------------------------------------------
2757
2758 \brief hdd_release_firmware() -
2759
2760 This function calls the release firmware API to free the firmware buffer.
2761
2762 \param - pFileName Pointer to the File Name.
2763 pCtx - Pointer to the adapter .
2764
2765
2766 \return - 0 for success, non zero for failure
2767
2768 --------------------------------------------------------------------------*/
2769
2770VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2771{
2772 VOS_STATUS status = VOS_STATUS_SUCCESS;
2773 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2774 ENTER();
2775
2776
2777 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2778
2779 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2780
2781 if(pHddCtx->fw) {
2782 release_firmware(pHddCtx->fw);
2783 pHddCtx->fw = NULL;
2784 }
2785 else
2786 status = VOS_STATUS_E_FAILURE;
2787 }
2788 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2789 if(pHddCtx->nv) {
2790 release_firmware(pHddCtx->nv);
2791 pHddCtx->nv = NULL;
2792 }
2793 else
2794 status = VOS_STATUS_E_FAILURE;
2795
2796 }
2797
2798 EXIT();
2799 return status;
2800}
2801
2802/**---------------------------------------------------------------------------
2803
2804 \brief hdd_request_firmware() -
2805
2806 This function reads the firmware file using the request firmware
2807 API and returns the the firmware data and the firmware file size.
2808
2809 \param - pfileName - Pointer to the file name.
2810 - pCtx - Pointer to the adapter .
2811 - ppfw_data - Pointer to the pointer of the firmware data.
2812 - pSize - Pointer to the file size.
2813
2814 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2815
2816 --------------------------------------------------------------------------*/
2817
2818
2819VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2820{
2821 int status;
2822 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2823 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2824 ENTER();
2825
2826 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2827
2828 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2829
2830 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2831 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2832 __func__, pfileName);
2833 retval = VOS_STATUS_E_FAILURE;
2834 }
2835
2836 else {
2837 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2838 *pSize = pHddCtx->fw->size;
2839 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2840 __func__, *pSize);
2841 }
2842 }
2843 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2844
2845 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2846
2847 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2849 __func__, pfileName);
2850 retval = VOS_STATUS_E_FAILURE;
2851 }
2852
2853 else {
2854 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2855 *pSize = pHddCtx->nv->size;
2856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2857 __func__, *pSize);
2858 }
2859 }
2860
2861 EXIT();
2862 return retval;
2863}
2864/**---------------------------------------------------------------------------
2865 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2866
2867 This is the function invoked by SME to inform the result of a full power
2868 request issued by HDD
2869
2870 \param - callbackcontext - Pointer to cookie
2871 status - result of request
2872
2873 \return - None
2874
2875--------------------------------------------------------------------------*/
2876void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2877{
2878 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2879
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002880 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 if(&pHddCtx->full_pwr_comp_var)
2882 {
2883 complete(&pHddCtx->full_pwr_comp_var);
2884 }
2885}
2886
2887/**---------------------------------------------------------------------------
2888
2889 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2890
2891 This is the function invoked by SME to inform the result of BMPS
2892 request issued by HDD
2893
2894 \param - callbackcontext - Pointer to cookie
2895 status - result of request
2896
2897 \return - None
2898
2899--------------------------------------------------------------------------*/
2900void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2901{
2902
2903 struct completion *completion_var = (struct completion*) callbackContext;
2904
2905 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2906 if(completion_var != NULL)
2907 {
2908 complete(completion_var);
2909 }
2910}
2911
2912/**---------------------------------------------------------------------------
2913
2914 \brief hdd_get_cfg_file_size() -
2915
2916 This function reads the configuration file using the request firmware
2917 API and returns the configuration file size.
2918
2919 \param - pCtx - Pointer to the adapter .
2920 - pFileName - Pointer to the file name.
2921 - pBufSize - Pointer to the buffer size.
2922
2923 \return - 0 for success, non zero for failure
2924
2925 --------------------------------------------------------------------------*/
2926
2927VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2928{
2929 int status;
2930 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2931
2932 ENTER();
2933
2934 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2935
2936 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2937 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2938 status = VOS_STATUS_E_FAILURE;
2939 }
2940 else {
2941 *pBufSize = pHddCtx->fw->size;
2942 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2943 release_firmware(pHddCtx->fw);
2944 pHddCtx->fw = NULL;
2945 }
2946
2947 EXIT();
2948 return VOS_STATUS_SUCCESS;
2949}
2950
2951/**---------------------------------------------------------------------------
2952
2953 \brief hdd_read_cfg_file() -
2954
2955 This function reads the configuration file using the request firmware
2956 API and returns the cfg data and the buffer size of the configuration file.
2957
2958 \param - pCtx - Pointer to the adapter .
2959 - pFileName - Pointer to the file name.
2960 - pBuffer - Pointer to the data buffer.
2961 - pBufSize - Pointer to the buffer size.
2962
2963 \return - 0 for success, non zero for failure
2964
2965 --------------------------------------------------------------------------*/
2966
2967VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2968 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2969{
2970 int status;
2971 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2972
2973 ENTER();
2974
2975 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2976
2977 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2979 return VOS_STATUS_E_FAILURE;
2980 }
2981 else {
2982 if(*pBufSize != pHddCtx->fw->size) {
2983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2984 "file size", __func__);
2985 release_firmware(pHddCtx->fw);
2986 pHddCtx->fw = NULL;
2987 return VOS_STATUS_E_FAILURE;
2988 }
2989 else {
2990 if(pBuffer) {
2991 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2992 }
2993 release_firmware(pHddCtx->fw);
2994 pHddCtx->fw = NULL;
2995 }
2996 }
2997
2998 EXIT();
2999
3000 return VOS_STATUS_SUCCESS;
3001}
3002
3003/**---------------------------------------------------------------------------
3004
Jeff Johnson295189b2012-06-20 16:38:30 -07003005 \brief hdd_set_mac_address() -
3006
3007 This function sets the user specified mac address using
3008 the command ifconfig wlanX hw ether <mac adress>.
3009
3010 \param - dev - Pointer to the net device.
3011 - addr - Pointer to the sockaddr.
3012 \return - 0 for success, non zero for failure
3013
3014 --------------------------------------------------------------------------*/
3015
3016static int hdd_set_mac_address(struct net_device *dev, void *addr)
3017{
3018 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3019 struct sockaddr *psta_mac_addr = addr;
3020 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3021
3022 ENTER();
3023
3024 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3025
3026#ifdef HDD_SESSIONIZE
3027 // set the MAC address though the STA ID CFG.
3028 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3029 (v_U8_t *)&pAdapter->macAddressCurrent,
3030 sizeof( pAdapter->macAddressCurrent ),
3031 hdd_set_mac_addr_cb, VOS_FALSE );
3032#endif
3033
3034 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3035
3036 EXIT();
3037 return halStatus;
3038}
3039
3040tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3041{
3042 int i;
3043 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3044 {
3045 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3046 break;
3047 }
3048
3049 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3050 return NULL;
3051
3052 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3053 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3054}
3055
3056void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3057{
3058 int i;
3059 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3060 {
3061 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3062 {
3063 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3064 break;
3065 }
3066 }
3067 return;
3068}
3069
3070#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3071 static struct net_device_ops wlan_drv_ops = {
3072 .ndo_open = hdd_open,
3073 .ndo_stop = hdd_stop,
3074 .ndo_uninit = hdd_uninit,
3075 .ndo_start_xmit = hdd_hard_start_xmit,
3076 .ndo_tx_timeout = hdd_tx_timeout,
3077 .ndo_get_stats = hdd_stats,
3078 .ndo_do_ioctl = hdd_ioctl,
3079 .ndo_set_mac_address = hdd_set_mac_address,
3080 .ndo_select_queue = hdd_select_queue,
3081#ifdef WLAN_FEATURE_PACKET_FILTERING
3082#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3083 .ndo_set_rx_mode = hdd_set_multicast_list,
3084#else
3085 .ndo_set_multicast_list = hdd_set_multicast_list,
3086#endif //LINUX_VERSION_CODE
3087#endif
3088 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 static struct net_device_ops wlan_mon_drv_ops = {
3090 .ndo_open = hdd_mon_open,
3091 .ndo_stop = hdd_stop,
3092 .ndo_uninit = hdd_uninit,
3093 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3094 .ndo_tx_timeout = hdd_tx_timeout,
3095 .ndo_get_stats = hdd_stats,
3096 .ndo_do_ioctl = hdd_ioctl,
3097 .ndo_set_mac_address = hdd_set_mac_address,
3098 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003099
3100#endif
3101
3102void hdd_set_station_ops( struct net_device *pWlanDev )
3103{
3104#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3105 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3106 pWlanDev->netdev_ops = &wlan_drv_ops;
3107#else
3108 pWlanDev->open = hdd_open;
3109 pWlanDev->stop = hdd_stop;
3110 pWlanDev->uninit = hdd_uninit;
3111 pWlanDev->hard_start_xmit = NULL;
3112 pWlanDev->tx_timeout = hdd_tx_timeout;
3113 pWlanDev->get_stats = hdd_stats;
3114 pWlanDev->do_ioctl = hdd_ioctl;
3115 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3116 pWlanDev->set_mac_address = hdd_set_mac_address;
3117#endif
3118}
3119
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003120static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003121{
3122 struct net_device *pWlanDev = NULL;
3123 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003124 /*
3125 * cfg80211 initialization and registration....
3126 */
3127 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3128
Jeff Johnson295189b2012-06-20 16:38:30 -07003129 if(pWlanDev != NULL)
3130 {
3131
3132 //Save the pointer to the net_device in the HDD adapter
3133 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3134
Jeff Johnson295189b2012-06-20 16:38:30 -07003135 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3136
3137 pAdapter->dev = pWlanDev;
3138 pAdapter->pHddCtx = pHddCtx;
3139 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3140
3141 init_completion(&pAdapter->session_open_comp_var);
3142 init_completion(&pAdapter->session_close_comp_var);
3143 init_completion(&pAdapter->disconnect_comp_var);
3144 init_completion(&pAdapter->linkup_event_var);
3145 init_completion(&pAdapter->cancel_rem_on_chan_var);
3146 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003147#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3148 init_completion(&pAdapter->offchannel_tx_event);
3149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003150 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003151#ifdef FEATURE_WLAN_TDLS
3152 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003153 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003154 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303155 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003157 init_completion(&pHddCtx->mc_sus_event_var);
3158 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303159 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003160 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003161
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 pAdapter->isLinkUpSvcNeeded = FALSE;
3163 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3164 //Init the net_device structure
3165 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3166
3167 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3168 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3169 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3170 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3171
3172 hdd_set_station_ops( pAdapter->dev );
3173
3174 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3176 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3177 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003178 /* set pWlanDev's parent to underlying device */
3179 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3180 }
3181
3182 return pAdapter;
3183}
3184
3185VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3186{
3187 struct net_device *pWlanDev = pAdapter->dev;
3188 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3189 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3190 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3191
3192 if( rtnl_lock_held )
3193 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003194 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3196 {
3197 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3198 return VOS_STATUS_E_FAILURE;
3199 }
3200 }
3201 if (register_netdevice(pWlanDev))
3202 {
3203 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3204 return VOS_STATUS_E_FAILURE;
3205 }
3206 }
3207 else
3208 {
3209 if(register_netdev(pWlanDev))
3210 {
3211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3212 return VOS_STATUS_E_FAILURE;
3213 }
3214 }
3215 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3216
3217 return VOS_STATUS_SUCCESS;
3218}
3219
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003220static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003221{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003222 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003223
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003224 if (NULL == pAdapter)
3225 {
3226 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3227 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003228 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003229
3230 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3231 {
3232 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3233 return eHAL_STATUS_NOT_INITIALIZED;
3234 }
3235
3236 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3237
3238 /* need to make sure all of our scheduled work has completed.
3239 * This callback is called from MC thread context, so it is safe to
3240 * to call below flush workqueue API from here.
3241 */
3242 flush_scheduled_work();
3243
3244 /* We can be blocked while waiting for scheduled work to be
3245 * flushed, and the adapter structure can potentially be freed, in
3246 * which case the magic will have been reset. So make sure the
3247 * magic is still good, and hence the adapter structure is still
3248 * valid, before signaling completion */
3249 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3250 {
3251 complete(&pAdapter->session_close_comp_var);
3252 }
3253
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 return eHAL_STATUS_SUCCESS;
3255}
3256
3257VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3258{
3259 struct net_device *pWlanDev = pAdapter->dev;
3260 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3261 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3262 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3263 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3264 int rc = 0;
3265
3266 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003267 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003268 //Open a SME session for future operation
3269 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003270 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3272 {
3273 hddLog(VOS_TRACE_LEVEL_FATAL,
3274 "sme_OpenSession() failed with status code %08d [x%08lx]",
3275 halStatus, halStatus );
3276 status = VOS_STATUS_E_FAILURE;
3277 goto error_sme_open;
3278 }
3279
3280 //Block on a completion variable. Can't wait forever though.
3281 rc = wait_for_completion_interruptible_timeout(
3282 &pAdapter->session_open_comp_var,
3283 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3284 if (!rc)
3285 {
3286 hddLog(VOS_TRACE_LEVEL_FATAL,
3287 "Session is not opened within timeout period code %08d", rc );
3288 status = VOS_STATUS_E_FAILURE;
3289 goto error_sme_open;
3290 }
3291
3292 // Register wireless extensions
3293 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3294 {
3295 hddLog(VOS_TRACE_LEVEL_FATAL,
3296 "hdd_register_wext() failed with status code %08d [x%08lx]",
3297 halStatus, halStatus );
3298 status = VOS_STATUS_E_FAILURE;
3299 goto error_register_wext;
3300 }
3301 //Safe to register the hard_start_xmit function again
3302#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3303 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3304#else
3305 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3306#endif
3307
3308 //Set the Connection State to Not Connected
3309 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3310
3311 //Set the default operation channel
3312 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3313
3314 /* Make the default Auth Type as OPEN*/
3315 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3316
3317 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3318 {
3319 hddLog(VOS_TRACE_LEVEL_FATAL,
3320 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3321 status, status );
3322 goto error_init_txrx;
3323 }
3324
3325 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3326
3327 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3328 {
3329 hddLog(VOS_TRACE_LEVEL_FATAL,
3330 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3331 status, status );
3332 goto error_wmm_init;
3333 }
3334
3335 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3336
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003337#ifdef FEATURE_WLAN_TDLS
3338 if(0 != wlan_hdd_tdls_init(pAdapter))
3339 {
3340 status = VOS_STATUS_E_FAILURE;
3341 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3342 goto error_tdls_init;
3343 }
3344 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3345#endif
3346
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 return VOS_STATUS_SUCCESS;
3348
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003349#ifdef FEATURE_WLAN_TDLS
3350error_tdls_init:
3351 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3352 hdd_wmm_adapter_close(pAdapter);
3353#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003354error_wmm_init:
3355 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3356 hdd_deinit_tx_rx(pAdapter);
3357error_init_txrx:
3358 hdd_UnregisterWext(pWlanDev);
3359error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003360 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 {
3362 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003363 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003365 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 {
3367 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003368 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003370 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 }
3372}
3373error_sme_open:
3374 return status;
3375}
3376
Jeff Johnson295189b2012-06-20 16:38:30 -07003377void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3378{
3379 hdd_cfg80211_state_t *cfgState;
3380
3381 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3382
3383 if( NULL != cfgState->buf )
3384 {
3385 int rc;
3386 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3387 rc = wait_for_completion_interruptible_timeout(
3388 &pAdapter->tx_action_cnf_event,
3389 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3390 if(!rc)
3391 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003392 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003393 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3394 }
3395 }
3396 return;
3397}
Jeff Johnson295189b2012-06-20 16:38:30 -07003398
3399void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3400{
3401 ENTER();
3402 switch ( pAdapter->device_mode )
3403 {
3404 case WLAN_HDD_INFRA_STATION:
3405 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003406 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003407 {
3408 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3409 {
3410 hdd_deinit_tx_rx( pAdapter );
3411 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3412 }
3413
3414 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3415 {
3416 hdd_wmm_adapter_close( pAdapter );
3417 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3418 }
3419
Jeff Johnson295189b2012-06-20 16:38:30 -07003420 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003421#ifdef FEATURE_WLAN_TDLS
3422 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3423 {
3424 wlan_hdd_tdls_exit(pAdapter);
3425 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3426 }
3427#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003428
3429 break;
3430 }
3431
3432 case WLAN_HDD_SOFTAP:
3433 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003435 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003436
3437 hdd_unregister_hostapd(pAdapter);
3438 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003439 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 break;
3441 }
3442
3443 case WLAN_HDD_MONITOR:
3444 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003445 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003446 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3447 {
3448 hdd_deinit_tx_rx( pAdapter );
3449 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3450 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003451 if(NULL != pAdapterforTx)
3452 {
3453 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3454 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003455 break;
3456 }
3457
3458
3459 default:
3460 break;
3461 }
3462
3463 EXIT();
3464}
3465
3466void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3467{
3468 struct net_device *pWlanDev = pAdapter->dev;
3469
3470 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3471 if( rtnl_held )
3472 {
3473 unregister_netdevice(pWlanDev);
3474 }
3475 else
3476 {
3477 unregister_netdev(pWlanDev);
3478 }
3479 // note that the pAdapter is no longer valid at this point
3480 // since the memory has been reclaimed
3481 }
3482
3483}
3484
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003485void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3486{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303487 VOS_STATUS status;
3488 hdd_adapter_t *pAdapter = NULL;
3489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003490
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303491 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003492
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303493 /*loop through all adapters.*/
3494 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003495 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303496 pAdapter = pAdapterNode->pAdapter;
3497 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3498 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003499
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303500 { // we skip this registration for modes other than STA and P2P client modes.
3501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3502 pAdapterNode = pNext;
3503 continue;
3504 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003505
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303506 //Apply Dynamic DTIM For P2P
3507 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3508 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3509 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3510 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3511 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3512 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3513 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3514 (eConnectionState_Associated ==
3515 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3516 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3517 {
3518 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003519
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303520 powerRequest.uIgnoreDTIM = 1;
3521 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3522
3523 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3524 {
3525 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3526 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3527 }
3528 else
3529 {
3530 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3531 }
3532
3533 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3534 * specified during Enter/Exit BMPS when LCD off*/
3535 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3536 NULL, eANI_BOOLEAN_FALSE);
3537 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3538 NULL, eANI_BOOLEAN_FALSE);
3539
3540 /* switch to the DTIM specified in cfg.ini */
3541 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3542 "Switch to DTIM %d", powerRequest.uListenInterval);
3543 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3544 break;
3545
3546 }
3547
3548 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3549 pAdapterNode = pNext;
3550 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003551}
3552
3553void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3554{
3555 /*Switch back to DTIM 1*/
3556 tSirSetPowerParamsReq powerRequest = { 0 };
3557
3558 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3559 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003560 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003561
3562 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3563 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3564 NULL, eANI_BOOLEAN_FALSE);
3565 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3566 NULL, eANI_BOOLEAN_FALSE);
3567
3568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3569 "Switch to DTIM%d",powerRequest.uListenInterval);
3570 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3571
3572}
3573
Jeff Johnson295189b2012-06-20 16:38:30 -07003574VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3575{
3576 VOS_STATUS status = VOS_STATUS_SUCCESS;
3577
3578 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3579 {
3580 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3581 }
3582
3583 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3584 {
3585 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3586 }
3587
3588 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3589 {
3590 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3591 }
3592
3593 return status;
3594}
3595
3596VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3597{
3598 hdd_adapter_t *pAdapter = NULL;
3599 eHalStatus halStatus;
3600 VOS_STATUS status = VOS_STATUS_E_INVAL;
3601 v_BOOL_t disableBmps = FALSE;
3602 v_BOOL_t disableImps = FALSE;
3603
3604 switch(session_type)
3605 {
3606 case WLAN_HDD_INFRA_STATION:
3607 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003608 case WLAN_HDD_P2P_CLIENT:
3609 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003610 //Exit BMPS -> Is Sta/P2P Client is already connected
3611 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3612 if((NULL != pAdapter)&&
3613 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3614 {
3615 disableBmps = TRUE;
3616 }
3617
3618 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3619 if((NULL != pAdapter)&&
3620 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3621 {
3622 disableBmps = TRUE;
3623 }
3624
3625 //Exit both Bmps and Imps incase of Go/SAP Mode
3626 if((WLAN_HDD_SOFTAP == session_type) ||
3627 (WLAN_HDD_P2P_GO == session_type))
3628 {
3629 disableBmps = TRUE;
3630 disableImps = TRUE;
3631 }
3632
3633 if(TRUE == disableImps)
3634 {
3635 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3636 {
3637 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3638 }
3639 }
3640
3641 if(TRUE == disableBmps)
3642 {
3643 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3644 {
3645 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3646
3647 if(eHAL_STATUS_SUCCESS != halStatus)
3648 {
3649 status = VOS_STATUS_E_FAILURE;
3650 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3651 VOS_ASSERT(0);
3652 return status;
3653 }
3654 }
3655
3656 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3657 {
3658 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3659
3660 if(eHAL_STATUS_SUCCESS != halStatus)
3661 {
3662 status = VOS_STATUS_E_FAILURE;
3663 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3664 VOS_ASSERT(0);
3665 return status;
3666 }
3667 }
3668 }
3669
3670 if((TRUE == disableBmps) ||
3671 (TRUE == disableImps))
3672 {
3673 /* Now, get the chip into Full Power now */
3674 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3675 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3676 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3677
3678 if(halStatus != eHAL_STATUS_SUCCESS)
3679 {
3680 if(halStatus == eHAL_STATUS_PMC_PENDING)
3681 {
3682 //Block on a completion variable. Can't wait forever though
3683 wait_for_completion_interruptible_timeout(
3684 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3685 }
3686 else
3687 {
3688 status = VOS_STATUS_E_FAILURE;
3689 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3690 VOS_ASSERT(0);
3691 return status;
3692 }
3693 }
3694
3695 status = VOS_STATUS_SUCCESS;
3696 }
3697
3698 break;
3699 }
3700 return status;
3701}
3702
3703hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003704 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003705 tANI_U8 rtnl_held )
3706{
3707 hdd_adapter_t *pAdapter = NULL;
3708 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3709 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3710 VOS_STATUS exitbmpsStatus;
3711
3712 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3713
3714 //Disable BMPS incase of Concurrency
3715 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3716
3717 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3718 {
3719 //Fail to Exit BMPS
3720 VOS_ASSERT(0);
3721 return NULL;
3722 }
3723
3724 switch(session_type)
3725 {
3726 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003728 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 {
3730 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3731
3732 if( NULL == pAdapter )
3733 return NULL;
3734
Jeff Johnsone7245742012-09-05 17:12:55 -07003735 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3736 NL80211_IFTYPE_P2P_CLIENT:
3737 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003738
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 pAdapter->device_mode = session_type;
3740
3741 status = hdd_init_station_mode( pAdapter );
3742 if( VOS_STATUS_SUCCESS != status )
3743 goto err_free_netdev;
3744
3745 status = hdd_register_interface( pAdapter, rtnl_held );
3746 if( VOS_STATUS_SUCCESS != status )
3747 {
3748 hdd_deinit_adapter(pHddCtx, pAdapter);
3749 goto err_free_netdev;
3750 }
3751 //Stop the Interface TX queue.
3752 netif_tx_disable(pAdapter->dev);
3753 //netif_tx_disable(pWlanDev);
3754 netif_carrier_off(pAdapter->dev);
3755
3756 break;
3757 }
3758
Jeff Johnson295189b2012-06-20 16:38:30 -07003759 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003760 case WLAN_HDD_SOFTAP:
3761 {
3762 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3763 if( NULL == pAdapter )
3764 return NULL;
3765
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3767 NL80211_IFTYPE_AP:
3768 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 pAdapter->device_mode = session_type;
3770
3771 status = hdd_init_ap_mode(pAdapter);
3772 if( VOS_STATUS_SUCCESS != status )
3773 goto err_free_netdev;
3774
3775 status = hdd_register_hostapd( pAdapter, rtnl_held );
3776 if( VOS_STATUS_SUCCESS != status )
3777 {
3778 hdd_deinit_adapter(pHddCtx, pAdapter);
3779 goto err_free_netdev;
3780 }
3781
3782 netif_tx_disable(pAdapter->dev);
3783 netif_carrier_off(pAdapter->dev);
3784
3785 hdd_set_conparam( 1 );
3786 break;
3787 }
3788 case WLAN_HDD_MONITOR:
3789 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3791 if( NULL == pAdapter )
3792 return NULL;
3793
3794 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3795 pAdapter->device_mode = session_type;
3796 status = hdd_register_interface( pAdapter, rtnl_held );
3797#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3798 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3799#else
3800 pAdapter->dev->open = hdd_mon_open;
3801 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3802#endif
3803 hdd_init_tx_rx( pAdapter );
3804 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3805 //Set adapter to be used for data tx. It will use either GO or softap.
3806 pAdapter->sessionCtx.monitor.pAdapterForTx =
3807 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3809 {
3810 pAdapter->sessionCtx.monitor.pAdapterForTx =
3811 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3812 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 /* This workqueue will be used to transmit management packet over
3814 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003815 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3816 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3817 return NULL;
3818 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003819
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3821 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 }
3823 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 case WLAN_HDD_FTM:
3825 {
3826 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3827
3828 if( NULL == pAdapter )
3829 return NULL;
3830 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3831 * message while loading driver in FTM mode. */
3832 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3833 pAdapter->device_mode = session_type;
3834 status = hdd_register_interface( pAdapter, rtnl_held );
3835 }
3836 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 default:
3838 {
3839 VOS_ASSERT(0);
3840 return NULL;
3841 }
3842 }
3843
3844
3845 if( VOS_STATUS_SUCCESS == status )
3846 {
3847 //Add it to the hdd's session list.
3848 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3849 if( NULL == pHddAdapterNode )
3850 {
3851 status = VOS_STATUS_E_NOMEM;
3852 }
3853 else
3854 {
3855 pHddAdapterNode->pAdapter = pAdapter;
3856 status = hdd_add_adapter_back ( pHddCtx,
3857 pHddAdapterNode );
3858 }
3859 }
3860
3861 if( VOS_STATUS_SUCCESS != status )
3862 {
3863 if( NULL != pAdapter )
3864 {
3865 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3866 pAdapter = NULL;
3867 }
3868 if( NULL != pHddAdapterNode )
3869 {
3870 vos_mem_free( pHddAdapterNode );
3871 }
3872
3873 goto resume_bmps;
3874 }
3875
3876 if(VOS_STATUS_SUCCESS == status)
3877 {
3878 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3879
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003880 //Initialize the WoWL service
3881 if(!hdd_init_wowl(pAdapter))
3882 {
3883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3884 goto err_free_netdev;
3885 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 return pAdapter;
3888
3889err_free_netdev:
3890 free_netdev(pAdapter->dev);
3891 wlan_hdd_release_intf_addr( pHddCtx,
3892 pAdapter->macAddressCurrent.bytes );
3893
3894resume_bmps:
3895 //If bmps disabled enable it
3896 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3897 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303898 if (pHddCtx->hdd_wlan_suspended)
3899 {
3900 hdd_set_pwrparams(pHddCtx);
3901 }
3902 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
3904 return NULL;
3905}
3906
3907VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3908 tANI_U8 rtnl_held )
3909{
3910 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3911 VOS_STATUS status;
3912
3913 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3914 if( VOS_STATUS_SUCCESS != status )
3915 return status;
3916
3917 while ( pCurrent->pAdapter != pAdapter )
3918 {
3919 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3920 if( VOS_STATUS_SUCCESS != status )
3921 break;
3922
3923 pCurrent = pNext;
3924 }
3925 pAdapterNode = pCurrent;
3926 if( VOS_STATUS_SUCCESS == status )
3927 {
3928 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3929 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3930 hdd_remove_adapter( pHddCtx, pAdapterNode );
3931 vos_mem_free( pAdapterNode );
3932
Jeff Johnson295189b2012-06-20 16:38:30 -07003933
3934 /* If there is a single session of STA/P2P client, re-enable BMPS */
3935 if ((!vos_concurrent_sessions_running()) &&
3936 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3937 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3938 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303939 if (pHddCtx->hdd_wlan_suspended)
3940 {
3941 hdd_set_pwrparams(pHddCtx);
3942 }
3943 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003944 }
3945
3946 return VOS_STATUS_SUCCESS;
3947 }
3948
3949 return VOS_STATUS_E_FAILURE;
3950}
3951
3952VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3953{
3954 hdd_adapter_list_node_t *pHddAdapterNode;
3955 VOS_STATUS status;
3956
3957 ENTER();
3958
3959 do
3960 {
3961 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3962 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3963 {
3964 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3965 vos_mem_free( pHddAdapterNode );
3966 }
3967 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3968
3969 EXIT();
3970
3971 return VOS_STATUS_SUCCESS;
3972}
3973
3974void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3975{
3976 v_U8_t addIE[1] = {0};
3977
3978 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3979 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3980 eANI_BOOLEAN_FALSE) )
3981 {
3982 hddLog(LOGE,
3983 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3984 }
3985
3986 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3987 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3988 eANI_BOOLEAN_FALSE) )
3989 {
3990 hddLog(LOGE,
3991 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3992 }
3993
3994 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3995 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3996 eANI_BOOLEAN_FALSE) )
3997 {
3998 hddLog(LOGE,
3999 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4000 }
4001}
4002
4003VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4004{
4005 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4006 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4007 union iwreq_data wrqu;
4008
4009 ENTER();
4010
4011 switch(pAdapter->device_mode)
4012 {
4013 case WLAN_HDD_INFRA_STATION:
4014 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004015 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4017 {
4018 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4019 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4020 pAdapter->sessionId,
4021 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4022 else
4023 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4024 pAdapter->sessionId,
4025 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4026 //success implies disconnect command got queued up successfully
4027 if(halStatus == eHAL_STATUS_SUCCESS)
4028 {
4029 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4030 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4031 }
4032 memset(&wrqu, '\0', sizeof(wrqu));
4033 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4034 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4035 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4036 }
4037 else
4038 {
4039 hdd_abort_mac_scan(pHddCtx);
4040 }
4041
4042 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4043 {
4044 INIT_COMPLETION(pAdapter->session_close_comp_var);
4045 if (eHAL_STATUS_SUCCESS ==
4046 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4047 hdd_smeCloseSessionCallback, pAdapter))
4048 {
4049 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004050 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004051 &pAdapter->session_close_comp_var,
4052 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4053 }
4054 }
4055
4056 break;
4057
4058 case WLAN_HDD_SOFTAP:
4059 case WLAN_HDD_P2P_GO:
4060 //Any softap specific cleanup here...
4061 mutex_lock(&pHddCtx->sap_lock);
4062 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4063 {
4064 VOS_STATUS status;
4065 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4066
4067 //Stop Bss.
4068 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4069 if (VOS_IS_STATUS_SUCCESS(status))
4070 {
4071 hdd_hostapd_state_t *pHostapdState =
4072 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4073
4074 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4075
4076 if (!VOS_IS_STATUS_SUCCESS(status))
4077 {
4078 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004079 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
4081 }
4082 else
4083 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004084 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 }
4086 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4087
4088 if (eHAL_STATUS_FAILURE ==
4089 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4090 0, NULL, eANI_BOOLEAN_FALSE))
4091 {
4092 hddLog(LOGE,
4093 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004094 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 }
4096
4097 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4098 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4099 eANI_BOOLEAN_FALSE) )
4100 {
4101 hddLog(LOGE,
4102 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4103 }
4104
4105 // Reset WNI_CFG_PROBE_RSP Flags
4106 wlan_hdd_reset_prob_rspies(pAdapter);
4107 kfree(pAdapter->sessionCtx.ap.beacon);
4108 pAdapter->sessionCtx.ap.beacon = NULL;
4109 }
4110 mutex_unlock(&pHddCtx->sap_lock);
4111 break;
4112 case WLAN_HDD_MONITOR:
4113 break;
4114 default:
4115 break;
4116 }
4117
4118 EXIT();
4119 return VOS_STATUS_SUCCESS;
4120}
4121
4122VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4123{
4124 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4125 VOS_STATUS status;
4126 hdd_adapter_t *pAdapter;
4127
4128 ENTER();
4129
4130 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4131
4132 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4133 {
4134 pAdapter = pAdapterNode->pAdapter;
4135 netif_tx_disable(pAdapter->dev);
4136 netif_carrier_off(pAdapter->dev);
4137
4138 hdd_stop_adapter( pHddCtx, pAdapter );
4139
4140 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4141 pAdapterNode = pNext;
4142 }
4143
4144 EXIT();
4145
4146 return VOS_STATUS_SUCCESS;
4147}
4148
4149VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4150{
4151 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4152 VOS_STATUS status;
4153 hdd_adapter_t *pAdapter;
4154
4155 ENTER();
4156
4157 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4158
4159 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4160 {
4161 pAdapter = pAdapterNode->pAdapter;
4162 netif_tx_disable(pAdapter->dev);
4163 netif_carrier_off(pAdapter->dev);
4164
Jeff Johnson295189b2012-06-20 16:38:30 -07004165 hdd_deinit_tx_rx(pAdapter);
4166 hdd_wmm_adapter_close(pAdapter);
4167
4168 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4169 pAdapterNode = pNext;
4170 }
4171
4172 EXIT();
4173
4174 return VOS_STATUS_SUCCESS;
4175}
4176
4177VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4178{
4179 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4180 VOS_STATUS status;
4181 hdd_adapter_t *pAdapter;
4182 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304183 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004184
4185 ENTER();
4186
4187 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4188
4189 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4190 {
4191 pAdapter = pAdapterNode->pAdapter;
4192
4193 switch(pAdapter->device_mode)
4194 {
4195 case WLAN_HDD_INFRA_STATION:
4196 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004197 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304198
4199 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4200
Jeff Johnson295189b2012-06-20 16:38:30 -07004201 hdd_init_station_mode(pAdapter);
4202 /* Open the gates for HDD to receive Wext commands */
4203 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004204 pHddCtx->scan_info.mScanPending = FALSE;
4205 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004206
4207 //Trigger the initial scan
4208 hdd_wlan_initial_scan(pAdapter);
4209
4210 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304211 if (eConnectionState_Associated == connState ||
4212 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004213 {
4214 union iwreq_data wrqu;
4215 memset(&wrqu, '\0', sizeof(wrqu));
4216 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4217 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4218 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004219
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 /* indicate disconnected event to nl80211 */
4221 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4222 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304224 else if (eConnectionState_Connecting == connState)
4225 {
4226 /*
4227 * Indicate connect failure to supplicant if we were in the
4228 * process of connecting
4229 */
4230 cfg80211_connect_result(pAdapter->dev, NULL,
4231 NULL, 0, NULL, 0,
4232 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4233 GFP_KERNEL);
4234 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 break;
4236
4237 case WLAN_HDD_SOFTAP:
4238 /* softAP can handle SSR */
4239 break;
4240
4241 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004242 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4243 __func__);
4244 /* event supplicant to restart */
4245 cfg80211_del_sta(pAdapter->dev,
4246 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 break;
4248
4249 case WLAN_HDD_MONITOR:
4250 /* monitor interface start */
4251 break;
4252 default:
4253 break;
4254 }
4255
4256 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4257 pAdapterNode = pNext;
4258 }
4259
4260 EXIT();
4261
4262 return VOS_STATUS_SUCCESS;
4263}
4264
4265VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4266{
4267 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4268 hdd_adapter_t *pAdapter;
4269 VOS_STATUS status;
4270 v_U32_t roamId;
4271
4272 ENTER();
4273
4274 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4275
4276 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4277 {
4278 pAdapter = pAdapterNode->pAdapter;
4279
4280 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4281 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4282 {
4283 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4284 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4285
4286 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4287 init_completion(&pAdapter->disconnect_comp_var);
4288 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4289 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4290
4291 wait_for_completion_interruptible_timeout(
4292 &pAdapter->disconnect_comp_var,
4293 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4294
4295 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4296 pHddCtx->isAmpAllowed = VOS_FALSE;
4297 sme_RoamConnect(pHddCtx->hHal,
4298 pAdapter->sessionId, &(pWextState->roamProfile),
4299 &roamId);
4300 }
4301
4302 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4303 pAdapterNode = pNext;
4304 }
4305
4306 EXIT();
4307
4308 return VOS_STATUS_SUCCESS;
4309}
4310
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004311void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4312{
4313 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4314 VOS_STATUS status;
4315 hdd_adapter_t *pAdapter;
4316 hdd_station_ctx_t *pHddStaCtx;
4317 hdd_ap_ctx_t *pHddApCtx;
4318 hdd_hostapd_state_t * pHostapdState;
4319 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4320 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4321 const char *p2pMode = "DEV";
4322 const char *ccMode = "Standalone";
4323 int n;
4324
4325 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4326 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4327 {
4328 pAdapter = pAdapterNode->pAdapter;
4329 switch (pAdapter->device_mode) {
4330 case WLAN_HDD_INFRA_STATION:
4331 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4332 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4333 staChannel = pHddStaCtx->conn_info.operationChannel;
4334 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4335 }
4336 break;
4337 case WLAN_HDD_P2P_CLIENT:
4338 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4339 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4340 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4341 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4342 p2pMode = "CLI";
4343 }
4344 break;
4345 case WLAN_HDD_P2P_GO:
4346 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4347 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4348 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4349 p2pChannel = pHddApCtx->operatingChannel;
4350 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4351 }
4352 p2pMode = "GO";
4353 break;
4354 case WLAN_HDD_SOFTAP:
4355 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4356 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4357 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4358 apChannel = pHddApCtx->operatingChannel;
4359 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4360 }
4361 break;
4362 default:
4363 break;
4364 }
4365 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4366 pAdapterNode = pNext;
4367 }
4368 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4369 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4370 }
4371 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4372 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4373 if (p2pChannel > 0) {
4374 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4375 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4376 }
4377 if (apChannel > 0) {
4378 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4379 apChannel, MAC_ADDR_ARRAY(apBssid));
4380 }
4381
4382 if (p2pChannel > 0 && apChannel > 0) {
4383 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4384 }
4385}
4386
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004387bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004388{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004389 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004390}
4391
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004392/* Once SSR is disabled then it cannot be set. */
4393void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004394{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004395 if (HDD_SSR_DISABLED == isSsrRequired)
4396 return;
4397
Jeff Johnson295189b2012-06-20 16:38:30 -07004398 isSsrRequired = value;
4399}
4400
4401VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4402 hdd_adapter_list_node_t** ppAdapterNode)
4403{
4404 VOS_STATUS status;
4405 spin_lock(&pHddCtx->hddAdapters.lock);
4406 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4407 (hdd_list_node_t**) ppAdapterNode );
4408 spin_unlock(&pHddCtx->hddAdapters.lock);
4409 return status;
4410}
4411
4412VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4413 hdd_adapter_list_node_t* pAdapterNode,
4414 hdd_adapter_list_node_t** pNextAdapterNode)
4415{
4416 VOS_STATUS status;
4417 spin_lock(&pHddCtx->hddAdapters.lock);
4418 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4419 (hdd_list_node_t*) pAdapterNode,
4420 (hdd_list_node_t**)pNextAdapterNode );
4421
4422 spin_unlock(&pHddCtx->hddAdapters.lock);
4423 return status;
4424}
4425
4426VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4427 hdd_adapter_list_node_t* pAdapterNode)
4428{
4429 VOS_STATUS status;
4430 spin_lock(&pHddCtx->hddAdapters.lock);
4431 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4432 &pAdapterNode->node );
4433 spin_unlock(&pHddCtx->hddAdapters.lock);
4434 return status;
4435}
4436
4437VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4438 hdd_adapter_list_node_t** ppAdapterNode)
4439{
4440 VOS_STATUS status;
4441 spin_lock(&pHddCtx->hddAdapters.lock);
4442 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4443 (hdd_list_node_t**) ppAdapterNode );
4444 spin_unlock(&pHddCtx->hddAdapters.lock);
4445 return status;
4446}
4447
4448VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4449 hdd_adapter_list_node_t* pAdapterNode)
4450{
4451 VOS_STATUS status;
4452 spin_lock(&pHddCtx->hddAdapters.lock);
4453 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4454 (hdd_list_node_t*) pAdapterNode );
4455 spin_unlock(&pHddCtx->hddAdapters.lock);
4456 return status;
4457}
4458
4459VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4460 hdd_adapter_list_node_t* pAdapterNode)
4461{
4462 VOS_STATUS status;
4463 spin_lock(&pHddCtx->hddAdapters.lock);
4464 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4465 (hdd_list_node_t*) pAdapterNode );
4466 spin_unlock(&pHddCtx->hddAdapters.lock);
4467 return status;
4468}
4469
4470hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4471 tSirMacAddr macAddr )
4472{
4473 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4474 hdd_adapter_t *pAdapter;
4475 VOS_STATUS status;
4476
4477 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4478
4479 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4480 {
4481 pAdapter = pAdapterNode->pAdapter;
4482
4483 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4484 macAddr, sizeof(tSirMacAddr) ) )
4485 {
4486 return pAdapter;
4487 }
4488 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4489 pAdapterNode = pNext;
4490 }
4491
4492 return NULL;
4493
4494}
4495
4496hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4497{
4498 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4499 hdd_adapter_t *pAdapter;
4500 VOS_STATUS status;
4501
4502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4503
4504 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4505 {
4506 pAdapter = pAdapterNode->pAdapter;
4507
4508 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4509 IFNAMSIZ ) )
4510 {
4511 return pAdapter;
4512 }
4513 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4514 pAdapterNode = pNext;
4515 }
4516
4517 return NULL;
4518
4519}
4520
4521hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4522{
4523 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4524 hdd_adapter_t *pAdapter;
4525 VOS_STATUS status;
4526
4527 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4528
4529 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4530 {
4531 pAdapter = pAdapterNode->pAdapter;
4532
4533 if( pAdapter && (mode == pAdapter->device_mode) )
4534 {
4535 return pAdapter;
4536 }
4537 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4538 pAdapterNode = pNext;
4539 }
4540
4541 return NULL;
4542
4543}
4544
4545//Remove this function later
4546hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4547{
4548 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4549 hdd_adapter_t *pAdapter;
4550 VOS_STATUS status;
4551
4552 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4553
4554 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4555 {
4556 pAdapter = pAdapterNode->pAdapter;
4557
4558 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4559 {
4560 return pAdapter;
4561 }
4562
4563 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4564 pAdapterNode = pNext;
4565 }
4566
4567 return NULL;
4568
4569}
4570
Jeff Johnson295189b2012-06-20 16:38:30 -07004571/**---------------------------------------------------------------------------
4572
4573 \brief hdd_set_monitor_tx_adapter() -
4574
4575 This API initializes the adapter to be used while transmitting on monitor
4576 adapter.
4577
4578 \param - pHddCtx - Pointer to the HDD context.
4579 pAdapter - Adapter that will used for TX. This can be NULL.
4580 \return - None.
4581 --------------------------------------------------------------------------*/
4582void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4583{
4584 hdd_adapter_t *pMonAdapter;
4585
4586 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4587
4588 if( NULL != pMonAdapter )
4589 {
4590 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4591 }
4592}
Jeff Johnson295189b2012-06-20 16:38:30 -07004593/**---------------------------------------------------------------------------
4594
4595 \brief hdd_select_queue() -
4596
4597 This API returns the operating channel of the requested device mode
4598
4599 \param - pHddCtx - Pointer to the HDD context.
4600 - mode - Device mode for which operating channel is required
4601 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4602 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4603 \return - channel number. "0" id the requested device is not found OR it is not connected.
4604 --------------------------------------------------------------------------*/
4605v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4606{
4607 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4608 VOS_STATUS status;
4609 hdd_adapter_t *pAdapter;
4610 v_U8_t operatingChannel = 0;
4611
4612 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4613
4614 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4615 {
4616 pAdapter = pAdapterNode->pAdapter;
4617
4618 if( mode == pAdapter->device_mode )
4619 {
4620 switch(pAdapter->device_mode)
4621 {
4622 case WLAN_HDD_INFRA_STATION:
4623 case WLAN_HDD_P2P_CLIENT:
4624 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4625 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4626 break;
4627 case WLAN_HDD_SOFTAP:
4628 case WLAN_HDD_P2P_GO:
4629 /*softap connection info */
4630 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4631 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4632 break;
4633 default:
4634 break;
4635 }
4636
4637 break; //Found the device of interest. break the loop
4638 }
4639
4640 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4641 pAdapterNode = pNext;
4642 }
4643 return operatingChannel;
4644}
4645
4646#ifdef WLAN_FEATURE_PACKET_FILTERING
4647/**---------------------------------------------------------------------------
4648
4649 \brief hdd_set_multicast_list() -
4650
4651 This used to set the multicast address list.
4652
4653 \param - dev - Pointer to the WLAN device.
4654 - skb - Pointer to OS packet (sk_buff).
4655 \return - success/fail
4656
4657 --------------------------------------------------------------------------*/
4658static void hdd_set_multicast_list(struct net_device *dev)
4659{
4660 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004661 int mc_count;
4662 int i = 0;
4663 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304664
4665 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004666 {
4667 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304668 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 return;
4670 }
4671
4672 if (dev->flags & IFF_ALLMULTI)
4673 {
4674 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004675 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304676 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004677 }
4678 else
4679 {
4680 mc_count = netdev_mc_count(dev);
4681 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004682 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004683 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4684 {
4685 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004686 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304687 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004688 return;
4689 }
4690
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304691 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004692
4693 netdev_for_each_mc_addr(ha, dev) {
4694 if (i == mc_count)
4695 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304696 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4697 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4698 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004699 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304700 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004701 i++;
4702 }
4703 }
4704 return;
4705}
4706#endif
4707
4708/**---------------------------------------------------------------------------
4709
4710 \brief hdd_select_queue() -
4711
4712 This function is registered with the Linux OS for network
4713 core to decide which queue to use first.
4714
4715 \param - dev - Pointer to the WLAN device.
4716 - skb - Pointer to OS packet (sk_buff).
4717 \return - ac, Queue Index/access category corresponding to UP in IP header
4718
4719 --------------------------------------------------------------------------*/
4720v_U16_t hdd_select_queue(struct net_device *dev,
4721 struct sk_buff *skb)
4722{
4723 return hdd_wmm_select_queue(dev, skb);
4724}
4725
4726
4727/**---------------------------------------------------------------------------
4728
4729 \brief hdd_wlan_initial_scan() -
4730
4731 This function triggers the initial scan
4732
4733 \param - pAdapter - Pointer to the HDD adapter.
4734
4735 --------------------------------------------------------------------------*/
4736void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4737{
4738 tCsrScanRequest scanReq;
4739 tCsrChannelInfo channelInfo;
4740 eHalStatus halStatus;
4741 unsigned long scanId;
4742 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4743
4744 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4745 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4746 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4747
4748 if(sme_Is11dSupported(pHddCtx->hHal))
4749 {
4750 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4751 if ( HAL_STATUS_SUCCESS( halStatus ) )
4752 {
4753 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4754 if( !scanReq.ChannelInfo.ChannelList )
4755 {
4756 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4757 vos_mem_free(channelInfo.ChannelList);
4758 return;
4759 }
4760 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4761 channelInfo.numOfChannels);
4762 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4763 vos_mem_free(channelInfo.ChannelList);
4764 }
4765
4766 scanReq.scanType = eSIR_PASSIVE_SCAN;
4767 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4768 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4769 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4770 }
4771 else
4772 {
4773 scanReq.scanType = eSIR_ACTIVE_SCAN;
4774 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4775 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4776 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4777 }
4778
4779 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4780 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4781 {
4782 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4783 __func__, halStatus );
4784 }
4785
4786 if(sme_Is11dSupported(pHddCtx->hHal))
4787 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4788}
4789
4790struct fullPowerContext
4791{
4792 struct completion completion;
4793 unsigned int magic;
4794};
4795#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4796
4797/**---------------------------------------------------------------------------
4798
4799 \brief hdd_full_power_callback() - HDD full power callback function
4800
4801 This is the function invoked by SME to inform the result of a full power
4802 request issued by HDD
4803
4804 \param - callbackcontext - Pointer to cookie
4805 \param - status - result of request
4806
4807 \return - None
4808
4809 --------------------------------------------------------------------------*/
4810static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4811{
4812 struct fullPowerContext *pContext = callbackContext;
4813
4814 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304815 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004816
4817 if (NULL == callbackContext)
4818 {
4819 hddLog(VOS_TRACE_LEVEL_ERROR,
4820 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004821 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 return;
4823 }
4824
4825 /* there is a race condition that exists between this callback function
4826 and the caller since the caller could time out either before or
4827 while this code is executing. we'll assume the timeout hasn't
4828 occurred, but we'll verify that right before we save our work */
4829
4830 if (POWER_CONTEXT_MAGIC != pContext->magic)
4831 {
4832 /* the caller presumably timed out so there is nothing we can do */
4833 hddLog(VOS_TRACE_LEVEL_WARN,
4834 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004835 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 return;
4837 }
4838
4839 /* the race is on. caller could have timed out immediately after
4840 we verified the magic, but if so, caller will wait a short time
4841 for us to notify the caller, so the context will stay valid */
4842 complete(&pContext->completion);
4843}
4844
4845/**---------------------------------------------------------------------------
4846
4847 \brief hdd_wlan_exit() - HDD WLAN exit function
4848
4849 This is the driver exit point (invoked during rmmod)
4850
4851 \param - pHddCtx - Pointer to the HDD Context
4852
4853 \return - None
4854
4855 --------------------------------------------------------------------------*/
4856void hdd_wlan_exit(hdd_context_t *pHddCtx)
4857{
4858 eHalStatus halStatus;
4859 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4860 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304861 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004863 struct fullPowerContext powerContext;
4864 long lrc;
4865
4866 ENTER();
4867
Jeff Johnson88ba7742013-02-27 14:36:02 -08004868 if (VOS_FTM_MODE != hdd_get_conparam())
4869 {
4870 // Unloading, restart logic is no more required.
4871 wlan_hdd_restart_deinit(pHddCtx);
4872 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004873
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004875 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 {
4878 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4879 WLAN_HDD_INFRA_STATION);
4880 if (pAdapter == NULL)
4881 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4882
4883 if (pAdapter != NULL)
4884 {
4885 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4886 hdd_UnregisterWext(pAdapter->dev);
4887 }
4888 }
4889 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004890
Jeff Johnson295189b2012-06-20 16:38:30 -07004891 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004892 {
4893 wlan_hdd_ftm_close(pHddCtx);
4894 goto free_hdd_ctx;
4895 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 //Stop the Interface TX queue.
4897 //netif_tx_disable(pWlanDev);
4898 //netif_carrier_off(pWlanDev);
4899
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4901 {
4902 pAdapter = hdd_get_adapter(pHddCtx,
4903 WLAN_HDD_SOFTAP);
4904 }
4905 else
4906 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004908 {
4909 pAdapter = hdd_get_adapter(pHddCtx,
4910 WLAN_HDD_INFRA_STATION);
4911 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 /* DeRegister with platform driver as client for Suspend/Resume */
4914 vosStatus = hddDeregisterPmOps(pHddCtx);
4915 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4916 {
4917 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4918 VOS_ASSERT(0);
4919 }
4920
4921 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4922 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4923 {
4924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4925 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004926
4927 // Cancel any outstanding scan requests. We are about to close all
4928 // of our adapters, but an adapter structure is what SME passes back
4929 // to our callback function. Hence if there are any outstanding scan
4930 // requests then there is a race condition between when the adapter
4931 // is closed and when the callback is invoked. We try to resolve that
4932 // race condition here by canceling any outstanding scans before we
4933 // close the adapters.
4934 // Note that the scans may be cancelled in an asynchronous manner, so
4935 // ideally there needs to be some kind of synchronization. Rather than
4936 // introduce a new synchronization here, we will utilize the fact that
4937 // we are about to Request Full Power, and since that is synchronized,
4938 // the expectation is that by the time Request Full Power has completed,
4939 // all scans will be cancelled.
4940 hdd_abort_mac_scan( pHddCtx );
4941
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304942 //Stop the timer if already running
4943 if (VOS_TIMER_STATE_RUNNING ==
4944 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4945 {
4946 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4947 }
4948
4949 // Destroy hdd_p2p_go_conn_is_in_progress timer
4950 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4951 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4952 {
4953 hddLog(VOS_TRACE_LEVEL_ERROR,
4954 "%s: Cannot deallocate p2p connection timer", __func__);
4955 }
4956
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 //Disable IMPS/BMPS as we do not want the device to enter any power
4958 //save mode during shutdown
4959 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4960 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4961 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4962
4963 //Ensure that device is in full power as we will touch H/W during vos_Stop
4964 init_completion(&powerContext.completion);
4965 powerContext.magic = POWER_CONTEXT_MAGIC;
4966
4967 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4968 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4969
4970 if (eHAL_STATUS_SUCCESS != halStatus)
4971 {
4972 if (eHAL_STATUS_PMC_PENDING == halStatus)
4973 {
4974 /* request was sent -- wait for the response */
4975 lrc = wait_for_completion_interruptible_timeout(
4976 &powerContext.completion,
4977 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4978 /* either we have a response or we timed out
4979 either way, first invalidate our magic */
4980 powerContext.magic = 0;
4981 if (lrc <= 0)
4982 {
4983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004984 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 /* there is a race condition such that the callback
4986 function could be executing at the same time we are. of
4987 primary concern is if the callback function had already
4988 verified the "magic" but hasn't yet set the completion
4989 variable. Since the completion variable is on our
4990 stack, we'll delay just a bit to make sure the data is
4991 still valid if that is the case */
4992 msleep(50);
4993 }
4994 }
4995 else
4996 {
4997 hddLog(VOS_TRACE_LEVEL_ERROR,
4998 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004999 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005000 VOS_ASSERT(0);
5001 /* continue -- need to clean up as much as possible */
5002 }
5003 }
5004
5005 // Unregister the Net Device Notifier
5006 unregister_netdevice_notifier(&hdd_netdev_notifier);
5007
Jeff Johnson295189b2012-06-20 16:38:30 -07005008 hdd_stop_all_adapters( pHddCtx );
5009
Jeff Johnson295189b2012-06-20 16:38:30 -07005010#ifdef WLAN_BTAMP_FEATURE
5011 vosStatus = WLANBAP_Stop(pVosContext);
5012 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5013 {
5014 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5015 "%s: Failed to stop BAP",__func__);
5016 }
5017#endif //WLAN_BTAMP_FEATURE
5018
5019 //Stop all the modules
5020 vosStatus = vos_stop( pVosContext );
5021 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5022 {
5023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5024 "%s: Failed to stop VOSS",__func__);
5025 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5026 }
5027
Jeff Johnson295189b2012-06-20 16:38:30 -07005028 //Assert Deep sleep signal now to put Libra HW in lowest power state
5029 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5030 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5031
5032 //Vote off any PMIC voltage supplies
5033 vos_chipPowerDown(NULL, NULL, NULL);
5034
5035 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5036
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005039
5040 //Close the scheduler before calling vos_close to make sure no thread is
5041 // scheduled after the each module close is called i.e after all the data
5042 // structures are freed.
5043 vosStatus = vos_sched_close( pVosContext );
5044 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5045 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5046 "%s: Failed to close VOSS Scheduler",__func__);
5047 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5048 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005049#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005050#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5051 /* Destroy the wake lock */
5052 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5053#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005054 /* Destroy the wake lock */
5055 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005056#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005057
5058 //Close VOSS
5059 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5060 vos_close(pVosContext);
5061
Jeff Johnson295189b2012-06-20 16:38:30 -07005062 //Close Watchdog
5063 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5064 vos_watchdog_close(pVosContext);
5065
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305066 //Clean up HDD Nlink Service
5067 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5068 nl_srv_exit();
5069
Jeff Johnson295189b2012-06-20 16:38:30 -07005070 /* Cancel the vote for XO Core ON.
5071 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5072 * exited at this point
5073 */
5074 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5075 " when WLAN is turned OFF\n");
5076 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5077 {
5078 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5079 " Not returning failure."
5080 " Power consumed will be high\n");
5081 }
5082
5083 hdd_close_all_adapters( pHddCtx );
5084
5085
5086 //Free up dynamically allocated members inside HDD Adapter
5087 kfree(pHddCtx->cfg_ini);
5088 pHddCtx->cfg_ini= NULL;
5089
5090 /* free the power on lock from platform driver */
5091 if (free_riva_power_on_lock("wlan"))
5092 {
5093 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5094 __func__);
5095 }
5096
Jeff Johnson88ba7742013-02-27 14:36:02 -08005097free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005098 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005099 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005100 if (hdd_is_ssr_required())
5101 {
5102 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005103 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 msleep(5000);
5105 }
5106 hdd_set_ssr_required (VOS_FALSE);
5107}
5108
5109
5110/**---------------------------------------------------------------------------
5111
5112 \brief hdd_update_config_from_nv() - Function to update the contents of
5113 the running configuration with parameters taken from NV storage
5114
5115 \param - pHddCtx - Pointer to the HDD global context
5116
5117 \return - VOS_STATUS_SUCCESS if successful
5118
5119 --------------------------------------------------------------------------*/
5120static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5121{
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 v_BOOL_t itemIsValid = VOS_FALSE;
5123 VOS_STATUS status;
5124 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5125 v_U8_t macLoop;
5126
5127 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5128 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5129 if(status != VOS_STATUS_SUCCESS)
5130 {
5131 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5132 return VOS_STATUS_E_FAILURE;
5133 }
5134
5135 if (itemIsValid == VOS_TRUE)
5136 {
5137 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5138 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5139 VOS_MAX_CONCURRENCY_PERSONA);
5140 if(status != VOS_STATUS_SUCCESS)
5141 {
5142 /* Get MAC from NV fail, not update CFG info
5143 * INI MAC value will be used for MAC setting */
5144 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5145 return VOS_STATUS_E_FAILURE;
5146 }
5147
5148 /* If first MAC is not valid, treat all others are not valid
5149 * Then all MACs will be got from ini file */
5150 if(vos_is_macaddr_zero(&macFromNV[0]))
5151 {
5152 /* MAC address in NV file is not configured yet */
5153 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5154 return VOS_STATUS_E_INVAL;
5155 }
5156
5157 /* Get MAC address from NV, update CFG info */
5158 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5159 {
5160 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5161 {
5162 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5163 /* This MAC is not valid, skip it
5164 * This MAC will be got from ini file */
5165 }
5166 else
5167 {
5168 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5169 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5170 VOS_MAC_ADDR_SIZE);
5171 }
5172 }
5173 }
5174 else
5175 {
5176 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5177 return VOS_STATUS_E_FAILURE;
5178 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005179
Jeff Johnson295189b2012-06-20 16:38:30 -07005180
5181 return VOS_STATUS_SUCCESS;
5182}
5183
5184/**---------------------------------------------------------------------------
5185
5186 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5187
5188 \param - pAdapter - Pointer to the HDD
5189
5190 \return - None
5191
5192 --------------------------------------------------------------------------*/
5193VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5194{
5195 eHalStatus halStatus;
5196 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305197 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005198
Jeff Johnson295189b2012-06-20 16:38:30 -07005199
5200 // Send ready indication to the HDD. This will kick off the MAC
5201 // into a 'running' state and should kick off an initial scan.
5202 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5203 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5204 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305205 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005206 "code %08d [x%08x]",__func__, halStatus, halStatus );
5207 return VOS_STATUS_E_FAILURE;
5208 }
5209
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305210 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5212 // And RIVA will crash
5213 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5214 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305215 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5216 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5217
5218
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 return VOS_STATUS_SUCCESS;
5220}
5221
Jeff Johnson295189b2012-06-20 16:38:30 -07005222/* wake lock APIs for HDD */
5223void hdd_prevent_suspend(void)
5224{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005225#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005226 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005227#else
5228 wcnss_prevent_suspend();
5229#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005230}
5231
5232void hdd_allow_suspend(void)
5233{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005234#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005236#else
5237 wcnss_allow_suspend();
5238#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005239}
5240
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005241void hdd_allow_suspend_timeout(v_U32_t timeout)
5242{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005243#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005244 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005245#else
5246 /* Do nothing as there is no API in wcnss for timeout*/
5247#endif
5248}
5249
Jeff Johnson295189b2012-06-20 16:38:30 -07005250/**---------------------------------------------------------------------------
5251
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005252 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5253 information between Host and Riva
5254
5255 This function gets reported version of FW
5256 It also finds the version of Riva headers used to compile the host
5257 It compares the above two and prints a warning if they are different
5258 It gets the SW and HW version string
5259 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5260 indicating the features they support through a bitmap
5261
5262 \param - pHddCtx - Pointer to HDD context
5263
5264 \return - void
5265
5266 --------------------------------------------------------------------------*/
5267
5268void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5269{
5270
5271 tSirVersionType versionCompiled;
5272 tSirVersionType versionReported;
5273 tSirVersionString versionString;
5274 tANI_U8 fwFeatCapsMsgSupported = 0;
5275 VOS_STATUS vstatus;
5276
5277 /* retrieve and display WCNSS version information */
5278 do {
5279
5280 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5281 &versionCompiled);
5282 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5283 {
5284 hddLog(VOS_TRACE_LEVEL_FATAL,
5285 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005286 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005287 break;
5288 }
5289
5290 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5291 &versionReported);
5292 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5293 {
5294 hddLog(VOS_TRACE_LEVEL_FATAL,
5295 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005296 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005297 break;
5298 }
5299
5300 if ((versionCompiled.major != versionReported.major) ||
5301 (versionCompiled.minor != versionReported.minor) ||
5302 (versionCompiled.version != versionReported.version) ||
5303 (versionCompiled.revision != versionReported.revision))
5304 {
5305 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5306 "Host expected %u.%u.%u.%u\n",
5307 WLAN_MODULE_NAME,
5308 (int)versionReported.major,
5309 (int)versionReported.minor,
5310 (int)versionReported.version,
5311 (int)versionReported.revision,
5312 (int)versionCompiled.major,
5313 (int)versionCompiled.minor,
5314 (int)versionCompiled.version,
5315 (int)versionCompiled.revision);
5316 }
5317 else
5318 {
5319 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5320 WLAN_MODULE_NAME,
5321 (int)versionReported.major,
5322 (int)versionReported.minor,
5323 (int)versionReported.version,
5324 (int)versionReported.revision);
5325 }
5326
5327 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5328 versionString,
5329 sizeof(versionString));
5330 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5331 {
5332 hddLog(VOS_TRACE_LEVEL_FATAL,
5333 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005334 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005335 break;
5336 }
5337
5338 pr_info("%s: WCNSS software version %s\n",
5339 WLAN_MODULE_NAME, versionString);
5340
5341 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5342 versionString,
5343 sizeof(versionString));
5344 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5345 {
5346 hddLog(VOS_TRACE_LEVEL_FATAL,
5347 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005348 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005349 break;
5350 }
5351
5352 pr_info("%s: WCNSS hardware version %s\n",
5353 WLAN_MODULE_NAME, versionString);
5354
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005355 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5356 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005357 send the message only if it the riva is 1.1
5358 minor numbers for different riva branches:
5359 0 -> (1.0)Mainline Build
5360 1 -> (1.1)Mainline Build
5361 2->(1.04) Stability Build
5362 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005363 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005364 ((versionReported.minor>=1) && (versionReported.version>=1)))
5365 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5366 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005367
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005368 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005369 {
5370#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5371 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5372 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5373#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005374 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005375 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005376
5377 } while (0);
5378
5379}
5380
5381/**---------------------------------------------------------------------------
5382
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305383 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5384
5385 \param - pHddCtx - Pointer to the hdd context
5386
5387 \return - true if hardware supports 5GHz
5388
5389 --------------------------------------------------------------------------*/
5390static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5391{
5392 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5393 * then hardware support 5Ghz.
5394 */
5395 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5396 {
5397 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5398 return true;
5399 }
5400 else
5401 {
5402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5403 __func__);
5404 return false;
5405 }
5406}
5407
5408
5409/**---------------------------------------------------------------------------
5410
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 \brief hdd_wlan_startup() - HDD init function
5412
5413 This is the driver startup code executed once a WLAN device has been detected
5414
5415 \param - dev - Pointer to the underlying device
5416
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005417 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005418
5419 --------------------------------------------------------------------------*/
5420
5421int hdd_wlan_startup(struct device *dev )
5422{
5423 VOS_STATUS status;
5424 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005425 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 hdd_context_t *pHddCtx = NULL;
5427 v_CONTEXT_t pVosContext= NULL;
5428#ifdef WLAN_BTAMP_FEATURE
5429 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5430 WLANBAP_ConfigType btAmpConfig;
5431 hdd_config_t *pConfig;
5432#endif
5433 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005434 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005435
5436 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 /*
5438 * cfg80211: wiphy allocation
5439 */
5440 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5441
5442 if(wiphy == NULL)
5443 {
5444 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005445 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 }
5447
5448 pHddCtx = wiphy_priv(wiphy);
5449
Jeff Johnson295189b2012-06-20 16:38:30 -07005450 //Initialize the adapter context to zeros.
5451 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5452
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 hdd_prevent_suspend();
5455 pHddCtx->isLoadUnloadInProgress = TRUE;
5456
5457 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5458
5459 /*Get vos context here bcoz vos_open requires it*/
5460 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5461
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005462 if(pVosContext == NULL)
5463 {
5464 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5465 goto err_free_hdd_context;
5466 }
5467
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 //Save the Global VOSS context in adapter context for future.
5469 pHddCtx->pvosContext = pVosContext;
5470
5471 //Save the adapter context in global context for future.
5472 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5473
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 pHddCtx->parent_dev = dev;
5475
5476 init_completion(&pHddCtx->full_pwr_comp_var);
5477 init_completion(&pHddCtx->standby_comp_var);
5478 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005479 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005480 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005481
5482 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5483
5484 // Load all config first as TL config is needed during vos_open
5485 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5486 if(pHddCtx->cfg_ini == NULL)
5487 {
5488 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5489 goto err_free_hdd_context;
5490 }
5491
5492 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5493
5494 // Read and parse the qcom_cfg.ini file
5495 status = hdd_parse_config_ini( pHddCtx );
5496 if ( VOS_STATUS_SUCCESS != status )
5497 {
5498 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5499 __func__, WLAN_INI_FILE);
5500 goto err_config;
5501 }
5502
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305503 /* INI has been read, initialise the configuredMcastBcastFilter with
5504 * INI value as this will serve as the default value
5505 */
5506 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5507 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5508 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305509
5510 if (false == hdd_is_5g_supported(pHddCtx))
5511 {
5512 //5Ghz is not supported.
5513 if (1 != pHddCtx->cfg_ini->nBandCapability)
5514 {
5515 hddLog(VOS_TRACE_LEVEL_INFO,
5516 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5517 pHddCtx->cfg_ini->nBandCapability = 1;
5518 }
5519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 /*
5521 * cfg80211: Initialization and registration ...
5522 */
5523 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5524 {
5525 hddLog(VOS_TRACE_LEVEL_FATAL,
5526 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5527 goto err_wiphy_reg;
5528 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005529
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005530 // Update VOS trace levels based upon the cfg.ini
5531 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5532 pHddCtx->cfg_ini->vosTraceEnableBAP);
5533 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5534 pHddCtx->cfg_ini->vosTraceEnableTL);
5535 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5536 pHddCtx->cfg_ini->vosTraceEnableWDI);
5537 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5538 pHddCtx->cfg_ini->vosTraceEnableHDD);
5539 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5540 pHddCtx->cfg_ini->vosTraceEnableSME);
5541 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5542 pHddCtx->cfg_ini->vosTraceEnablePE);
5543 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5544 pHddCtx->cfg_ini->vosTraceEnableWDA);
5545 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5546 pHddCtx->cfg_ini->vosTraceEnableSYS);
5547 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5548 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005549 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5550 pHddCtx->cfg_ini->vosTraceEnableSAP);
5551 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5552 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005553
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 // Update WDI trace levels based upon the cfg.ini
5555 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5556 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5557 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5558 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5559 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5560 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5561 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5562 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005563
Jeff Johnson88ba7742013-02-27 14:36:02 -08005564 if (VOS_FTM_MODE == hdd_get_conparam())
5565 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5567 {
5568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5569 goto err_free_hdd_context;
5570 }
5571 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5572 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005573 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005574
Jeff Johnson88ba7742013-02-27 14:36:02 -08005575 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5577 {
5578 status = vos_watchdog_open(pVosContext,
5579 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5580
5581 if(!VOS_IS_STATUS_SUCCESS( status ))
5582 {
5583 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 }
5586 }
5587
5588 pHddCtx->isLogpInProgress = FALSE;
5589 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5592 if(!VOS_IS_STATUS_SUCCESS(status))
5593 {
5594 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005595 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 }
5597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 status = vos_open( &pVosContext, 0);
5599 if ( !VOS_IS_STATUS_SUCCESS( status ))
5600 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005601 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5602 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 }
5604
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5606
5607 if ( NULL == pHddCtx->hHal )
5608 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005609 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005610 goto err_vosclose;
5611 }
5612
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005613 status = vos_preStart( pHddCtx->pvosContext );
5614 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5615 {
5616 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5617 goto err_vosclose;
5618 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005619
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005620 /* Note that the vos_preStart() sequence triggers the cfg download.
5621 The cfg download must occur before we update the SME config
5622 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 status = hdd_set_sme_config( pHddCtx );
5624
5625 if ( VOS_STATUS_SUCCESS != status )
5626 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005627 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5628 goto err_vosclose;
5629 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005630
5631 //Initialize the WMM module
5632 status = hdd_wmm_init(pHddCtx);
5633 if (!VOS_IS_STATUS_SUCCESS(status))
5634 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005635 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005636 goto err_vosclose;
5637 }
5638
Jeff Johnson295189b2012-06-20 16:38:30 -07005639 /* In the integrated architecture we update the configuration from
5640 the INI file and from NV before vOSS has been started so that
5641 the final contents are available to send down to the cCPU */
5642
5643 // Apply the cfg.ini to cfg.dat
5644 if (FALSE == hdd_update_config_dat(pHddCtx))
5645 {
5646 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5647 goto err_vosclose;
5648 }
5649
5650 // Apply the NV to cfg.dat
5651 /* Prima Update MAC address only at here */
5652 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5653 {
5654#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5655 /* There was not a valid set of MAC Addresses in NV. See if the
5656 default addresses were modified by the cfg.ini settings. If so,
5657 we'll use them, but if not, we'll autogenerate a set of MAC
5658 addresses based upon the device serial number */
5659
5660 static const v_MACADDR_t default_address =
5661 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5662 unsigned int serialno;
5663 int i;
5664
5665 serialno = wcnss_get_serial_number();
5666 if ((0 != serialno) &&
5667 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5668 sizeof(default_address))))
5669 {
5670 /* cfg.ini has the default address, invoke autogen logic */
5671
5672 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5673 bytes of the serial number that can be used to generate
5674 the other 3 bytes of the MAC address. Mask off all but
5675 the lower 3 bytes (this will also make sure we don't
5676 overflow in the next step) */
5677 serialno &= 0x00FFFFFF;
5678
5679 /* we need a unique address for each session */
5680 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5681
5682 /* autogen all addresses */
5683 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5684 {
5685 /* start with the entire default address */
5686 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5687 /* then replace the lower 3 bytes */
5688 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5689 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5690 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5691
5692 serialno++;
5693 }
5694
5695 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5696 MAC_ADDRESS_STR,
5697 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5698 }
5699 else
5700#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5701 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005702 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 "%s: Invalid MAC address in NV, using MAC from ini file "
5704 MAC_ADDRESS_STR, __func__,
5705 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5706 }
5707 }
5708 {
5709 eHalStatus halStatus;
5710 // Set the MAC Address
5711 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5712 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5713 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5714 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5715
5716 if (!HAL_STATUS_SUCCESS( halStatus ))
5717 {
5718 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5719 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005720 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005721 }
5722 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005723
5724 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5725 Note: Firmware image will be read and downloaded inside vos_start API */
5726 status = vos_start( pHddCtx->pvosContext );
5727 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5728 {
5729 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5730 goto err_vosclose;
5731 }
5732
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005733 /* Exchange capability info between Host and FW and also get versioning info from FW */
5734 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005735
5736 status = hdd_post_voss_start_config( pHddCtx );
5737 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5738 {
5739 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5740 __func__);
5741 goto err_vosstop;
5742 }
5743
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5745 {
5746 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5747 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5748 }
5749 else
5750 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005751 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5752 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5753 if (pAdapter != NULL)
5754 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305755 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005756 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305757 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5758 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5759 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005760
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305761 /* Generate the P2P Device Address. This consists of the device's
5762 * primary MAC address with the locally administered bit set.
5763 */
5764 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005765 }
5766 else
5767 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305768 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5769 if (p2p_dev_addr != NULL)
5770 {
5771 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5772 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5773 }
5774 else
5775 {
5776 hddLog(VOS_TRACE_LEVEL_FATAL,
5777 "%s: Failed to allocate mac_address for p2p_device",
5778 __func__);
5779 goto err_close_adapter;
5780 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005782
5783 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5784 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5785 if ( NULL == pP2pAdapter )
5786 {
5787 hddLog(VOS_TRACE_LEVEL_FATAL,
5788 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005789 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005790 goto err_close_adapter;
5791 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005792 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005794
5795 if( pAdapter == NULL )
5796 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005797 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5798 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005800
Jeff Johnson295189b2012-06-20 16:38:30 -07005801#ifdef WLAN_BTAMP_FEATURE
5802 vStatus = WLANBAP_Open(pVosContext);
5803 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5804 {
5805 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5806 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005807 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 }
5809
5810 vStatus = BSL_Init(pVosContext);
5811 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5812 {
5813 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5814 "%s: Failed to Init BSL",__func__);
5815 goto err_bap_close;
5816 }
5817 vStatus = WLANBAP_Start(pVosContext);
5818 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5819 {
5820 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5821 "%s: Failed to start TL",__func__);
5822 goto err_bap_close;
5823 }
5824
5825 pConfig = pHddCtx->cfg_ini;
5826 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5827 status = WLANBAP_SetConfig(&btAmpConfig);
5828
5829#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005830
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005831#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5832 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5833 {
5834 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5835 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5836 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5837 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5838 }
5839#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005840#ifdef FEATURE_WLAN_SCAN_PNO
5841 /*SME must send channel update configuration to RIVA*/
5842 sme_UpdateChannelConfig(pHddCtx->hHal);
5843#endif
5844
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 /* Register with platform driver as client for Suspend/Resume */
5846 status = hddRegisterPmOps(pHddCtx);
5847 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5848 {
5849 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5850#ifdef WLAN_BTAMP_FEATURE
5851 goto err_bap_stop;
5852#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005853 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005854#endif //WLAN_BTAMP_FEATURE
5855 }
5856
5857 /* Register TM level change handler function to the platform */
5858 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5859 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5860 {
5861 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5862 goto err_unregister_pmops;
5863 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005864
5865 /* register for riva power on lock to platform driver */
5866 if (req_riva_power_on_lock("wlan"))
5867 {
5868 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5869 __func__);
5870 goto err_unregister_pmops;
5871 }
5872
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 // register net device notifier for device change notification
5874 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5875
5876 if(ret < 0)
5877 {
5878 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5879 goto err_free_power_on_lock;
5880 }
5881
5882 //Initialize the nlink service
5883 if(nl_srv_init() != 0)
5884 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305885 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 goto err_reg_netdev;
5887 }
5888
5889 //Initialize the BTC service
5890 if(btc_activate_service(pHddCtx) != 0)
5891 {
5892 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5893 goto err_nl_srv;
5894 }
5895
5896#ifdef PTT_SOCK_SVC_ENABLE
5897 //Initialize the PTT service
5898 if(ptt_sock_activate_svc(pHddCtx) != 0)
5899 {
5900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5901 goto err_nl_srv;
5902 }
5903#endif
5904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005907 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005908 /* Action frame registered in one adapter which will
5909 * applicable to all interfaces
5910 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005911 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005913
5914 mutex_init(&pHddCtx->sap_lock);
5915
5916 pHddCtx->isLoadUnloadInProgress = FALSE;
5917
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005918#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005919#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5920 /* Initialize the wake lcok */
5921 wake_lock_init(&pHddCtx->rx_wake_lock,
5922 WAKE_LOCK_SUSPEND,
5923 "qcom_rx_wakelock");
5924#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005925 /* Initialize the wake lcok */
5926 wake_lock_init(&pHddCtx->sap_wake_lock,
5927 WAKE_LOCK_SUSPEND,
5928 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005929#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005930
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005931 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5932 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005933
5934 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5935 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305936
Jeff Johnsone7245742012-09-05 17:12:55 -07005937 // Initialize the restart logic
5938 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305939
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305940 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5941 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5942 {
5943 hddLog(VOS_TRACE_LEVEL_ERROR,
5944 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5945 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005946 goto success;
5947
5948err_nl_srv:
5949 nl_srv_exit();
5950
5951err_reg_netdev:
5952 unregister_netdevice_notifier(&hdd_netdev_notifier);
5953
5954err_free_power_on_lock:
5955 free_riva_power_on_lock("wlan");
5956
5957err_unregister_pmops:
5958 hddDevTmUnregisterNotifyCallback(pHddCtx);
5959 hddDeregisterPmOps(pHddCtx);
5960
5961#ifdef WLAN_BTAMP_FEATURE
5962err_bap_stop:
5963 WLANBAP_Stop(pVosContext);
5964#endif
5965
5966#ifdef WLAN_BTAMP_FEATURE
5967err_bap_close:
5968 WLANBAP_Close(pVosContext);
5969#endif
5970
Jeff Johnson295189b2012-06-20 16:38:30 -07005971err_close_adapter:
5972 hdd_close_all_adapters( pHddCtx );
5973
5974err_vosstop:
5975 vos_stop(pVosContext);
5976
5977err_vosclose:
5978 status = vos_sched_close( pVosContext );
5979 if (!VOS_IS_STATUS_SUCCESS(status)) {
5980 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5981 "%s: Failed to close VOSS Scheduler", __func__);
5982 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5983 }
5984 vos_close(pVosContext );
5985
Jeff Johnson295189b2012-06-20 16:38:30 -07005986err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005987 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005988
5989err_wdclose:
5990 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5991 vos_watchdog_close(pVosContext);
5992
Jeff Johnson295189b2012-06-20 16:38:30 -07005993err_wiphy_reg:
5994 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005995
5996err_config:
5997 kfree(pHddCtx->cfg_ini);
5998 pHddCtx->cfg_ini= NULL;
5999
6000err_free_hdd_context:
6001 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 wiphy_free(wiphy) ;
6003 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 VOS_BUG(1);
6005
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006006 if (hdd_is_ssr_required())
6007 {
6008 /* WDI timeout had happened during load, so SSR is needed here */
6009 subsystem_restart("wcnss");
6010 msleep(5000);
6011 }
6012 hdd_set_ssr_required (VOS_FALSE);
6013
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006014 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006015
6016success:
6017 EXIT();
6018 return 0;
6019}
6020
6021/**---------------------------------------------------------------------------
6022
Jeff Johnson32d95a32012-09-10 13:15:23 -07006023 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006024
Jeff Johnson32d95a32012-09-10 13:15:23 -07006025 This is the driver entry point - called in different timeline depending
6026 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006027
6028 \param - None
6029
6030 \return - 0 for success, non zero for failure
6031
6032 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006033static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006034{
6035 VOS_STATUS status;
6036 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006037 struct device *dev = NULL;
6038 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006039#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6040 int max_retries = 0;
6041#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006042
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306043#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6044 vos_wconn_trace_init();
6045#endif
6046
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 ENTER();
6048
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006049#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006050 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006051#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006052
6053 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6054 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6055
6056 //Power Up Libra WLAN card first if not already powered up
6057 status = vos_chipPowerUp(NULL,NULL,NULL);
6058 if (!VOS_IS_STATUS_SUCCESS(status))
6059 {
6060 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6061 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306062#ifdef WLAN_OPEN_SOURCE
6063 wake_lock_destroy(&wlan_wake_lock);
6064#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006065 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 }
6067
Jeff Johnson295189b2012-06-20 16:38:30 -07006068#ifdef ANI_BUS_TYPE_PCI
6069
6070 dev = wcnss_wlan_get_device();
6071
6072#endif // ANI_BUS_TYPE_PCI
6073
6074#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006075
6076#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6077 /* wait until WCNSS driver downloads NV */
6078 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6079 msleep(1000);
6080 }
6081 if (max_retries >= 5) {
6082 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306083#ifdef WLAN_OPEN_SOURCE
6084 wake_lock_destroy(&wlan_wake_lock);
6085#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006086 return -ENODEV;
6087 }
6088#endif
6089
Jeff Johnson295189b2012-06-20 16:38:30 -07006090 dev = wcnss_wlan_get_device();
6091#endif // ANI_BUS_TYPE_PLATFORM
6092
6093
6094 do {
6095 if (NULL == dev) {
6096 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6097 ret_status = -1;
6098 break;
6099 }
6100
6101#ifdef MEMORY_DEBUG
6102 vos_mem_init();
6103#endif
6104
6105#ifdef TIMER_MANAGER
6106 vos_timer_manager_init();
6107#endif
6108
6109 /* Preopen VOSS so that it is ready to start at least SAL */
6110 status = vos_preOpen(&pVosContext);
6111
6112 if (!VOS_IS_STATUS_SUCCESS(status))
6113 {
6114 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6115 ret_status = -1;
6116 break;
6117 }
6118
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006119#ifndef MODULE
6120 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6121 */
6122 hdd_set_conparam((v_UINT_t)con_mode);
6123#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006124
6125 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006126 if (hdd_wlan_startup(dev))
6127 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006128 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006129 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 vos_preClose( &pVosContext );
6131 ret_status = -1;
6132 break;
6133 }
6134
6135 /* Cancel the vote for XO Core ON
6136 * This is done here for safety purposes in case we re-initialize without turning
6137 * it OFF in any error scenario.
6138 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006139 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006141 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6143 {
6144 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6145 " Power consumed will be high\n");
6146 }
6147 } while (0);
6148
6149 if (0 != ret_status)
6150 {
6151 //Assert Deep sleep signal now to put Libra HW in lowest power state
6152 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6153 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6154
6155 //Vote off any PMIC voltage supplies
6156 vos_chipPowerDown(NULL, NULL, NULL);
6157#ifdef TIMER_MANAGER
6158 vos_timer_exit();
6159#endif
6160#ifdef MEMORY_DEBUG
6161 vos_mem_exit();
6162#endif
6163
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006164#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006166#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6168 }
6169 else
6170 {
6171 //Send WLAN UP indication to Nlink Service
6172 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6173
6174 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 }
6176
6177 EXIT();
6178
6179 return ret_status;
6180}
6181
Jeff Johnson32d95a32012-09-10 13:15:23 -07006182/**---------------------------------------------------------------------------
6183
6184 \brief hdd_module_init() - Init Function
6185
6186 This is the driver entry point (invoked when module is loaded using insmod)
6187
6188 \param - None
6189
6190 \return - 0 for success, non zero for failure
6191
6192 --------------------------------------------------------------------------*/
6193#ifdef MODULE
6194static int __init hdd_module_init ( void)
6195{
6196 return hdd_driver_init();
6197}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006198#else /* #ifdef MODULE */
6199static int __init hdd_module_init ( void)
6200{
6201 /* Driver initialization is delayed to fwpath_changed_handler */
6202 return 0;
6203}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006204#endif /* #ifdef MODULE */
6205
Jeff Johnson295189b2012-06-20 16:38:30 -07006206
6207/**---------------------------------------------------------------------------
6208
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006209 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006210
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006211 This is the driver exit point (invoked when module is unloaded using rmmod
6212 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006213
6214 \param - None
6215
6216 \return - None
6217
6218 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006219static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006220{
6221 hdd_context_t *pHddCtx = NULL;
6222 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006223 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006224
6225 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6226
6227 //Get the global vos context
6228 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6229
6230 if(!pVosContext)
6231 {
6232 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6233 goto done;
6234 }
6235
6236 //Get the HDD context.
6237 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6238
6239 if(!pHddCtx)
6240 {
6241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6242 }
6243 else
6244 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006245 while(isWDresetInProgress()) {
6246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6247 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006248 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006249
6250 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6252 "%s:SSR never completed, fatal error", __func__);
6253 VOS_BUG(0);
6254 }
6255 }
6256
Jeff Johnson295189b2012-06-20 16:38:30 -07006257
6258 pHddCtx->isLoadUnloadInProgress = TRUE;
6259 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6260
6261 //Do all the cleanup before deregistering the driver
6262 hdd_wlan_exit(pHddCtx);
6263 }
6264
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 vos_preClose( &pVosContext );
6266
6267#ifdef TIMER_MANAGER
6268 vos_timer_exit();
6269#endif
6270#ifdef MEMORY_DEBUG
6271 vos_mem_exit();
6272#endif
6273
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306274#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6275 vos_wconn_trace_exit();
6276#endif
6277
Jeff Johnson295189b2012-06-20 16:38:30 -07006278done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006279#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006280 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006281#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006282 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6283}
6284
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006285/**---------------------------------------------------------------------------
6286
6287 \brief hdd_module_exit() - Exit function
6288
6289 This is the driver exit point (invoked when module is unloaded using rmmod)
6290
6291 \param - None
6292
6293 \return - None
6294
6295 --------------------------------------------------------------------------*/
6296static void __exit hdd_module_exit(void)
6297{
6298 hdd_driver_exit();
6299}
6300
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006301#ifdef MODULE
6302static int fwpath_changed_handler(const char *kmessage,
6303 struct kernel_param *kp)
6304{
Jeff Johnson76052702013-04-16 13:55:05 -07006305 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006306}
6307
6308static int con_mode_handler(const char *kmessage,
6309 struct kernel_param *kp)
6310{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006311 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006312}
6313#else /* #ifdef MODULE */
6314/**---------------------------------------------------------------------------
6315
Jeff Johnson76052702013-04-16 13:55:05 -07006316 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006317
Jeff Johnson76052702013-04-16 13:55:05 -07006318 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006319 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006320 - invoked when module parameter fwpath is modified from userspace to signal
6321 initializing the WLAN driver or when con_mode is modified from userspace
6322 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006323
6324 \return - 0 for success, non zero for failure
6325
6326 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006327static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006328{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006329 int ret_status;
6330
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006331 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006332 ret_status = hdd_driver_init();
6333 wlan_hdd_inited = ret_status ? 0 : 1;
6334 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006335 }
6336
6337 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006338
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006339 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006340
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006341 ret_status = hdd_driver_init();
6342 wlan_hdd_inited = ret_status ? 0 : 1;
6343 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006344}
6345
Jeff Johnson295189b2012-06-20 16:38:30 -07006346/**---------------------------------------------------------------------------
6347
Jeff Johnson76052702013-04-16 13:55:05 -07006348 \brief fwpath_changed_handler() - Handler Function
6349
6350 Handle changes to the fwpath parameter
6351
6352 \return - 0 for success, non zero for failure
6353
6354 --------------------------------------------------------------------------*/
6355static int fwpath_changed_handler(const char *kmessage,
6356 struct kernel_param *kp)
6357{
6358 int ret;
6359
6360 ret = param_set_copystring(kmessage, kp);
6361 if (0 == ret)
6362 ret = kickstart_driver();
6363 return ret;
6364}
6365
6366/**---------------------------------------------------------------------------
6367
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006368 \brief con_mode_handler() -
6369
6370 Handler function for module param con_mode when it is changed by userspace
6371 Dynamically linked - do nothing
6372 Statically linked - exit and init driver, as in rmmod and insmod
6373
Jeff Johnson76052702013-04-16 13:55:05 -07006374 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006375
Jeff Johnson76052702013-04-16 13:55:05 -07006376 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006377
6378 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006379static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006380{
Jeff Johnson76052702013-04-16 13:55:05 -07006381 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006382
Jeff Johnson76052702013-04-16 13:55:05 -07006383 ret = param_set_int(kmessage, kp);
6384 if (0 == ret)
6385 ret = kickstart_driver();
6386 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006387}
6388#endif /* #ifdef MODULE */
6389
6390/**---------------------------------------------------------------------------
6391
Jeff Johnson295189b2012-06-20 16:38:30 -07006392 \brief hdd_get_conparam() -
6393
6394 This is the driver exit point (invoked when module is unloaded using rmmod)
6395
6396 \param - None
6397
6398 \return - tVOS_CON_MODE
6399
6400 --------------------------------------------------------------------------*/
6401tVOS_CON_MODE hdd_get_conparam ( void )
6402{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006403#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006404 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006405#else
6406 return (tVOS_CON_MODE)curr_con_mode;
6407#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006408}
6409void hdd_set_conparam ( v_UINT_t newParam )
6410{
6411 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006412#ifndef MODULE
6413 curr_con_mode = con_mode;
6414#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006415}
6416/**---------------------------------------------------------------------------
6417
6418 \brief hdd_softap_sta_deauth() - function
6419
6420 This to take counter measure to handle deauth req from HDD
6421
6422 \param - pAdapter - Pointer to the HDD
6423
6424 \param - enable - boolean value
6425
6426 \return - None
6427
6428 --------------------------------------------------------------------------*/
6429
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006430VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006431{
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006433 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006434
6435 ENTER();
6436
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306437 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006438
6439 //Ignore request to deauth bcmc station
6440 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006441 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006442
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006443 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006444
6445 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006446 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006447}
6448
6449/**---------------------------------------------------------------------------
6450
6451 \brief hdd_softap_sta_disassoc() - function
6452
6453 This to take counter measure to handle deauth req from HDD
6454
6455 \param - pAdapter - Pointer to the HDD
6456
6457 \param - enable - boolean value
6458
6459 \return - None
6460
6461 --------------------------------------------------------------------------*/
6462
6463void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6464{
6465 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6466
6467 ENTER();
6468
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306469 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006470
6471 //Ignore request to disassoc bcmc station
6472 if( pDestMacAddress[0] & 0x1 )
6473 return;
6474
6475 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6476}
6477
6478void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6479{
6480 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6481
6482 ENTER();
6483
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306484 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006485
6486 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6487}
6488
Jeff Johnson295189b2012-06-20 16:38:30 -07006489/**---------------------------------------------------------------------------
6490 *
6491 * \brief hdd_get__concurrency_mode() -
6492 *
6493 *
6494 * \param - None
6495 *
6496 * \return - CONCURRENCY MODE
6497 *
6498 * --------------------------------------------------------------------------*/
6499tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6500{
6501 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6502 hdd_context_t *pHddCtx;
6503
6504 if (NULL != pVosContext)
6505 {
6506 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6507 if (NULL != pHddCtx)
6508 {
6509 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6510 }
6511 }
6512
6513 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006514 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006515 return VOS_STA;
6516}
6517
6518/* Decide whether to allow/not the apps power collapse.
6519 * Allow apps power collapse if we are in connected state.
6520 * if not, allow only if we are in IMPS */
6521v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6522{
6523 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006524 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006525 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6527 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6528 hdd_adapter_t *pAdapter = NULL;
6529 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006530 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006531
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6533 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006534
Yathish9f22e662012-12-10 14:21:35 -08006535 concurrent_state = hdd_get_concurrency_mode();
6536
6537#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6538 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6539 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6540 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6541 return TRUE;
6542#endif
6543
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 /*loop through all adapters. TBD fix for Concurrency */
6545 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6546 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6547 {
6548 pAdapter = pAdapterNode->pAdapter;
6549 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6550 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6551 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006552 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006553 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006554 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006555 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6556 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006558 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006559 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6560 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006561 return FALSE;
6562 }
6563 }
6564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6565 pAdapterNode = pNext;
6566 }
6567 return TRUE;
6568}
6569
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006570/* Decides whether to send suspend notification to Riva
6571 * if any adapter is in BMPS; then it is required */
6572v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6573{
6574 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6575 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6576
6577 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6578 {
6579 return TRUE;
6580 }
6581 return FALSE;
6582}
6583
Jeff Johnson295189b2012-06-20 16:38:30 -07006584void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6585{
6586 switch(mode)
6587 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006588 case VOS_STA_MODE:
6589 case VOS_P2P_CLIENT_MODE:
6590 case VOS_P2P_GO_MODE:
6591 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006592 pHddCtx->concurrency_mode |= (1 << mode);
6593 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006594 break;
6595 default:
6596 break;
6597
6598 }
6599 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6600 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6601}
6602
6603
6604void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6605{
6606 switch(mode)
6607 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006608 case VOS_STA_MODE:
6609 case VOS_P2P_CLIENT_MODE:
6610 case VOS_P2P_GO_MODE:
6611 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006612 pHddCtx->no_of_sessions[mode]--;
6613 if (!(pHddCtx->no_of_sessions[mode]))
6614 pHddCtx->concurrency_mode &= (~(1 << mode));
6615 break;
6616 default:
6617 break;
6618 }
6619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6620 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6621}
6622
Jeff Johnsone7245742012-09-05 17:12:55 -07006623/**---------------------------------------------------------------------------
6624 *
6625 * \brief wlan_hdd_restart_init
6626 *
6627 * This function initalizes restart timer/flag. An internal function.
6628 *
6629 * \param - pHddCtx
6630 *
6631 * \return - None
6632 *
6633 * --------------------------------------------------------------------------*/
6634
6635static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6636{
6637 /* Initialize */
6638 pHddCtx->hdd_restart_retries = 0;
6639 atomic_set(&pHddCtx->isRestartInProgress, 0);
6640 vos_timer_init(&pHddCtx->hdd_restart_timer,
6641 VOS_TIMER_TYPE_SW,
6642 wlan_hdd_restart_timer_cb,
6643 pHddCtx);
6644}
6645/**---------------------------------------------------------------------------
6646 *
6647 * \brief wlan_hdd_restart_deinit
6648 *
6649 * This function cleans up the resources used. An internal function.
6650 *
6651 * \param - pHddCtx
6652 *
6653 * \return - None
6654 *
6655 * --------------------------------------------------------------------------*/
6656
6657static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6658{
6659
6660 VOS_STATUS vos_status;
6661 /* Block any further calls */
6662 atomic_set(&pHddCtx->isRestartInProgress, 1);
6663 /* Cleanup */
6664 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6665 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006666 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006667 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6668 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006669 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006670
6671}
6672
6673/**---------------------------------------------------------------------------
6674 *
6675 * \brief wlan_hdd_framework_restart
6676 *
6677 * This function uses a cfg80211 API to start a framework initiated WLAN
6678 * driver module unload/load.
6679 *
6680 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6681 *
6682 *
6683 * \param - pHddCtx
6684 *
6685 * \return - VOS_STATUS_SUCCESS: Success
6686 * VOS_STATUS_E_EMPTY: Adapter is Empty
6687 * VOS_STATUS_E_NOMEM: No memory
6688
6689 * --------------------------------------------------------------------------*/
6690
6691static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6692{
6693 VOS_STATUS status = VOS_STATUS_SUCCESS;
6694 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006695 int len = (sizeof (struct ieee80211_mgmt));
6696 struct ieee80211_mgmt *mgmt = NULL;
6697
6698 /* Prepare the DEAUTH managment frame with reason code */
6699 mgmt = kzalloc(len, GFP_KERNEL);
6700 if(mgmt == NULL)
6701 {
6702 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6703 "%s: memory allocation failed (%d bytes)", __func__, len);
6704 return VOS_STATUS_E_NOMEM;
6705 }
6706 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006707
6708 /* Iterate over all adapters/devices */
6709 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6710 do
6711 {
6712 if( (status == VOS_STATUS_SUCCESS) &&
6713 pAdapterNode &&
6714 pAdapterNode->pAdapter)
6715 {
6716 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6717 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6718 pAdapterNode->pAdapter->dev->name,
6719 pAdapterNode->pAdapter->device_mode,
6720 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006721 /*
6722 * CFG80211 event to restart the driver
6723 *
6724 * 'cfg80211_send_unprot_deauth' sends a
6725 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6726 * of SME(Linux Kernel) state machine.
6727 *
6728 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6729 * the driver.
6730 *
6731 */
6732
6733 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006734 }
6735 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6736 pAdapterNode = pNext;
6737 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6738
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006739
6740 /* Free the allocated management frame */
6741 kfree(mgmt);
6742
Jeff Johnsone7245742012-09-05 17:12:55 -07006743 /* Retry until we unload or reach max count */
6744 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6745 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6746
6747 return status;
6748
6749}
6750/**---------------------------------------------------------------------------
6751 *
6752 * \brief wlan_hdd_restart_timer_cb
6753 *
6754 * Restart timer callback. An internal function.
6755 *
6756 * \param - User data:
6757 *
6758 * \return - None
6759 *
6760 * --------------------------------------------------------------------------*/
6761
6762void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6763{
6764 hdd_context_t *pHddCtx = usrDataForCallback;
6765 wlan_hdd_framework_restart(pHddCtx);
6766 return;
6767
6768}
6769
6770
6771/**---------------------------------------------------------------------------
6772 *
6773 * \brief wlan_hdd_restart_driver
6774 *
6775 * This function sends an event to supplicant to restart the WLAN driver.
6776 *
6777 * This function is called from vos_wlanRestart.
6778 *
6779 * \param - pHddCtx
6780 *
6781 * \return - VOS_STATUS_SUCCESS: Success
6782 * VOS_STATUS_E_EMPTY: Adapter is Empty
6783 * VOS_STATUS_E_ALREADY: Request already in progress
6784
6785 * --------------------------------------------------------------------------*/
6786VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6787{
6788 VOS_STATUS status = VOS_STATUS_SUCCESS;
6789
6790 /* A tight check to make sure reentrancy */
6791 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6792 {
6793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6794 "%s: WLAN restart is already in progress", __func__);
6795
6796 return VOS_STATUS_E_ALREADY;
6797 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006798 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006799#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006800 wcnss_reset_intr();
6801#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006802
Jeff Johnsone7245742012-09-05 17:12:55 -07006803 return status;
6804}
6805
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006806/*
6807 * API to find if there is any STA or P2P-Client is connected
6808 */
6809VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6810{
6811 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6812}
Jeff Johnsone7245742012-09-05 17:12:55 -07006813
Jeff Johnson295189b2012-06-20 16:38:30 -07006814//Register the module init/exit functions
6815module_init(hdd_module_init);
6816module_exit(hdd_module_exit);
6817
6818MODULE_LICENSE("Dual BSD/GPL");
6819MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6820MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6821
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006822module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6823 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006824
Jeff Johnson76052702013-04-16 13:55:05 -07006825module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006826 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);