blob: 82f6da2f32314b35fe0ac8d654c9ed895febcc41 [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
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002040 else {
2041 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2042 __func__, command);
2043 }
2044
Jeff Johnson295189b2012-06-20 16:38:30 -07002045 }
2046exit:
2047 if (command)
2048 {
2049 kfree(command);
2050 }
2051 return ret;
2052}
2053
Srinivas Girigowdade697412013-02-14 16:31:48 -08002054#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2055void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2056{
2057 eCsrBand band = -1;
2058 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2059 switch (band)
2060 {
2061 case eCSR_BAND_ALL:
2062 *pBand = WLAN_HDD_UI_BAND_AUTO;
2063 break;
2064
2065 case eCSR_BAND_24:
2066 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2067 break;
2068
2069 case eCSR_BAND_5G:
2070 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2071 break;
2072
2073 default:
2074 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2075 *pBand = -1;
2076 break;
2077 }
2078}
2079
2080/**---------------------------------------------------------------------------
2081
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002082 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2083
2084 This function parses the send action frame data passed in the format
2085 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2086
2087 \param - pValue Pointer to input country code revision
2088 \param - pTargetApBssid Pointer to target Ap bssid
2089 \param - pChannel Pointer to the Target AP channel
2090 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2091 \param - pBuf Pointer to data
2092 \param - pBufLen Pointer to data length
2093
2094 \return - 0 for success non-zero for failure
2095
2096 --------------------------------------------------------------------------*/
2097VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2098 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2099{
2100 tANI_U8 *inPtr = pValue;
2101 tANI_U8 *dataEnd;
2102 int tempInt;
2103 int j = 0;
2104 int i = 0;
2105 int v = 0;
2106 tANI_U8 tempBuf[32];
2107 tANI_U8 tempByte = 0;
2108
2109 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2110 /*no argument after the command*/
2111 if (NULL == inPtr)
2112 {
2113 return -EINVAL;
2114 }
2115
2116 /*no space after the command*/
2117 else if (SPACE_ASCII_VALUE != *inPtr)
2118 {
2119 return -EINVAL;
2120 }
2121
2122 /*removing empty spaces*/
2123 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2124
2125 /*no argument followed by spaces*/
2126 if ('\0' == *inPtr)
2127 {
2128 return -EINVAL;
2129 }
2130
2131 /*getting the first argument ie the target AP bssid */
2132 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2133 {
2134 return -EINVAL;
2135 }
2136 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2137 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2138 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2139
2140 /* point to the next argument */
2141 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2142 /*no argument after the command*/
2143 if (NULL == inPtr) return -EINVAL;
2144
2145 /*removing empty spaces*/
2146 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2147
2148 /*no argument followed by spaces*/
2149 if ('\0' == *inPtr)
2150 {
2151 return -EINVAL;
2152 }
2153
2154 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002155 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002156 v = kstrtos32(tempBuf, 10, &tempInt);
2157 if ( v < 0) return -EINVAL;
2158
2159 *pChannel = tempInt;
2160
2161 /* point to the next argument */
2162 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2163 /*no argument after the command*/
2164 if (NULL == inPtr) return -EINVAL;
2165 /*removing empty spaces*/
2166 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2167
2168 /*no argument followed by spaces*/
2169 if ('\0' == *inPtr)
2170 {
2171 return -EINVAL;
2172 }
2173
2174 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002175 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002176 v = kstrtos32(tempBuf, 10, &tempInt);
2177 if ( v < 0) return -EINVAL;
2178
2179 *pDwellTime = tempInt;
2180
2181 /* point to the next argument */
2182 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2183 /*no argument after the command*/
2184 if (NULL == inPtr) return -EINVAL;
2185 /*removing empty spaces*/
2186 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2187
2188 /*no argument followed by spaces*/
2189 if ('\0' == *inPtr)
2190 {
2191 return -EINVAL;
2192 }
2193
2194 /* find the length of data */
2195 dataEnd = inPtr;
2196 while(('\0' != *dataEnd) )
2197 {
2198 dataEnd++;
2199 ++(*pBufLen);
2200 }
2201 if ( *pBufLen <= 0) return -EINVAL;
2202
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002203 /* Allocate the number of bytes based on the number of input characters
2204 whether it is even or odd.
2205 if the number of input characters are even, then we need N/2 byte.
2206 if the number of input characters are odd, then we need do (N+1)/2 to
2207 compensate rounding off.
2208 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2209 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2210 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002211 if (NULL == *pBuf)
2212 {
2213 hddLog(VOS_TRACE_LEVEL_FATAL,
2214 "%s: vos_mem_alloc failed ", __func__);
2215 return -EINVAL;
2216 }
2217
2218 /* the buffer received from the upper layer is character buffer,
2219 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2220 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2221 and f0 in 3rd location */
2222 for (i = 0, j = 0; j < *pBufLen; j += 2)
2223 {
2224 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2225 (*pBuf)[i++] = tempByte;
2226 }
2227 *pBufLen = i;
2228 return VOS_STATUS_SUCCESS;
2229}
2230
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002231/**---------------------------------------------------------------------------
2232
Srinivas Girigowdade697412013-02-14 16:31:48 -08002233 \brief hdd_parse_countryrev() - HDD Parse country code revision
2234
2235 This function parses the country code revision passed in the format
2236 SETCOUNTRYREV<space><Country code><space>revision
2237
2238 \param - pValue Pointer to input country code revision
2239 \param - pCountryCode Pointer to local output array to record country code
2240 \param - pRevision Pointer to store revision integer number
2241
2242 \return - 0 for success non-zero for failure
2243
2244 --------------------------------------------------------------------------*/
2245VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2246{
2247 tANI_U8 *inPtr = pValue;
2248 int tempInt;
2249
2250 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2251 /*no argument after the command*/
2252 if (NULL == inPtr)
2253 {
2254 return -EINVAL;
2255 }
2256
2257 /*no space after the command*/
2258 else if (SPACE_ASCII_VALUE != *inPtr)
2259 {
2260 return -EINVAL;
2261 }
2262
2263 /*removing empty spaces*/
2264 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2265
2266 /*no argument followed by spaces*/
2267 if ('\0' == *inPtr)
2268 {
2269 return -EINVAL;
2270 }
2271
2272 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002273 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002274
2275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2276 "Country code is : %s", pCountryCode);
2277
2278 /*inPtr pointing to the beginning of first space after country code */
2279 inPtr = strpbrk( inPtr, " " );
2280 /*no revision number after the country code argument */
2281 if (NULL == inPtr)
2282 {
2283 return -EINVAL;
2284 }
2285
2286 inPtr++;
2287
2288 /*removing empty space*/
2289 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2290
2291 /*no channel list after the number of channels argument and spaces*/
2292 if (0 == strncmp(pCountryCode, "KR", 2))
2293 {
2294 if ('\0' == *inPtr)
2295 {
2296 return -EINVAL;
2297 }
2298
2299 sscanf(inPtr, "%d", &tempInt);
2300 *pRevision = tempInt;
2301 }
2302 else
2303 {
2304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2305 "Revision input is required only for Country KR");
2306 return -EINVAL;
2307 }
2308 return VOS_STATUS_SUCCESS;
2309}
2310
2311/**---------------------------------------------------------------------------
2312
2313 \brief hdd_parse_channellist() - HDD Parse channel list
2314
2315 This function parses the channel list passed in the format
2316 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002317 if the Number of channels (N) does not match with the actual number of channels passed
2318 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2319 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2320 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2321 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002322
2323 \param - pValue Pointer to input channel list
2324 \param - ChannelList Pointer to local output array to record channel list
2325 \param - pNumChannels Pointer to number of roam scan channels
2326
2327 \return - 0 for success non-zero for failure
2328
2329 --------------------------------------------------------------------------*/
2330VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2331{
2332 tANI_U8 *inPtr = pValue;
2333 int tempInt;
2334 int j = 0;
2335 int v = 0;
2336 char buf[32];
2337
2338 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2339 /*no argument after the command*/
2340 if (NULL == inPtr)
2341 {
2342 return -EINVAL;
2343 }
2344
2345 /*no space after the command*/
2346 else if (SPACE_ASCII_VALUE != *inPtr)
2347 {
2348 return -EINVAL;
2349 }
2350
2351 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002352 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002353
2354 /*no argument followed by spaces*/
2355 if ('\0' == *inPtr)
2356 {
2357 return -EINVAL;
2358 }
2359
2360 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002361 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002362 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002363 if ((v < 0) ||
2364 (tempInt <= 0) ||
2365 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2366 {
2367 return -EINVAL;
2368 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002369
2370 *pNumChannels = tempInt;
2371
2372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2373 "Number of channels are: %d", *pNumChannels);
2374
2375 for (j = 0; j < (*pNumChannels); j++)
2376 {
2377 /*inPtr pointing to the beginning of first space after number of channels*/
2378 inPtr = strpbrk( inPtr, " " );
2379 /*no channel list after the number of channels argument*/
2380 if (NULL == inPtr)
2381 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002382 if (0 != j)
2383 {
2384 *pNumChannels = j;
2385 return VOS_STATUS_SUCCESS;
2386 }
2387 else
2388 {
2389 return -EINVAL;
2390 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002391 }
2392
2393 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002394 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002395
2396 /*no channel list after the number of channels argument and spaces*/
2397 if ( '\0' == *inPtr )
2398 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002399 if (0 != j)
2400 {
2401 *pNumChannels = j;
2402 return VOS_STATUS_SUCCESS;
2403 }
2404 else
2405 {
2406 return -EINVAL;
2407 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002408 }
2409
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002410 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002411 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002412 if ((v < 0) ||
2413 (tempInt <= 0) ||
2414 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2415 {
2416 return -EINVAL;
2417 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002418 pChannelList[j] = tempInt;
2419
2420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2421 "Channel %d added to preferred channel list",
2422 pChannelList[j] );
2423 }
2424
Srinivas Girigowdade697412013-02-14 16:31:48 -08002425 return VOS_STATUS_SUCCESS;
2426}
2427
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002428
2429/**---------------------------------------------------------------------------
2430
2431 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2432
2433 This function parses the reasoc command data passed in the format
2434 REASSOC<space><bssid><space><channel>
2435
2436 \param - pValue Pointer to input country code revision
2437 \param - pTargetApBssid Pointer to target Ap bssid
2438 \param - pChannel Pointer to the Target AP channel
2439
2440 \return - 0 for success non-zero for failure
2441
2442 --------------------------------------------------------------------------*/
2443VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2444{
2445 tANI_U8 *inPtr = pValue;
2446 int tempInt;
2447 int v = 0;
2448 tANI_U8 tempBuf[32];
2449
2450 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2451 /*no argument after the command*/
2452 if (NULL == inPtr)
2453 {
2454 return -EINVAL;
2455 }
2456
2457 /*no space after the command*/
2458 else if (SPACE_ASCII_VALUE != *inPtr)
2459 {
2460 return -EINVAL;
2461 }
2462
2463 /*removing empty spaces*/
2464 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2465
2466 /*no argument followed by spaces*/
2467 if ('\0' == *inPtr)
2468 {
2469 return -EINVAL;
2470 }
2471
2472 /*getting the first argument ie the target AP bssid */
2473 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2474 {
2475 return -EINVAL;
2476 }
2477 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2478 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2479 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2480
2481 /* point to the next argument */
2482 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2483 /*no argument after the command*/
2484 if (NULL == inPtr) return -EINVAL;
2485
2486 /*removing empty spaces*/
2487 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2488
2489 /*no argument followed by spaces*/
2490 if ('\0' == *inPtr)
2491 {
2492 return -EINVAL;
2493 }
2494
2495 /*getting the next argument ie the channel number */
2496 sscanf(inPtr, "%s ", tempBuf);
2497 v = kstrtos32(tempBuf, 10, &tempInt);
2498 if ( v < 0) return -EINVAL;
2499
2500 *pChannel = tempInt;
2501 return VOS_STATUS_SUCCESS;
2502}
2503
2504#endif
2505
Jeff Johnson295189b2012-06-20 16:38:30 -07002506/**---------------------------------------------------------------------------
2507
2508 \brief hdd_open() - HDD Open function
2509
2510 This is called in response to ifconfig up
2511
2512 \param - dev Pointer to net_device structure
2513
2514 \return - 0 for success non-zero for failure
2515
2516 --------------------------------------------------------------------------*/
2517int hdd_open (struct net_device *dev)
2518{
2519 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2520 hdd_context_t *pHddCtx;
2521 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2522 VOS_STATUS status;
2523 v_BOOL_t in_standby = TRUE;
2524
2525 if (NULL == pAdapter)
2526 {
2527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002528 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002529 return -ENODEV;
2530 }
2531
2532 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2533 if (NULL == pHddCtx)
2534 {
2535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002536 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002537 return -ENODEV;
2538 }
2539
2540 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2541 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2542 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002543 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2544 {
2545 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302546 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002547 in_standby = FALSE;
2548 break;
2549 }
2550 else
2551 {
2552 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2553 pAdapterNode = pNext;
2554 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 }
2556
2557 if (TRUE == in_standby)
2558 {
2559 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2560 {
2561 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2562 "wlan out of power save", __func__);
2563 return -EINVAL;
2564 }
2565 }
2566
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002567 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002568 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2569 {
2570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002571 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002572 /* Enable TX queues only when we are connected */
2573 netif_tx_start_all_queues(dev);
2574 }
2575
2576 return 0;
2577}
2578
2579int hdd_mon_open (struct net_device *dev)
2580{
2581 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2582
2583 if(pAdapter == NULL) {
2584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002585 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002586 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002587 }
2588
2589 netif_start_queue(dev);
2590
2591 return 0;
2592}
2593/**---------------------------------------------------------------------------
2594
2595 \brief hdd_stop() - HDD stop function
2596
2597 This is called in response to ifconfig down
2598
2599 \param - dev Pointer to net_device structure
2600
2601 \return - 0 for success non-zero for failure
2602
2603 --------------------------------------------------------------------------*/
2604
2605int hdd_stop (struct net_device *dev)
2606{
2607 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2608 hdd_context_t *pHddCtx;
2609 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2610 VOS_STATUS status;
2611 v_BOOL_t enter_standby = TRUE;
2612
2613 ENTER();
2614
2615 if (NULL == pAdapter)
2616 {
2617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002618 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002619 return -ENODEV;
2620 }
2621
2622 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2623 if (NULL == pHddCtx)
2624 {
2625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002626 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 return -ENODEV;
2628 }
2629
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002630 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2632 netif_tx_disable(pAdapter->dev);
2633 netif_carrier_off(pAdapter->dev);
2634
2635
2636 /* SoftAP ifaces should never go in power save mode
2637 making sure same here. */
2638 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2639 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002640 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002641 )
2642 {
2643 /* SoftAP mode, so return from here */
2644 EXIT();
2645 return 0;
2646 }
2647
2648 /* Find if any iface is up then
2649 if any iface is up then can't put device to sleep/ power save mode. */
2650 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2651 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2652 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002653 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2654 {
2655 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302656 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002657 enter_standby = FALSE;
2658 break;
2659 }
2660 else
2661 {
2662 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2663 pAdapterNode = pNext;
2664 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002665 }
2666
2667 if (TRUE == enter_standby)
2668 {
2669 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2670 "entering standby", __func__);
2671 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2672 {
2673 /*log and return success*/
2674 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2675 "wlan in power save", __func__);
2676 }
2677 }
2678
2679 EXIT();
2680 return 0;
2681}
2682
2683/**---------------------------------------------------------------------------
2684
2685 \brief hdd_uninit() - HDD uninit function
2686
2687 This is called during the netdev unregister to uninitialize all data
2688associated with the device
2689
2690 \param - dev Pointer to net_device structure
2691
2692 \return - void
2693
2694 --------------------------------------------------------------------------*/
2695static void hdd_uninit (struct net_device *dev)
2696{
2697 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2698
2699 ENTER();
2700
2701 do
2702 {
2703 if (NULL == pAdapter)
2704 {
2705 hddLog(VOS_TRACE_LEVEL_FATAL,
2706 "%s: NULL pAdapter", __func__);
2707 break;
2708 }
2709
2710 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2711 {
2712 hddLog(VOS_TRACE_LEVEL_FATAL,
2713 "%s: Invalid magic", __func__);
2714 break;
2715 }
2716
2717 if (NULL == pAdapter->pHddCtx)
2718 {
2719 hddLog(VOS_TRACE_LEVEL_FATAL,
2720 "%s: NULL pHddCtx", __func__);
2721 break;
2722 }
2723
2724 if (dev != pAdapter->dev)
2725 {
2726 hddLog(VOS_TRACE_LEVEL_FATAL,
2727 "%s: Invalid device reference", __func__);
2728 /* we haven't validated all cases so let this go for now */
2729 }
2730
2731 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2732
2733 /* after uninit our adapter structure will no longer be valid */
2734 pAdapter->dev = NULL;
2735 pAdapter->magic = 0;
2736 } while (0);
2737
2738 EXIT();
2739}
2740
2741/**---------------------------------------------------------------------------
2742
2743 \brief hdd_release_firmware() -
2744
2745 This function calls the release firmware API to free the firmware buffer.
2746
2747 \param - pFileName Pointer to the File Name.
2748 pCtx - Pointer to the adapter .
2749
2750
2751 \return - 0 for success, non zero for failure
2752
2753 --------------------------------------------------------------------------*/
2754
2755VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2756{
2757 VOS_STATUS status = VOS_STATUS_SUCCESS;
2758 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2759 ENTER();
2760
2761
2762 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2763
2764 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2765
2766 if(pHddCtx->fw) {
2767 release_firmware(pHddCtx->fw);
2768 pHddCtx->fw = NULL;
2769 }
2770 else
2771 status = VOS_STATUS_E_FAILURE;
2772 }
2773 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2774 if(pHddCtx->nv) {
2775 release_firmware(pHddCtx->nv);
2776 pHddCtx->nv = NULL;
2777 }
2778 else
2779 status = VOS_STATUS_E_FAILURE;
2780
2781 }
2782
2783 EXIT();
2784 return status;
2785}
2786
2787/**---------------------------------------------------------------------------
2788
2789 \brief hdd_request_firmware() -
2790
2791 This function reads the firmware file using the request firmware
2792 API and returns the the firmware data and the firmware file size.
2793
2794 \param - pfileName - Pointer to the file name.
2795 - pCtx - Pointer to the adapter .
2796 - ppfw_data - Pointer to the pointer of the firmware data.
2797 - pSize - Pointer to the file size.
2798
2799 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2800
2801 --------------------------------------------------------------------------*/
2802
2803
2804VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2805{
2806 int status;
2807 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2808 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2809 ENTER();
2810
2811 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2812
2813 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2814
2815 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2816 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2817 __func__, pfileName);
2818 retval = VOS_STATUS_E_FAILURE;
2819 }
2820
2821 else {
2822 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2823 *pSize = pHddCtx->fw->size;
2824 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2825 __func__, *pSize);
2826 }
2827 }
2828 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2829
2830 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2831
2832 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2834 __func__, pfileName);
2835 retval = VOS_STATUS_E_FAILURE;
2836 }
2837
2838 else {
2839 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2840 *pSize = pHddCtx->nv->size;
2841 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2842 __func__, *pSize);
2843 }
2844 }
2845
2846 EXIT();
2847 return retval;
2848}
2849/**---------------------------------------------------------------------------
2850 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2851
2852 This is the function invoked by SME to inform the result of a full power
2853 request issued by HDD
2854
2855 \param - callbackcontext - Pointer to cookie
2856 status - result of request
2857
2858 \return - None
2859
2860--------------------------------------------------------------------------*/
2861void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2862{
2863 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2864
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002865 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002866 if(&pHddCtx->full_pwr_comp_var)
2867 {
2868 complete(&pHddCtx->full_pwr_comp_var);
2869 }
2870}
2871
2872/**---------------------------------------------------------------------------
2873
2874 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2875
2876 This is the function invoked by SME to inform the result of BMPS
2877 request issued by HDD
2878
2879 \param - callbackcontext - Pointer to cookie
2880 status - result of request
2881
2882 \return - None
2883
2884--------------------------------------------------------------------------*/
2885void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2886{
2887
2888 struct completion *completion_var = (struct completion*) callbackContext;
2889
2890 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2891 if(completion_var != NULL)
2892 {
2893 complete(completion_var);
2894 }
2895}
2896
2897/**---------------------------------------------------------------------------
2898
2899 \brief hdd_get_cfg_file_size() -
2900
2901 This function reads the configuration file using the request firmware
2902 API and returns the configuration file size.
2903
2904 \param - pCtx - Pointer to the adapter .
2905 - pFileName - Pointer to the file name.
2906 - pBufSize - Pointer to the buffer size.
2907
2908 \return - 0 for success, non zero for failure
2909
2910 --------------------------------------------------------------------------*/
2911
2912VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2913{
2914 int status;
2915 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2916
2917 ENTER();
2918
2919 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2920
2921 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2923 status = VOS_STATUS_E_FAILURE;
2924 }
2925 else {
2926 *pBufSize = pHddCtx->fw->size;
2927 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2928 release_firmware(pHddCtx->fw);
2929 pHddCtx->fw = NULL;
2930 }
2931
2932 EXIT();
2933 return VOS_STATUS_SUCCESS;
2934}
2935
2936/**---------------------------------------------------------------------------
2937
2938 \brief hdd_read_cfg_file() -
2939
2940 This function reads the configuration file using the request firmware
2941 API and returns the cfg data and the buffer size of the configuration file.
2942
2943 \param - pCtx - Pointer to the adapter .
2944 - pFileName - Pointer to the file name.
2945 - pBuffer - Pointer to the data buffer.
2946 - pBufSize - Pointer to the buffer size.
2947
2948 \return - 0 for success, non zero for failure
2949
2950 --------------------------------------------------------------------------*/
2951
2952VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2953 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2954{
2955 int status;
2956 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2957
2958 ENTER();
2959
2960 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2961
2962 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2964 return VOS_STATUS_E_FAILURE;
2965 }
2966 else {
2967 if(*pBufSize != pHddCtx->fw->size) {
2968 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2969 "file size", __func__);
2970 release_firmware(pHddCtx->fw);
2971 pHddCtx->fw = NULL;
2972 return VOS_STATUS_E_FAILURE;
2973 }
2974 else {
2975 if(pBuffer) {
2976 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2977 }
2978 release_firmware(pHddCtx->fw);
2979 pHddCtx->fw = NULL;
2980 }
2981 }
2982
2983 EXIT();
2984
2985 return VOS_STATUS_SUCCESS;
2986}
2987
2988/**---------------------------------------------------------------------------
2989
Jeff Johnson295189b2012-06-20 16:38:30 -07002990 \brief hdd_set_mac_address() -
2991
2992 This function sets the user specified mac address using
2993 the command ifconfig wlanX hw ether <mac adress>.
2994
2995 \param - dev - Pointer to the net device.
2996 - addr - Pointer to the sockaddr.
2997 \return - 0 for success, non zero for failure
2998
2999 --------------------------------------------------------------------------*/
3000
3001static int hdd_set_mac_address(struct net_device *dev, void *addr)
3002{
3003 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3004 struct sockaddr *psta_mac_addr = addr;
3005 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3006
3007 ENTER();
3008
3009 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3010
3011#ifdef HDD_SESSIONIZE
3012 // set the MAC address though the STA ID CFG.
3013 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3014 (v_U8_t *)&pAdapter->macAddressCurrent,
3015 sizeof( pAdapter->macAddressCurrent ),
3016 hdd_set_mac_addr_cb, VOS_FALSE );
3017#endif
3018
3019 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3020
3021 EXIT();
3022 return halStatus;
3023}
3024
3025tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3026{
3027 int i;
3028 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3029 {
3030 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3031 break;
3032 }
3033
3034 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3035 return NULL;
3036
3037 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3038 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3039}
3040
3041void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3042{
3043 int i;
3044 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3045 {
3046 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3047 {
3048 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3049 break;
3050 }
3051 }
3052 return;
3053}
3054
3055#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3056 static struct net_device_ops wlan_drv_ops = {
3057 .ndo_open = hdd_open,
3058 .ndo_stop = hdd_stop,
3059 .ndo_uninit = hdd_uninit,
3060 .ndo_start_xmit = hdd_hard_start_xmit,
3061 .ndo_tx_timeout = hdd_tx_timeout,
3062 .ndo_get_stats = hdd_stats,
3063 .ndo_do_ioctl = hdd_ioctl,
3064 .ndo_set_mac_address = hdd_set_mac_address,
3065 .ndo_select_queue = hdd_select_queue,
3066#ifdef WLAN_FEATURE_PACKET_FILTERING
3067#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3068 .ndo_set_rx_mode = hdd_set_multicast_list,
3069#else
3070 .ndo_set_multicast_list = hdd_set_multicast_list,
3071#endif //LINUX_VERSION_CODE
3072#endif
3073 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003074 static struct net_device_ops wlan_mon_drv_ops = {
3075 .ndo_open = hdd_mon_open,
3076 .ndo_stop = hdd_stop,
3077 .ndo_uninit = hdd_uninit,
3078 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3079 .ndo_tx_timeout = hdd_tx_timeout,
3080 .ndo_get_stats = hdd_stats,
3081 .ndo_do_ioctl = hdd_ioctl,
3082 .ndo_set_mac_address = hdd_set_mac_address,
3083 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003084
3085#endif
3086
3087void hdd_set_station_ops( struct net_device *pWlanDev )
3088{
3089#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3090 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3091 pWlanDev->netdev_ops = &wlan_drv_ops;
3092#else
3093 pWlanDev->open = hdd_open;
3094 pWlanDev->stop = hdd_stop;
3095 pWlanDev->uninit = hdd_uninit;
3096 pWlanDev->hard_start_xmit = NULL;
3097 pWlanDev->tx_timeout = hdd_tx_timeout;
3098 pWlanDev->get_stats = hdd_stats;
3099 pWlanDev->do_ioctl = hdd_ioctl;
3100 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3101 pWlanDev->set_mac_address = hdd_set_mac_address;
3102#endif
3103}
3104
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003105static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003106{
3107 struct net_device *pWlanDev = NULL;
3108 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 /*
3110 * cfg80211 initialization and registration....
3111 */
3112 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3113
Jeff Johnson295189b2012-06-20 16:38:30 -07003114 if(pWlanDev != NULL)
3115 {
3116
3117 //Save the pointer to the net_device in the HDD adapter
3118 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3119
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3121
3122 pAdapter->dev = pWlanDev;
3123 pAdapter->pHddCtx = pHddCtx;
3124 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3125
3126 init_completion(&pAdapter->session_open_comp_var);
3127 init_completion(&pAdapter->session_close_comp_var);
3128 init_completion(&pAdapter->disconnect_comp_var);
3129 init_completion(&pAdapter->linkup_event_var);
3130 init_completion(&pAdapter->cancel_rem_on_chan_var);
3131 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003132#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3133 init_completion(&pAdapter->offchannel_tx_event);
3134#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003135 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003136#ifdef FEATURE_WLAN_TDLS
3137 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003138 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003139 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303140 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003141#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 init_completion(&pHddCtx->mc_sus_event_var);
3143 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303144 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003145 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003146
Jeff Johnson295189b2012-06-20 16:38:30 -07003147 pAdapter->isLinkUpSvcNeeded = FALSE;
3148 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3149 //Init the net_device structure
3150 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3151
3152 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3153 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3154 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3155 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3156
3157 hdd_set_station_ops( pAdapter->dev );
3158
3159 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3161 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3162 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003163 /* set pWlanDev's parent to underlying device */
3164 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3165 }
3166
3167 return pAdapter;
3168}
3169
3170VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3171{
3172 struct net_device *pWlanDev = pAdapter->dev;
3173 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3174 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3175 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3176
3177 if( rtnl_lock_held )
3178 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003179 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003180 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3181 {
3182 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3183 return VOS_STATUS_E_FAILURE;
3184 }
3185 }
3186 if (register_netdevice(pWlanDev))
3187 {
3188 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3189 return VOS_STATUS_E_FAILURE;
3190 }
3191 }
3192 else
3193 {
3194 if(register_netdev(pWlanDev))
3195 {
3196 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3197 return VOS_STATUS_E_FAILURE;
3198 }
3199 }
3200 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3201
3202 return VOS_STATUS_SUCCESS;
3203}
3204
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003205static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003206{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003207 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003208
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003209 if (NULL == pAdapter)
3210 {
3211 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3212 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003213 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003214
3215 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3216 {
3217 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3218 return eHAL_STATUS_NOT_INITIALIZED;
3219 }
3220
3221 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3222
3223 /* need to make sure all of our scheduled work has completed.
3224 * This callback is called from MC thread context, so it is safe to
3225 * to call below flush workqueue API from here.
3226 */
3227 flush_scheduled_work();
3228
3229 /* We can be blocked while waiting for scheduled work to be
3230 * flushed, and the adapter structure can potentially be freed, in
3231 * which case the magic will have been reset. So make sure the
3232 * magic is still good, and hence the adapter structure is still
3233 * valid, before signaling completion */
3234 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3235 {
3236 complete(&pAdapter->session_close_comp_var);
3237 }
3238
Jeff Johnson295189b2012-06-20 16:38:30 -07003239 return eHAL_STATUS_SUCCESS;
3240}
3241
3242VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3243{
3244 struct net_device *pWlanDev = pAdapter->dev;
3245 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3246 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3247 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3248 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3249 int rc = 0;
3250
3251 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003252 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003253 //Open a SME session for future operation
3254 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003255 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3257 {
3258 hddLog(VOS_TRACE_LEVEL_FATAL,
3259 "sme_OpenSession() failed with status code %08d [x%08lx]",
3260 halStatus, halStatus );
3261 status = VOS_STATUS_E_FAILURE;
3262 goto error_sme_open;
3263 }
3264
3265 //Block on a completion variable. Can't wait forever though.
3266 rc = wait_for_completion_interruptible_timeout(
3267 &pAdapter->session_open_comp_var,
3268 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3269 if (!rc)
3270 {
3271 hddLog(VOS_TRACE_LEVEL_FATAL,
3272 "Session is not opened within timeout period code %08d", rc );
3273 status = VOS_STATUS_E_FAILURE;
3274 goto error_sme_open;
3275 }
3276
3277 // Register wireless extensions
3278 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3279 {
3280 hddLog(VOS_TRACE_LEVEL_FATAL,
3281 "hdd_register_wext() failed with status code %08d [x%08lx]",
3282 halStatus, halStatus );
3283 status = VOS_STATUS_E_FAILURE;
3284 goto error_register_wext;
3285 }
3286 //Safe to register the hard_start_xmit function again
3287#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3288 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3289#else
3290 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3291#endif
3292
3293 //Set the Connection State to Not Connected
3294 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3295
3296 //Set the default operation channel
3297 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3298
3299 /* Make the default Auth Type as OPEN*/
3300 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3301
3302 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3303 {
3304 hddLog(VOS_TRACE_LEVEL_FATAL,
3305 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3306 status, status );
3307 goto error_init_txrx;
3308 }
3309
3310 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3311
3312 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3313 {
3314 hddLog(VOS_TRACE_LEVEL_FATAL,
3315 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3316 status, status );
3317 goto error_wmm_init;
3318 }
3319
3320 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3321
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003322#ifdef FEATURE_WLAN_TDLS
3323 if(0 != wlan_hdd_tdls_init(pAdapter))
3324 {
3325 status = VOS_STATUS_E_FAILURE;
3326 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3327 goto error_tdls_init;
3328 }
3329 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3330#endif
3331
Jeff Johnson295189b2012-06-20 16:38:30 -07003332 return VOS_STATUS_SUCCESS;
3333
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003334#ifdef FEATURE_WLAN_TDLS
3335error_tdls_init:
3336 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3337 hdd_wmm_adapter_close(pAdapter);
3338#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003339error_wmm_init:
3340 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3341 hdd_deinit_tx_rx(pAdapter);
3342error_init_txrx:
3343 hdd_UnregisterWext(pWlanDev);
3344error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003345 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 {
3347 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003348 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003349 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003350 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 {
3352 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003353 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003354 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003355 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003356 }
3357}
3358error_sme_open:
3359 return status;
3360}
3361
Jeff Johnson295189b2012-06-20 16:38:30 -07003362void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3363{
3364 hdd_cfg80211_state_t *cfgState;
3365
3366 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3367
3368 if( NULL != cfgState->buf )
3369 {
3370 int rc;
3371 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3372 rc = wait_for_completion_interruptible_timeout(
3373 &pAdapter->tx_action_cnf_event,
3374 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3375 if(!rc)
3376 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3379 }
3380 }
3381 return;
3382}
Jeff Johnson295189b2012-06-20 16:38:30 -07003383
3384void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3385{
3386 ENTER();
3387 switch ( pAdapter->device_mode )
3388 {
3389 case WLAN_HDD_INFRA_STATION:
3390 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003391 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003392 {
3393 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3394 {
3395 hdd_deinit_tx_rx( pAdapter );
3396 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3397 }
3398
3399 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3400 {
3401 hdd_wmm_adapter_close( pAdapter );
3402 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3403 }
3404
Jeff Johnson295189b2012-06-20 16:38:30 -07003405 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003406#ifdef FEATURE_WLAN_TDLS
3407 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3408 {
3409 wlan_hdd_tdls_exit(pAdapter);
3410 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3411 }
3412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003413
3414 break;
3415 }
3416
3417 case WLAN_HDD_SOFTAP:
3418 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003419 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003420 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003421
3422 hdd_unregister_hostapd(pAdapter);
3423 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003425 break;
3426 }
3427
3428 case WLAN_HDD_MONITOR:
3429 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003430 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003431 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3432 {
3433 hdd_deinit_tx_rx( pAdapter );
3434 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3435 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003436 if(NULL != pAdapterforTx)
3437 {
3438 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 break;
3441 }
3442
3443
3444 default:
3445 break;
3446 }
3447
3448 EXIT();
3449}
3450
3451void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3452{
3453 struct net_device *pWlanDev = pAdapter->dev;
3454
3455 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3456 if( rtnl_held )
3457 {
3458 unregister_netdevice(pWlanDev);
3459 }
3460 else
3461 {
3462 unregister_netdev(pWlanDev);
3463 }
3464 // note that the pAdapter is no longer valid at this point
3465 // since the memory has been reclaimed
3466 }
3467
3468}
3469
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003470void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3471{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303472 VOS_STATUS status;
3473 hdd_adapter_t *pAdapter = NULL;
3474 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003475
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303476 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003477
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303478 /*loop through all adapters.*/
3479 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003480 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303481 pAdapter = pAdapterNode->pAdapter;
3482 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3483 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003484
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303485 { // we skip this registration for modes other than STA and P2P client modes.
3486 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3487 pAdapterNode = pNext;
3488 continue;
3489 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003490
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303491 //Apply Dynamic DTIM For P2P
3492 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3493 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3494 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3495 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3496 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3497 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3498 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3499 (eConnectionState_Associated ==
3500 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3501 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3502 {
3503 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003504
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303505 powerRequest.uIgnoreDTIM = 1;
3506 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3507
3508 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3509 {
3510 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3511 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3512 }
3513 else
3514 {
3515 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3516 }
3517
3518 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3519 * specified during Enter/Exit BMPS when LCD off*/
3520 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3521 NULL, eANI_BOOLEAN_FALSE);
3522 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3523 NULL, eANI_BOOLEAN_FALSE);
3524
3525 /* switch to the DTIM specified in cfg.ini */
3526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3527 "Switch to DTIM %d", powerRequest.uListenInterval);
3528 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3529 break;
3530
3531 }
3532
3533 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3534 pAdapterNode = pNext;
3535 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003536}
3537
3538void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3539{
3540 /*Switch back to DTIM 1*/
3541 tSirSetPowerParamsReq powerRequest = { 0 };
3542
3543 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3544 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003545 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003546
3547 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3548 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3549 NULL, eANI_BOOLEAN_FALSE);
3550 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3551 NULL, eANI_BOOLEAN_FALSE);
3552
3553 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3554 "Switch to DTIM%d",powerRequest.uListenInterval);
3555 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3556
3557}
3558
Jeff Johnson295189b2012-06-20 16:38:30 -07003559VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3560{
3561 VOS_STATUS status = VOS_STATUS_SUCCESS;
3562
3563 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3564 {
3565 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3566 }
3567
3568 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3569 {
3570 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3571 }
3572
3573 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3574 {
3575 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3576 }
3577
3578 return status;
3579}
3580
3581VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3582{
3583 hdd_adapter_t *pAdapter = NULL;
3584 eHalStatus halStatus;
3585 VOS_STATUS status = VOS_STATUS_E_INVAL;
3586 v_BOOL_t disableBmps = FALSE;
3587 v_BOOL_t disableImps = FALSE;
3588
3589 switch(session_type)
3590 {
3591 case WLAN_HDD_INFRA_STATION:
3592 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003593 case WLAN_HDD_P2P_CLIENT:
3594 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003595 //Exit BMPS -> Is Sta/P2P Client is already connected
3596 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3597 if((NULL != pAdapter)&&
3598 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3599 {
3600 disableBmps = TRUE;
3601 }
3602
3603 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3604 if((NULL != pAdapter)&&
3605 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3606 {
3607 disableBmps = TRUE;
3608 }
3609
3610 //Exit both Bmps and Imps incase of Go/SAP Mode
3611 if((WLAN_HDD_SOFTAP == session_type) ||
3612 (WLAN_HDD_P2P_GO == session_type))
3613 {
3614 disableBmps = TRUE;
3615 disableImps = TRUE;
3616 }
3617
3618 if(TRUE == disableImps)
3619 {
3620 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3621 {
3622 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3623 }
3624 }
3625
3626 if(TRUE == disableBmps)
3627 {
3628 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3629 {
3630 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3631
3632 if(eHAL_STATUS_SUCCESS != halStatus)
3633 {
3634 status = VOS_STATUS_E_FAILURE;
3635 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3636 VOS_ASSERT(0);
3637 return status;
3638 }
3639 }
3640
3641 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3642 {
3643 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3644
3645 if(eHAL_STATUS_SUCCESS != halStatus)
3646 {
3647 status = VOS_STATUS_E_FAILURE;
3648 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3649 VOS_ASSERT(0);
3650 return status;
3651 }
3652 }
3653 }
3654
3655 if((TRUE == disableBmps) ||
3656 (TRUE == disableImps))
3657 {
3658 /* Now, get the chip into Full Power now */
3659 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3660 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3661 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3662
3663 if(halStatus != eHAL_STATUS_SUCCESS)
3664 {
3665 if(halStatus == eHAL_STATUS_PMC_PENDING)
3666 {
3667 //Block on a completion variable. Can't wait forever though
3668 wait_for_completion_interruptible_timeout(
3669 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3670 }
3671 else
3672 {
3673 status = VOS_STATUS_E_FAILURE;
3674 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3675 VOS_ASSERT(0);
3676 return status;
3677 }
3678 }
3679
3680 status = VOS_STATUS_SUCCESS;
3681 }
3682
3683 break;
3684 }
3685 return status;
3686}
3687
3688hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003689 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003690 tANI_U8 rtnl_held )
3691{
3692 hdd_adapter_t *pAdapter = NULL;
3693 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3694 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3695 VOS_STATUS exitbmpsStatus;
3696
3697 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3698
3699 //Disable BMPS incase of Concurrency
3700 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3701
3702 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3703 {
3704 //Fail to Exit BMPS
3705 VOS_ASSERT(0);
3706 return NULL;
3707 }
3708
3709 switch(session_type)
3710 {
3711 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003712 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003713 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003714 {
3715 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3716
3717 if( NULL == pAdapter )
3718 return NULL;
3719
Jeff Johnsone7245742012-09-05 17:12:55 -07003720 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3721 NL80211_IFTYPE_P2P_CLIENT:
3722 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003723
Jeff Johnson295189b2012-06-20 16:38:30 -07003724 pAdapter->device_mode = session_type;
3725
3726 status = hdd_init_station_mode( pAdapter );
3727 if( VOS_STATUS_SUCCESS != status )
3728 goto err_free_netdev;
3729
3730 status = hdd_register_interface( pAdapter, rtnl_held );
3731 if( VOS_STATUS_SUCCESS != status )
3732 {
3733 hdd_deinit_adapter(pHddCtx, pAdapter);
3734 goto err_free_netdev;
3735 }
3736 //Stop the Interface TX queue.
3737 netif_tx_disable(pAdapter->dev);
3738 //netif_tx_disable(pWlanDev);
3739 netif_carrier_off(pAdapter->dev);
3740
3741 break;
3742 }
3743
Jeff Johnson295189b2012-06-20 16:38:30 -07003744 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003745 case WLAN_HDD_SOFTAP:
3746 {
3747 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3748 if( NULL == pAdapter )
3749 return NULL;
3750
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3752 NL80211_IFTYPE_AP:
3753 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 pAdapter->device_mode = session_type;
3755
3756 status = hdd_init_ap_mode(pAdapter);
3757 if( VOS_STATUS_SUCCESS != status )
3758 goto err_free_netdev;
3759
3760 status = hdd_register_hostapd( pAdapter, rtnl_held );
3761 if( VOS_STATUS_SUCCESS != status )
3762 {
3763 hdd_deinit_adapter(pHddCtx, pAdapter);
3764 goto err_free_netdev;
3765 }
3766
3767 netif_tx_disable(pAdapter->dev);
3768 netif_carrier_off(pAdapter->dev);
3769
3770 hdd_set_conparam( 1 );
3771 break;
3772 }
3773 case WLAN_HDD_MONITOR:
3774 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003775 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3776 if( NULL == pAdapter )
3777 return NULL;
3778
3779 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3780 pAdapter->device_mode = session_type;
3781 status = hdd_register_interface( pAdapter, rtnl_held );
3782#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3783 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3784#else
3785 pAdapter->dev->open = hdd_mon_open;
3786 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3787#endif
3788 hdd_init_tx_rx( pAdapter );
3789 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3790 //Set adapter to be used for data tx. It will use either GO or softap.
3791 pAdapter->sessionCtx.monitor.pAdapterForTx =
3792 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3794 {
3795 pAdapter->sessionCtx.monitor.pAdapterForTx =
3796 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3797 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003798 /* This workqueue will be used to transmit management packet over
3799 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003800 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3801 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3802 return NULL;
3803 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003804
Jeff Johnson295189b2012-06-20 16:38:30 -07003805 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3806 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003807 }
3808 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 case WLAN_HDD_FTM:
3810 {
3811 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3812
3813 if( NULL == pAdapter )
3814 return NULL;
3815 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3816 * message while loading driver in FTM mode. */
3817 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3818 pAdapter->device_mode = session_type;
3819 status = hdd_register_interface( pAdapter, rtnl_held );
3820 }
3821 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 default:
3823 {
3824 VOS_ASSERT(0);
3825 return NULL;
3826 }
3827 }
3828
3829
3830 if( VOS_STATUS_SUCCESS == status )
3831 {
3832 //Add it to the hdd's session list.
3833 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3834 if( NULL == pHddAdapterNode )
3835 {
3836 status = VOS_STATUS_E_NOMEM;
3837 }
3838 else
3839 {
3840 pHddAdapterNode->pAdapter = pAdapter;
3841 status = hdd_add_adapter_back ( pHddCtx,
3842 pHddAdapterNode );
3843 }
3844 }
3845
3846 if( VOS_STATUS_SUCCESS != status )
3847 {
3848 if( NULL != pAdapter )
3849 {
3850 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3851 pAdapter = NULL;
3852 }
3853 if( NULL != pHddAdapterNode )
3854 {
3855 vos_mem_free( pHddAdapterNode );
3856 }
3857
3858 goto resume_bmps;
3859 }
3860
3861 if(VOS_STATUS_SUCCESS == status)
3862 {
3863 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3864
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003865 //Initialize the WoWL service
3866 if(!hdd_init_wowl(pAdapter))
3867 {
3868 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3869 goto err_free_netdev;
3870 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003871 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 return pAdapter;
3873
3874err_free_netdev:
3875 free_netdev(pAdapter->dev);
3876 wlan_hdd_release_intf_addr( pHddCtx,
3877 pAdapter->macAddressCurrent.bytes );
3878
3879resume_bmps:
3880 //If bmps disabled enable it
3881 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3882 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303883 if (pHddCtx->hdd_wlan_suspended)
3884 {
3885 hdd_set_pwrparams(pHddCtx);
3886 }
3887 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 }
3889 return NULL;
3890}
3891
3892VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3893 tANI_U8 rtnl_held )
3894{
3895 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3896 VOS_STATUS status;
3897
3898 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3899 if( VOS_STATUS_SUCCESS != status )
3900 return status;
3901
3902 while ( pCurrent->pAdapter != pAdapter )
3903 {
3904 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3905 if( VOS_STATUS_SUCCESS != status )
3906 break;
3907
3908 pCurrent = pNext;
3909 }
3910 pAdapterNode = pCurrent;
3911 if( VOS_STATUS_SUCCESS == status )
3912 {
3913 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3914 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3915 hdd_remove_adapter( pHddCtx, pAdapterNode );
3916 vos_mem_free( pAdapterNode );
3917
Jeff Johnson295189b2012-06-20 16:38:30 -07003918
3919 /* If there is a single session of STA/P2P client, re-enable BMPS */
3920 if ((!vos_concurrent_sessions_running()) &&
3921 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3922 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3923 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303924 if (pHddCtx->hdd_wlan_suspended)
3925 {
3926 hdd_set_pwrparams(pHddCtx);
3927 }
3928 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003929 }
3930
3931 return VOS_STATUS_SUCCESS;
3932 }
3933
3934 return VOS_STATUS_E_FAILURE;
3935}
3936
3937VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3938{
3939 hdd_adapter_list_node_t *pHddAdapterNode;
3940 VOS_STATUS status;
3941
3942 ENTER();
3943
3944 do
3945 {
3946 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3947 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3948 {
3949 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3950 vos_mem_free( pHddAdapterNode );
3951 }
3952 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3953
3954 EXIT();
3955
3956 return VOS_STATUS_SUCCESS;
3957}
3958
3959void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3960{
3961 v_U8_t addIE[1] = {0};
3962
3963 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3964 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3965 eANI_BOOLEAN_FALSE) )
3966 {
3967 hddLog(LOGE,
3968 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3969 }
3970
3971 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3972 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3973 eANI_BOOLEAN_FALSE) )
3974 {
3975 hddLog(LOGE,
3976 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3977 }
3978
3979 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3980 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3981 eANI_BOOLEAN_FALSE) )
3982 {
3983 hddLog(LOGE,
3984 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3985 }
3986}
3987
3988VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3989{
3990 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3991 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3992 union iwreq_data wrqu;
3993
3994 ENTER();
3995
3996 switch(pAdapter->device_mode)
3997 {
3998 case WLAN_HDD_INFRA_STATION:
3999 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004000 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004001 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4002 {
4003 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4004 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4005 pAdapter->sessionId,
4006 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4007 else
4008 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4009 pAdapter->sessionId,
4010 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4011 //success implies disconnect command got queued up successfully
4012 if(halStatus == eHAL_STATUS_SUCCESS)
4013 {
4014 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4015 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4016 }
4017 memset(&wrqu, '\0', sizeof(wrqu));
4018 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4019 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4020 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4021 }
4022 else
4023 {
4024 hdd_abort_mac_scan(pHddCtx);
4025 }
4026
4027 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4028 {
4029 INIT_COMPLETION(pAdapter->session_close_comp_var);
4030 if (eHAL_STATUS_SUCCESS ==
4031 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4032 hdd_smeCloseSessionCallback, pAdapter))
4033 {
4034 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004035 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004036 &pAdapter->session_close_comp_var,
4037 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4038 }
4039 }
4040
4041 break;
4042
4043 case WLAN_HDD_SOFTAP:
4044 case WLAN_HDD_P2P_GO:
4045 //Any softap specific cleanup here...
4046 mutex_lock(&pHddCtx->sap_lock);
4047 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4048 {
4049 VOS_STATUS status;
4050 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4051
4052 //Stop Bss.
4053 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4054 if (VOS_IS_STATUS_SUCCESS(status))
4055 {
4056 hdd_hostapd_state_t *pHostapdState =
4057 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4058
4059 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4060
4061 if (!VOS_IS_STATUS_SUCCESS(status))
4062 {
4063 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004064 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004065 }
4066 }
4067 else
4068 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004069 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004070 }
4071 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4072
4073 if (eHAL_STATUS_FAILURE ==
4074 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4075 0, NULL, eANI_BOOLEAN_FALSE))
4076 {
4077 hddLog(LOGE,
4078 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004079 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
4081
4082 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4083 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4084 eANI_BOOLEAN_FALSE) )
4085 {
4086 hddLog(LOGE,
4087 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4088 }
4089
4090 // Reset WNI_CFG_PROBE_RSP Flags
4091 wlan_hdd_reset_prob_rspies(pAdapter);
4092 kfree(pAdapter->sessionCtx.ap.beacon);
4093 pAdapter->sessionCtx.ap.beacon = NULL;
4094 }
4095 mutex_unlock(&pHddCtx->sap_lock);
4096 break;
4097 case WLAN_HDD_MONITOR:
4098 break;
4099 default:
4100 break;
4101 }
4102
4103 EXIT();
4104 return VOS_STATUS_SUCCESS;
4105}
4106
4107VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4108{
4109 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4110 VOS_STATUS status;
4111 hdd_adapter_t *pAdapter;
4112
4113 ENTER();
4114
4115 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4116
4117 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4118 {
4119 pAdapter = pAdapterNode->pAdapter;
4120 netif_tx_disable(pAdapter->dev);
4121 netif_carrier_off(pAdapter->dev);
4122
4123 hdd_stop_adapter( pHddCtx, pAdapter );
4124
4125 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4126 pAdapterNode = pNext;
4127 }
4128
4129 EXIT();
4130
4131 return VOS_STATUS_SUCCESS;
4132}
4133
4134VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4135{
4136 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4137 VOS_STATUS status;
4138 hdd_adapter_t *pAdapter;
4139
4140 ENTER();
4141
4142 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4143
4144 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4145 {
4146 pAdapter = pAdapterNode->pAdapter;
4147 netif_tx_disable(pAdapter->dev);
4148 netif_carrier_off(pAdapter->dev);
4149
Jeff Johnson295189b2012-06-20 16:38:30 -07004150 hdd_deinit_tx_rx(pAdapter);
4151 hdd_wmm_adapter_close(pAdapter);
4152
4153 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4154 pAdapterNode = pNext;
4155 }
4156
4157 EXIT();
4158
4159 return VOS_STATUS_SUCCESS;
4160}
4161
4162VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4163{
4164 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4165 VOS_STATUS status;
4166 hdd_adapter_t *pAdapter;
4167 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304168 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004169
4170 ENTER();
4171
4172 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4173
4174 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4175 {
4176 pAdapter = pAdapterNode->pAdapter;
4177
4178 switch(pAdapter->device_mode)
4179 {
4180 case WLAN_HDD_INFRA_STATION:
4181 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004182 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304183
4184 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4185
Jeff Johnson295189b2012-06-20 16:38:30 -07004186 hdd_init_station_mode(pAdapter);
4187 /* Open the gates for HDD to receive Wext commands */
4188 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004189 pHddCtx->scan_info.mScanPending = FALSE;
4190 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004191
4192 //Trigger the initial scan
4193 hdd_wlan_initial_scan(pAdapter);
4194
4195 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304196 if (eConnectionState_Associated == connState ||
4197 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 {
4199 union iwreq_data wrqu;
4200 memset(&wrqu, '\0', sizeof(wrqu));
4201 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4202 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4203 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004204
Jeff Johnson295189b2012-06-20 16:38:30 -07004205 /* indicate disconnected event to nl80211 */
4206 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4207 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004208 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304209 else if (eConnectionState_Connecting == connState)
4210 {
4211 /*
4212 * Indicate connect failure to supplicant if we were in the
4213 * process of connecting
4214 */
4215 cfg80211_connect_result(pAdapter->dev, NULL,
4216 NULL, 0, NULL, 0,
4217 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4218 GFP_KERNEL);
4219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 break;
4221
4222 case WLAN_HDD_SOFTAP:
4223 /* softAP can handle SSR */
4224 break;
4225
4226 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4228 __func__);
4229 /* event supplicant to restart */
4230 cfg80211_del_sta(pAdapter->dev,
4231 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 break;
4233
4234 case WLAN_HDD_MONITOR:
4235 /* monitor interface start */
4236 break;
4237 default:
4238 break;
4239 }
4240
4241 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4242 pAdapterNode = pNext;
4243 }
4244
4245 EXIT();
4246
4247 return VOS_STATUS_SUCCESS;
4248}
4249
4250VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4251{
4252 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4253 hdd_adapter_t *pAdapter;
4254 VOS_STATUS status;
4255 v_U32_t roamId;
4256
4257 ENTER();
4258
4259 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4260
4261 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4262 {
4263 pAdapter = pAdapterNode->pAdapter;
4264
4265 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4266 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4267 {
4268 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4269 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4270
4271 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4272 init_completion(&pAdapter->disconnect_comp_var);
4273 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4274 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4275
4276 wait_for_completion_interruptible_timeout(
4277 &pAdapter->disconnect_comp_var,
4278 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4279
4280 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4281 pHddCtx->isAmpAllowed = VOS_FALSE;
4282 sme_RoamConnect(pHddCtx->hHal,
4283 pAdapter->sessionId, &(pWextState->roamProfile),
4284 &roamId);
4285 }
4286
4287 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4288 pAdapterNode = pNext;
4289 }
4290
4291 EXIT();
4292
4293 return VOS_STATUS_SUCCESS;
4294}
4295
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004296void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4297{
4298 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4299 VOS_STATUS status;
4300 hdd_adapter_t *pAdapter;
4301 hdd_station_ctx_t *pHddStaCtx;
4302 hdd_ap_ctx_t *pHddApCtx;
4303 hdd_hostapd_state_t * pHostapdState;
4304 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4305 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4306 const char *p2pMode = "DEV";
4307 const char *ccMode = "Standalone";
4308 int n;
4309
4310 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4311 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4312 {
4313 pAdapter = pAdapterNode->pAdapter;
4314 switch (pAdapter->device_mode) {
4315 case WLAN_HDD_INFRA_STATION:
4316 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4317 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4318 staChannel = pHddStaCtx->conn_info.operationChannel;
4319 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4320 }
4321 break;
4322 case WLAN_HDD_P2P_CLIENT:
4323 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4324 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4325 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4326 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4327 p2pMode = "CLI";
4328 }
4329 break;
4330 case WLAN_HDD_P2P_GO:
4331 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4332 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4333 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4334 p2pChannel = pHddApCtx->operatingChannel;
4335 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4336 }
4337 p2pMode = "GO";
4338 break;
4339 case WLAN_HDD_SOFTAP:
4340 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4341 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4342 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4343 apChannel = pHddApCtx->operatingChannel;
4344 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4345 }
4346 break;
4347 default:
4348 break;
4349 }
4350 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4351 pAdapterNode = pNext;
4352 }
4353 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4354 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4355 }
4356 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4357 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4358 if (p2pChannel > 0) {
4359 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4360 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4361 }
4362 if (apChannel > 0) {
4363 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4364 apChannel, MAC_ADDR_ARRAY(apBssid));
4365 }
4366
4367 if (p2pChannel > 0 && apChannel > 0) {
4368 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4369 }
4370}
4371
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004372bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004373{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004374 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004375}
4376
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004377/* Once SSR is disabled then it cannot be set. */
4378void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004379{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004380 if (HDD_SSR_DISABLED == isSsrRequired)
4381 return;
4382
Jeff Johnson295189b2012-06-20 16:38:30 -07004383 isSsrRequired = value;
4384}
4385
4386VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4387 hdd_adapter_list_node_t** ppAdapterNode)
4388{
4389 VOS_STATUS status;
4390 spin_lock(&pHddCtx->hddAdapters.lock);
4391 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4392 (hdd_list_node_t**) ppAdapterNode );
4393 spin_unlock(&pHddCtx->hddAdapters.lock);
4394 return status;
4395}
4396
4397VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4398 hdd_adapter_list_node_t* pAdapterNode,
4399 hdd_adapter_list_node_t** pNextAdapterNode)
4400{
4401 VOS_STATUS status;
4402 spin_lock(&pHddCtx->hddAdapters.lock);
4403 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4404 (hdd_list_node_t*) pAdapterNode,
4405 (hdd_list_node_t**)pNextAdapterNode );
4406
4407 spin_unlock(&pHddCtx->hddAdapters.lock);
4408 return status;
4409}
4410
4411VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4412 hdd_adapter_list_node_t* pAdapterNode)
4413{
4414 VOS_STATUS status;
4415 spin_lock(&pHddCtx->hddAdapters.lock);
4416 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4417 &pAdapterNode->node );
4418 spin_unlock(&pHddCtx->hddAdapters.lock);
4419 return status;
4420}
4421
4422VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4423 hdd_adapter_list_node_t** ppAdapterNode)
4424{
4425 VOS_STATUS status;
4426 spin_lock(&pHddCtx->hddAdapters.lock);
4427 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4428 (hdd_list_node_t**) ppAdapterNode );
4429 spin_unlock(&pHddCtx->hddAdapters.lock);
4430 return status;
4431}
4432
4433VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4434 hdd_adapter_list_node_t* pAdapterNode)
4435{
4436 VOS_STATUS status;
4437 spin_lock(&pHddCtx->hddAdapters.lock);
4438 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4439 (hdd_list_node_t*) pAdapterNode );
4440 spin_unlock(&pHddCtx->hddAdapters.lock);
4441 return status;
4442}
4443
4444VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4445 hdd_adapter_list_node_t* pAdapterNode)
4446{
4447 VOS_STATUS status;
4448 spin_lock(&pHddCtx->hddAdapters.lock);
4449 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4450 (hdd_list_node_t*) pAdapterNode );
4451 spin_unlock(&pHddCtx->hddAdapters.lock);
4452 return status;
4453}
4454
4455hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4456 tSirMacAddr macAddr )
4457{
4458 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4459 hdd_adapter_t *pAdapter;
4460 VOS_STATUS status;
4461
4462 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4463
4464 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4465 {
4466 pAdapter = pAdapterNode->pAdapter;
4467
4468 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4469 macAddr, sizeof(tSirMacAddr) ) )
4470 {
4471 return pAdapter;
4472 }
4473 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4474 pAdapterNode = pNext;
4475 }
4476
4477 return NULL;
4478
4479}
4480
4481hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4482{
4483 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4484 hdd_adapter_t *pAdapter;
4485 VOS_STATUS status;
4486
4487 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4488
4489 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4490 {
4491 pAdapter = pAdapterNode->pAdapter;
4492
4493 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4494 IFNAMSIZ ) )
4495 {
4496 return pAdapter;
4497 }
4498 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4499 pAdapterNode = pNext;
4500 }
4501
4502 return NULL;
4503
4504}
4505
4506hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4507{
4508 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4509 hdd_adapter_t *pAdapter;
4510 VOS_STATUS status;
4511
4512 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4513
4514 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4515 {
4516 pAdapter = pAdapterNode->pAdapter;
4517
4518 if( pAdapter && (mode == pAdapter->device_mode) )
4519 {
4520 return pAdapter;
4521 }
4522 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4523 pAdapterNode = pNext;
4524 }
4525
4526 return NULL;
4527
4528}
4529
4530//Remove this function later
4531hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4532{
4533 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4534 hdd_adapter_t *pAdapter;
4535 VOS_STATUS status;
4536
4537 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4538
4539 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4540 {
4541 pAdapter = pAdapterNode->pAdapter;
4542
4543 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4544 {
4545 return pAdapter;
4546 }
4547
4548 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4549 pAdapterNode = pNext;
4550 }
4551
4552 return NULL;
4553
4554}
4555
Jeff Johnson295189b2012-06-20 16:38:30 -07004556/**---------------------------------------------------------------------------
4557
4558 \brief hdd_set_monitor_tx_adapter() -
4559
4560 This API initializes the adapter to be used while transmitting on monitor
4561 adapter.
4562
4563 \param - pHddCtx - Pointer to the HDD context.
4564 pAdapter - Adapter that will used for TX. This can be NULL.
4565 \return - None.
4566 --------------------------------------------------------------------------*/
4567void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4568{
4569 hdd_adapter_t *pMonAdapter;
4570
4571 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4572
4573 if( NULL != pMonAdapter )
4574 {
4575 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4576 }
4577}
Jeff Johnson295189b2012-06-20 16:38:30 -07004578/**---------------------------------------------------------------------------
4579
4580 \brief hdd_select_queue() -
4581
4582 This API returns the operating channel of the requested device mode
4583
4584 \param - pHddCtx - Pointer to the HDD context.
4585 - mode - Device mode for which operating channel is required
4586 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4587 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4588 \return - channel number. "0" id the requested device is not found OR it is not connected.
4589 --------------------------------------------------------------------------*/
4590v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4591{
4592 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4593 VOS_STATUS status;
4594 hdd_adapter_t *pAdapter;
4595 v_U8_t operatingChannel = 0;
4596
4597 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4598
4599 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4600 {
4601 pAdapter = pAdapterNode->pAdapter;
4602
4603 if( mode == pAdapter->device_mode )
4604 {
4605 switch(pAdapter->device_mode)
4606 {
4607 case WLAN_HDD_INFRA_STATION:
4608 case WLAN_HDD_P2P_CLIENT:
4609 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4610 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4611 break;
4612 case WLAN_HDD_SOFTAP:
4613 case WLAN_HDD_P2P_GO:
4614 /*softap connection info */
4615 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4616 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4617 break;
4618 default:
4619 break;
4620 }
4621
4622 break; //Found the device of interest. break the loop
4623 }
4624
4625 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4626 pAdapterNode = pNext;
4627 }
4628 return operatingChannel;
4629}
4630
4631#ifdef WLAN_FEATURE_PACKET_FILTERING
4632/**---------------------------------------------------------------------------
4633
4634 \brief hdd_set_multicast_list() -
4635
4636 This used to set the multicast address list.
4637
4638 \param - dev - Pointer to the WLAN device.
4639 - skb - Pointer to OS packet (sk_buff).
4640 \return - success/fail
4641
4642 --------------------------------------------------------------------------*/
4643static void hdd_set_multicast_list(struct net_device *dev)
4644{
4645 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 int mc_count;
4647 int i = 0;
4648 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304649
4650 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004651 {
4652 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304653 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 return;
4655 }
4656
4657 if (dev->flags & IFF_ALLMULTI)
4658 {
4659 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004660 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304661 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004662 }
4663 else
4664 {
4665 mc_count = netdev_mc_count(dev);
4666 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004667 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4669 {
4670 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004671 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304672 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004673 return;
4674 }
4675
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304676 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004677
4678 netdev_for_each_mc_addr(ha, dev) {
4679 if (i == mc_count)
4680 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304681 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4682 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4683 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304685 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004686 i++;
4687 }
4688 }
4689 return;
4690}
4691#endif
4692
4693/**---------------------------------------------------------------------------
4694
4695 \brief hdd_select_queue() -
4696
4697 This function is registered with the Linux OS for network
4698 core to decide which queue to use first.
4699
4700 \param - dev - Pointer to the WLAN device.
4701 - skb - Pointer to OS packet (sk_buff).
4702 \return - ac, Queue Index/access category corresponding to UP in IP header
4703
4704 --------------------------------------------------------------------------*/
4705v_U16_t hdd_select_queue(struct net_device *dev,
4706 struct sk_buff *skb)
4707{
4708 return hdd_wmm_select_queue(dev, skb);
4709}
4710
4711
4712/**---------------------------------------------------------------------------
4713
4714 \brief hdd_wlan_initial_scan() -
4715
4716 This function triggers the initial scan
4717
4718 \param - pAdapter - Pointer to the HDD adapter.
4719
4720 --------------------------------------------------------------------------*/
4721void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4722{
4723 tCsrScanRequest scanReq;
4724 tCsrChannelInfo channelInfo;
4725 eHalStatus halStatus;
4726 unsigned long scanId;
4727 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4728
4729 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4730 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4731 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4732
4733 if(sme_Is11dSupported(pHddCtx->hHal))
4734 {
4735 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4736 if ( HAL_STATUS_SUCCESS( halStatus ) )
4737 {
4738 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4739 if( !scanReq.ChannelInfo.ChannelList )
4740 {
4741 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4742 vos_mem_free(channelInfo.ChannelList);
4743 return;
4744 }
4745 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4746 channelInfo.numOfChannels);
4747 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4748 vos_mem_free(channelInfo.ChannelList);
4749 }
4750
4751 scanReq.scanType = eSIR_PASSIVE_SCAN;
4752 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4753 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4754 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4755 }
4756 else
4757 {
4758 scanReq.scanType = eSIR_ACTIVE_SCAN;
4759 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4760 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4761 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4762 }
4763
4764 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4765 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4766 {
4767 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4768 __func__, halStatus );
4769 }
4770
4771 if(sme_Is11dSupported(pHddCtx->hHal))
4772 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4773}
4774
4775struct fullPowerContext
4776{
4777 struct completion completion;
4778 unsigned int magic;
4779};
4780#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4781
4782/**---------------------------------------------------------------------------
4783
4784 \brief hdd_full_power_callback() - HDD full power callback function
4785
4786 This is the function invoked by SME to inform the result of a full power
4787 request issued by HDD
4788
4789 \param - callbackcontext - Pointer to cookie
4790 \param - status - result of request
4791
4792 \return - None
4793
4794 --------------------------------------------------------------------------*/
4795static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4796{
4797 struct fullPowerContext *pContext = callbackContext;
4798
4799 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304800 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004801
4802 if (NULL == callbackContext)
4803 {
4804 hddLog(VOS_TRACE_LEVEL_ERROR,
4805 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004806 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 return;
4808 }
4809
4810 /* there is a race condition that exists between this callback function
4811 and the caller since the caller could time out either before or
4812 while this code is executing. we'll assume the timeout hasn't
4813 occurred, but we'll verify that right before we save our work */
4814
4815 if (POWER_CONTEXT_MAGIC != pContext->magic)
4816 {
4817 /* the caller presumably timed out so there is nothing we can do */
4818 hddLog(VOS_TRACE_LEVEL_WARN,
4819 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004820 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 return;
4822 }
4823
4824 /* the race is on. caller could have timed out immediately after
4825 we verified the magic, but if so, caller will wait a short time
4826 for us to notify the caller, so the context will stay valid */
4827 complete(&pContext->completion);
4828}
4829
4830/**---------------------------------------------------------------------------
4831
4832 \brief hdd_wlan_exit() - HDD WLAN exit function
4833
4834 This is the driver exit point (invoked during rmmod)
4835
4836 \param - pHddCtx - Pointer to the HDD Context
4837
4838 \return - None
4839
4840 --------------------------------------------------------------------------*/
4841void hdd_wlan_exit(hdd_context_t *pHddCtx)
4842{
4843 eHalStatus halStatus;
4844 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4845 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304846 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004848 struct fullPowerContext powerContext;
4849 long lrc;
4850
4851 ENTER();
4852
Jeff Johnson88ba7742013-02-27 14:36:02 -08004853 if (VOS_FTM_MODE != hdd_get_conparam())
4854 {
4855 // Unloading, restart logic is no more required.
4856 wlan_hdd_restart_deinit(pHddCtx);
4857 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004858
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 {
4863 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4864 WLAN_HDD_INFRA_STATION);
4865 if (pAdapter == NULL)
4866 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4867
4868 if (pAdapter != NULL)
4869 {
4870 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4871 hdd_UnregisterWext(pAdapter->dev);
4872 }
4873 }
4874 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004877 {
4878 wlan_hdd_ftm_close(pHddCtx);
4879 goto free_hdd_ctx;
4880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 //Stop the Interface TX queue.
4882 //netif_tx_disable(pWlanDev);
4883 //netif_carrier_off(pWlanDev);
4884
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4886 {
4887 pAdapter = hdd_get_adapter(pHddCtx,
4888 WLAN_HDD_SOFTAP);
4889 }
4890 else
4891 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 {
4894 pAdapter = hdd_get_adapter(pHddCtx,
4895 WLAN_HDD_INFRA_STATION);
4896 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 /* DeRegister with platform driver as client for Suspend/Resume */
4899 vosStatus = hddDeregisterPmOps(pHddCtx);
4900 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4901 {
4902 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4903 VOS_ASSERT(0);
4904 }
4905
4906 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4907 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4908 {
4909 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
4912 // Cancel any outstanding scan requests. We are about to close all
4913 // of our adapters, but an adapter structure is what SME passes back
4914 // to our callback function. Hence if there are any outstanding scan
4915 // requests then there is a race condition between when the adapter
4916 // is closed and when the callback is invoked. We try to resolve that
4917 // race condition here by canceling any outstanding scans before we
4918 // close the adapters.
4919 // Note that the scans may be cancelled in an asynchronous manner, so
4920 // ideally there needs to be some kind of synchronization. Rather than
4921 // introduce a new synchronization here, we will utilize the fact that
4922 // we are about to Request Full Power, and since that is synchronized,
4923 // the expectation is that by the time Request Full Power has completed,
4924 // all scans will be cancelled.
4925 hdd_abort_mac_scan( pHddCtx );
4926
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304927 //Stop the timer if already running
4928 if (VOS_TIMER_STATE_RUNNING ==
4929 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4930 {
4931 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4932 }
4933
4934 // Destroy hdd_p2p_go_conn_is_in_progress timer
4935 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4936 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4937 {
4938 hddLog(VOS_TRACE_LEVEL_ERROR,
4939 "%s: Cannot deallocate p2p connection timer", __func__);
4940 }
4941
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 //Disable IMPS/BMPS as we do not want the device to enter any power
4943 //save mode during shutdown
4944 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4945 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4946 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4947
4948 //Ensure that device is in full power as we will touch H/W during vos_Stop
4949 init_completion(&powerContext.completion);
4950 powerContext.magic = POWER_CONTEXT_MAGIC;
4951
4952 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4953 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4954
4955 if (eHAL_STATUS_SUCCESS != halStatus)
4956 {
4957 if (eHAL_STATUS_PMC_PENDING == halStatus)
4958 {
4959 /* request was sent -- wait for the response */
4960 lrc = wait_for_completion_interruptible_timeout(
4961 &powerContext.completion,
4962 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4963 /* either we have a response or we timed out
4964 either way, first invalidate our magic */
4965 powerContext.magic = 0;
4966 if (lrc <= 0)
4967 {
4968 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004969 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004970 /* there is a race condition such that the callback
4971 function could be executing at the same time we are. of
4972 primary concern is if the callback function had already
4973 verified the "magic" but hasn't yet set the completion
4974 variable. Since the completion variable is on our
4975 stack, we'll delay just a bit to make sure the data is
4976 still valid if that is the case */
4977 msleep(50);
4978 }
4979 }
4980 else
4981 {
4982 hddLog(VOS_TRACE_LEVEL_ERROR,
4983 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004984 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 VOS_ASSERT(0);
4986 /* continue -- need to clean up as much as possible */
4987 }
4988 }
4989
4990 // Unregister the Net Device Notifier
4991 unregister_netdevice_notifier(&hdd_netdev_notifier);
4992
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 hdd_stop_all_adapters( pHddCtx );
4994
Jeff Johnson295189b2012-06-20 16:38:30 -07004995#ifdef WLAN_BTAMP_FEATURE
4996 vosStatus = WLANBAP_Stop(pVosContext);
4997 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4998 {
4999 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5000 "%s: Failed to stop BAP",__func__);
5001 }
5002#endif //WLAN_BTAMP_FEATURE
5003
5004 //Stop all the modules
5005 vosStatus = vos_stop( pVosContext );
5006 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5007 {
5008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5009 "%s: Failed to stop VOSS",__func__);
5010 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5011 }
5012
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 //Assert Deep sleep signal now to put Libra HW in lowest power state
5014 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5015 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5016
5017 //Vote off any PMIC voltage supplies
5018 vos_chipPowerDown(NULL, NULL, NULL);
5019
5020 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5021
Jeff Johnson295189b2012-06-20 16:38:30 -07005022 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005023 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005024
5025 //Close the scheduler before calling vos_close to make sure no thread is
5026 // scheduled after the each module close is called i.e after all the data
5027 // structures are freed.
5028 vosStatus = vos_sched_close( pVosContext );
5029 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5030 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5031 "%s: Failed to close VOSS Scheduler",__func__);
5032 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5033 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005034#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005035#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5036 /* Destroy the wake lock */
5037 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5038#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005039 /* Destroy the wake lock */
5040 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005041#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005042
5043 //Close VOSS
5044 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5045 vos_close(pVosContext);
5046
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 //Close Watchdog
5048 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5049 vos_watchdog_close(pVosContext);
5050
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305051 //Clean up HDD Nlink Service
5052 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5053 nl_srv_exit();
5054
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 /* Cancel the vote for XO Core ON.
5056 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5057 * exited at this point
5058 */
5059 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5060 " when WLAN is turned OFF\n");
5061 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5062 {
5063 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5064 " Not returning failure."
5065 " Power consumed will be high\n");
5066 }
5067
5068 hdd_close_all_adapters( pHddCtx );
5069
5070
5071 //Free up dynamically allocated members inside HDD Adapter
5072 kfree(pHddCtx->cfg_ini);
5073 pHddCtx->cfg_ini= NULL;
5074
5075 /* free the power on lock from platform driver */
5076 if (free_riva_power_on_lock("wlan"))
5077 {
5078 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5079 __func__);
5080 }
5081
Jeff Johnson88ba7742013-02-27 14:36:02 -08005082free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005083 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005085 if (hdd_is_ssr_required())
5086 {
5087 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005088 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005089 msleep(5000);
5090 }
5091 hdd_set_ssr_required (VOS_FALSE);
5092}
5093
5094
5095/**---------------------------------------------------------------------------
5096
5097 \brief hdd_update_config_from_nv() - Function to update the contents of
5098 the running configuration with parameters taken from NV storage
5099
5100 \param - pHddCtx - Pointer to the HDD global context
5101
5102 \return - VOS_STATUS_SUCCESS if successful
5103
5104 --------------------------------------------------------------------------*/
5105static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5106{
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 v_BOOL_t itemIsValid = VOS_FALSE;
5108 VOS_STATUS status;
5109 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5110 v_U8_t macLoop;
5111
5112 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5113 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5114 if(status != VOS_STATUS_SUCCESS)
5115 {
5116 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5117 return VOS_STATUS_E_FAILURE;
5118 }
5119
5120 if (itemIsValid == VOS_TRUE)
5121 {
5122 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5123 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5124 VOS_MAX_CONCURRENCY_PERSONA);
5125 if(status != VOS_STATUS_SUCCESS)
5126 {
5127 /* Get MAC from NV fail, not update CFG info
5128 * INI MAC value will be used for MAC setting */
5129 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5130 return VOS_STATUS_E_FAILURE;
5131 }
5132
5133 /* If first MAC is not valid, treat all others are not valid
5134 * Then all MACs will be got from ini file */
5135 if(vos_is_macaddr_zero(&macFromNV[0]))
5136 {
5137 /* MAC address in NV file is not configured yet */
5138 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5139 return VOS_STATUS_E_INVAL;
5140 }
5141
5142 /* Get MAC address from NV, update CFG info */
5143 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5144 {
5145 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5146 {
5147 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5148 /* This MAC is not valid, skip it
5149 * This MAC will be got from ini file */
5150 }
5151 else
5152 {
5153 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5154 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5155 VOS_MAC_ADDR_SIZE);
5156 }
5157 }
5158 }
5159 else
5160 {
5161 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5162 return VOS_STATUS_E_FAILURE;
5163 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005164
Jeff Johnson295189b2012-06-20 16:38:30 -07005165
5166 return VOS_STATUS_SUCCESS;
5167}
5168
5169/**---------------------------------------------------------------------------
5170
5171 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5172
5173 \param - pAdapter - Pointer to the HDD
5174
5175 \return - None
5176
5177 --------------------------------------------------------------------------*/
5178VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5179{
5180 eHalStatus halStatus;
5181 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305182 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005183
Jeff Johnson295189b2012-06-20 16:38:30 -07005184
5185 // Send ready indication to the HDD. This will kick off the MAC
5186 // into a 'running' state and should kick off an initial scan.
5187 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5188 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5189 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305190 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 "code %08d [x%08x]",__func__, halStatus, halStatus );
5192 return VOS_STATUS_E_FAILURE;
5193 }
5194
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305195 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5197 // And RIVA will crash
5198 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5199 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305200 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5201 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5202
5203
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 return VOS_STATUS_SUCCESS;
5205}
5206
Jeff Johnson295189b2012-06-20 16:38:30 -07005207/* wake lock APIs for HDD */
5208void hdd_prevent_suspend(void)
5209{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005210#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005212#else
5213 wcnss_prevent_suspend();
5214#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005215}
5216
5217void hdd_allow_suspend(void)
5218{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005219#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005221#else
5222 wcnss_allow_suspend();
5223#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005224}
5225
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005226void hdd_allow_suspend_timeout(v_U32_t timeout)
5227{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005228#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005229 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005230#else
5231 /* Do nothing as there is no API in wcnss for timeout*/
5232#endif
5233}
5234
Jeff Johnson295189b2012-06-20 16:38:30 -07005235/**---------------------------------------------------------------------------
5236
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005237 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5238 information between Host and Riva
5239
5240 This function gets reported version of FW
5241 It also finds the version of Riva headers used to compile the host
5242 It compares the above two and prints a warning if they are different
5243 It gets the SW and HW version string
5244 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5245 indicating the features they support through a bitmap
5246
5247 \param - pHddCtx - Pointer to HDD context
5248
5249 \return - void
5250
5251 --------------------------------------------------------------------------*/
5252
5253void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5254{
5255
5256 tSirVersionType versionCompiled;
5257 tSirVersionType versionReported;
5258 tSirVersionString versionString;
5259 tANI_U8 fwFeatCapsMsgSupported = 0;
5260 VOS_STATUS vstatus;
5261
5262 /* retrieve and display WCNSS version information */
5263 do {
5264
5265 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5266 &versionCompiled);
5267 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5268 {
5269 hddLog(VOS_TRACE_LEVEL_FATAL,
5270 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005271 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005272 break;
5273 }
5274
5275 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5276 &versionReported);
5277 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5278 {
5279 hddLog(VOS_TRACE_LEVEL_FATAL,
5280 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005281 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005282 break;
5283 }
5284
5285 if ((versionCompiled.major != versionReported.major) ||
5286 (versionCompiled.minor != versionReported.minor) ||
5287 (versionCompiled.version != versionReported.version) ||
5288 (versionCompiled.revision != versionReported.revision))
5289 {
5290 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5291 "Host expected %u.%u.%u.%u\n",
5292 WLAN_MODULE_NAME,
5293 (int)versionReported.major,
5294 (int)versionReported.minor,
5295 (int)versionReported.version,
5296 (int)versionReported.revision,
5297 (int)versionCompiled.major,
5298 (int)versionCompiled.minor,
5299 (int)versionCompiled.version,
5300 (int)versionCompiled.revision);
5301 }
5302 else
5303 {
5304 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5305 WLAN_MODULE_NAME,
5306 (int)versionReported.major,
5307 (int)versionReported.minor,
5308 (int)versionReported.version,
5309 (int)versionReported.revision);
5310 }
5311
5312 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5313 versionString,
5314 sizeof(versionString));
5315 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5316 {
5317 hddLog(VOS_TRACE_LEVEL_FATAL,
5318 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005319 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005320 break;
5321 }
5322
5323 pr_info("%s: WCNSS software version %s\n",
5324 WLAN_MODULE_NAME, versionString);
5325
5326 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5327 versionString,
5328 sizeof(versionString));
5329 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5330 {
5331 hddLog(VOS_TRACE_LEVEL_FATAL,
5332 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005333 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005334 break;
5335 }
5336
5337 pr_info("%s: WCNSS hardware version %s\n",
5338 WLAN_MODULE_NAME, versionString);
5339
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005340 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5341 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005342 send the message only if it the riva is 1.1
5343 minor numbers for different riva branches:
5344 0 -> (1.0)Mainline Build
5345 1 -> (1.1)Mainline Build
5346 2->(1.04) Stability Build
5347 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005348 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005349 ((versionReported.minor>=1) && (versionReported.version>=1)))
5350 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5351 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005352
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005353 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005354 {
5355#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5356 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5357 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5358#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005359 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005360 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005361
5362 } while (0);
5363
5364}
5365
5366/**---------------------------------------------------------------------------
5367
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305368 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5369
5370 \param - pHddCtx - Pointer to the hdd context
5371
5372 \return - true if hardware supports 5GHz
5373
5374 --------------------------------------------------------------------------*/
5375static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5376{
5377 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5378 * then hardware support 5Ghz.
5379 */
5380 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5381 {
5382 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5383 return true;
5384 }
5385 else
5386 {
5387 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5388 __func__);
5389 return false;
5390 }
5391}
5392
5393
5394/**---------------------------------------------------------------------------
5395
Jeff Johnson295189b2012-06-20 16:38:30 -07005396 \brief hdd_wlan_startup() - HDD init function
5397
5398 This is the driver startup code executed once a WLAN device has been detected
5399
5400 \param - dev - Pointer to the underlying device
5401
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005402 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005403
5404 --------------------------------------------------------------------------*/
5405
5406int hdd_wlan_startup(struct device *dev )
5407{
5408 VOS_STATUS status;
5409 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005410 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 hdd_context_t *pHddCtx = NULL;
5412 v_CONTEXT_t pVosContext= NULL;
5413#ifdef WLAN_BTAMP_FEATURE
5414 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5415 WLANBAP_ConfigType btAmpConfig;
5416 hdd_config_t *pConfig;
5417#endif
5418 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005420
5421 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 /*
5423 * cfg80211: wiphy allocation
5424 */
5425 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5426
5427 if(wiphy == NULL)
5428 {
5429 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005430 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005431 }
5432
5433 pHddCtx = wiphy_priv(wiphy);
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 //Initialize the adapter context to zeros.
5436 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5437
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 hdd_prevent_suspend();
5440 pHddCtx->isLoadUnloadInProgress = TRUE;
5441
5442 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5443
5444 /*Get vos context here bcoz vos_open requires it*/
5445 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5446
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005447 if(pVosContext == NULL)
5448 {
5449 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5450 goto err_free_hdd_context;
5451 }
5452
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 //Save the Global VOSS context in adapter context for future.
5454 pHddCtx->pvosContext = pVosContext;
5455
5456 //Save the adapter context in global context for future.
5457 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5458
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 pHddCtx->parent_dev = dev;
5460
5461 init_completion(&pHddCtx->full_pwr_comp_var);
5462 init_completion(&pHddCtx->standby_comp_var);
5463 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005464 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005465 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005466
5467 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5468
5469 // Load all config first as TL config is needed during vos_open
5470 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5471 if(pHddCtx->cfg_ini == NULL)
5472 {
5473 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5474 goto err_free_hdd_context;
5475 }
5476
5477 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5478
5479 // Read and parse the qcom_cfg.ini file
5480 status = hdd_parse_config_ini( pHddCtx );
5481 if ( VOS_STATUS_SUCCESS != status )
5482 {
5483 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5484 __func__, WLAN_INI_FILE);
5485 goto err_config;
5486 }
5487
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305488 /* INI has been read, initialise the configuredMcastBcastFilter with
5489 * INI value as this will serve as the default value
5490 */
5491 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5492 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5493 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305494
5495 if (false == hdd_is_5g_supported(pHddCtx))
5496 {
5497 //5Ghz is not supported.
5498 if (1 != pHddCtx->cfg_ini->nBandCapability)
5499 {
5500 hddLog(VOS_TRACE_LEVEL_INFO,
5501 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5502 pHddCtx->cfg_ini->nBandCapability = 1;
5503 }
5504 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005505 /*
5506 * cfg80211: Initialization and registration ...
5507 */
5508 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5509 {
5510 hddLog(VOS_TRACE_LEVEL_FATAL,
5511 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5512 goto err_wiphy_reg;
5513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005514
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005515 // Update VOS trace levels based upon the cfg.ini
5516 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5517 pHddCtx->cfg_ini->vosTraceEnableBAP);
5518 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5519 pHddCtx->cfg_ini->vosTraceEnableTL);
5520 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5521 pHddCtx->cfg_ini->vosTraceEnableWDI);
5522 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5523 pHddCtx->cfg_ini->vosTraceEnableHDD);
5524 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5525 pHddCtx->cfg_ini->vosTraceEnableSME);
5526 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5527 pHddCtx->cfg_ini->vosTraceEnablePE);
5528 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5529 pHddCtx->cfg_ini->vosTraceEnableWDA);
5530 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5531 pHddCtx->cfg_ini->vosTraceEnableSYS);
5532 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5533 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005534 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5535 pHddCtx->cfg_ini->vosTraceEnableSAP);
5536 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5537 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005538
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 // Update WDI trace levels based upon the cfg.ini
5540 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5541 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5542 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5543 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5544 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5545 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5546 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5547 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005548
Jeff Johnson88ba7742013-02-27 14:36:02 -08005549 if (VOS_FTM_MODE == hdd_get_conparam())
5550 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5552 {
5553 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5554 goto err_free_hdd_context;
5555 }
5556 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5557 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005558 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005559
Jeff Johnson88ba7742013-02-27 14:36:02 -08005560 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5562 {
5563 status = vos_watchdog_open(pVosContext,
5564 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5565
5566 if(!VOS_IS_STATUS_SUCCESS( status ))
5567 {
5568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 }
5571 }
5572
5573 pHddCtx->isLogpInProgress = FALSE;
5574 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5575
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5577 if(!VOS_IS_STATUS_SUCCESS(status))
5578 {
5579 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005581 }
5582
Jeff Johnson295189b2012-06-20 16:38:30 -07005583 status = vos_open( &pVosContext, 0);
5584 if ( !VOS_IS_STATUS_SUCCESS( status ))
5585 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005586 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5587 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 }
5589
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5591
5592 if ( NULL == pHddCtx->hHal )
5593 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005594 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005595 goto err_vosclose;
5596 }
5597
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005598 status = vos_preStart( pHddCtx->pvosContext );
5599 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5600 {
5601 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5602 goto err_vosclose;
5603 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005604
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005605 /* Note that the vos_preStart() sequence triggers the cfg download.
5606 The cfg download must occur before we update the SME config
5607 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 status = hdd_set_sme_config( pHddCtx );
5609
5610 if ( VOS_STATUS_SUCCESS != status )
5611 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005612 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5613 goto err_vosclose;
5614 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005615
5616 //Initialize the WMM module
5617 status = hdd_wmm_init(pHddCtx);
5618 if (!VOS_IS_STATUS_SUCCESS(status))
5619 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005620 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 goto err_vosclose;
5622 }
5623
Jeff Johnson295189b2012-06-20 16:38:30 -07005624 /* In the integrated architecture we update the configuration from
5625 the INI file and from NV before vOSS has been started so that
5626 the final contents are available to send down to the cCPU */
5627
5628 // Apply the cfg.ini to cfg.dat
5629 if (FALSE == hdd_update_config_dat(pHddCtx))
5630 {
5631 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5632 goto err_vosclose;
5633 }
5634
5635 // Apply the NV to cfg.dat
5636 /* Prima Update MAC address only at here */
5637 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5638 {
5639#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5640 /* There was not a valid set of MAC Addresses in NV. See if the
5641 default addresses were modified by the cfg.ini settings. If so,
5642 we'll use them, but if not, we'll autogenerate a set of MAC
5643 addresses based upon the device serial number */
5644
5645 static const v_MACADDR_t default_address =
5646 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5647 unsigned int serialno;
5648 int i;
5649
5650 serialno = wcnss_get_serial_number();
5651 if ((0 != serialno) &&
5652 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5653 sizeof(default_address))))
5654 {
5655 /* cfg.ini has the default address, invoke autogen logic */
5656
5657 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5658 bytes of the serial number that can be used to generate
5659 the other 3 bytes of the MAC address. Mask off all but
5660 the lower 3 bytes (this will also make sure we don't
5661 overflow in the next step) */
5662 serialno &= 0x00FFFFFF;
5663
5664 /* we need a unique address for each session */
5665 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5666
5667 /* autogen all addresses */
5668 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5669 {
5670 /* start with the entire default address */
5671 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5672 /* then replace the lower 3 bytes */
5673 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5674 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5675 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5676
5677 serialno++;
5678 }
5679
5680 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5681 MAC_ADDRESS_STR,
5682 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5683 }
5684 else
5685#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5686 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005687 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 "%s: Invalid MAC address in NV, using MAC from ini file "
5689 MAC_ADDRESS_STR, __func__,
5690 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5691 }
5692 }
5693 {
5694 eHalStatus halStatus;
5695 // Set the MAC Address
5696 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5697 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5698 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5699 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5700
5701 if (!HAL_STATUS_SUCCESS( halStatus ))
5702 {
5703 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5704 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005705 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 }
5707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005708
5709 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5710 Note: Firmware image will be read and downloaded inside vos_start API */
5711 status = vos_start( pHddCtx->pvosContext );
5712 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5713 {
5714 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5715 goto err_vosclose;
5716 }
5717
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005718 /* Exchange capability info between Host and FW and also get versioning info from FW */
5719 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005720
5721 status = hdd_post_voss_start_config( pHddCtx );
5722 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5723 {
5724 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5725 __func__);
5726 goto err_vosstop;
5727 }
5728
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5730 {
5731 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5732 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5733 }
5734 else
5735 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005736 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5737 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5738 if (pAdapter != NULL)
5739 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305740 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005741 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305742 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5743 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5744 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005745
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305746 /* Generate the P2P Device Address. This consists of the device's
5747 * primary MAC address with the locally administered bit set.
5748 */
5749 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005750 }
5751 else
5752 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305753 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5754 if (p2p_dev_addr != NULL)
5755 {
5756 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5757 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5758 }
5759 else
5760 {
5761 hddLog(VOS_TRACE_LEVEL_FATAL,
5762 "%s: Failed to allocate mac_address for p2p_device",
5763 __func__);
5764 goto err_close_adapter;
5765 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005767
5768 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5769 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5770 if ( NULL == pP2pAdapter )
5771 {
5772 hddLog(VOS_TRACE_LEVEL_FATAL,
5773 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005774 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005775 goto err_close_adapter;
5776 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005777 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005779
5780 if( pAdapter == NULL )
5781 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005782 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5783 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005785
Jeff Johnson295189b2012-06-20 16:38:30 -07005786#ifdef WLAN_BTAMP_FEATURE
5787 vStatus = WLANBAP_Open(pVosContext);
5788 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5789 {
5790 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5791 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005792 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 }
5794
5795 vStatus = BSL_Init(pVosContext);
5796 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5797 {
5798 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5799 "%s: Failed to Init BSL",__func__);
5800 goto err_bap_close;
5801 }
5802 vStatus = WLANBAP_Start(pVosContext);
5803 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5804 {
5805 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5806 "%s: Failed to start TL",__func__);
5807 goto err_bap_close;
5808 }
5809
5810 pConfig = pHddCtx->cfg_ini;
5811 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5812 status = WLANBAP_SetConfig(&btAmpConfig);
5813
5814#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005815
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005816#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5817 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5818 {
5819 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5820 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5821 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5822 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5823 }
5824#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005825#ifdef FEATURE_WLAN_SCAN_PNO
5826 /*SME must send channel update configuration to RIVA*/
5827 sme_UpdateChannelConfig(pHddCtx->hHal);
5828#endif
5829
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 /* Register with platform driver as client for Suspend/Resume */
5831 status = hddRegisterPmOps(pHddCtx);
5832 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5833 {
5834 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5835#ifdef WLAN_BTAMP_FEATURE
5836 goto err_bap_stop;
5837#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005838 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005839#endif //WLAN_BTAMP_FEATURE
5840 }
5841
5842 /* Register TM level change handler function to the platform */
5843 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5844 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5845 {
5846 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5847 goto err_unregister_pmops;
5848 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005849
5850 /* register for riva power on lock to platform driver */
5851 if (req_riva_power_on_lock("wlan"))
5852 {
5853 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5854 __func__);
5855 goto err_unregister_pmops;
5856 }
5857
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 // register net device notifier for device change notification
5859 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5860
5861 if(ret < 0)
5862 {
5863 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5864 goto err_free_power_on_lock;
5865 }
5866
5867 //Initialize the nlink service
5868 if(nl_srv_init() != 0)
5869 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 goto err_reg_netdev;
5872 }
5873
5874 //Initialize the BTC service
5875 if(btc_activate_service(pHddCtx) != 0)
5876 {
5877 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5878 goto err_nl_srv;
5879 }
5880
5881#ifdef PTT_SOCK_SVC_ENABLE
5882 //Initialize the PTT service
5883 if(ptt_sock_activate_svc(pHddCtx) != 0)
5884 {
5885 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5886 goto err_nl_srv;
5887 }
5888#endif
5889
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005892 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005893 /* Action frame registered in one adapter which will
5894 * applicable to all interfaces
5895 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005896 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005898
5899 mutex_init(&pHddCtx->sap_lock);
5900
5901 pHddCtx->isLoadUnloadInProgress = FALSE;
5902
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005903#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005904#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5905 /* Initialize the wake lcok */
5906 wake_lock_init(&pHddCtx->rx_wake_lock,
5907 WAKE_LOCK_SUSPEND,
5908 "qcom_rx_wakelock");
5909#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005910 /* Initialize the wake lcok */
5911 wake_lock_init(&pHddCtx->sap_wake_lock,
5912 WAKE_LOCK_SUSPEND,
5913 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005914#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005915
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005916 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5917 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005918
5919 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5920 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305921
Jeff Johnsone7245742012-09-05 17:12:55 -07005922 // Initialize the restart logic
5923 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305924
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305925 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5926 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5927 {
5928 hddLog(VOS_TRACE_LEVEL_ERROR,
5929 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5930 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005931 goto success;
5932
5933err_nl_srv:
5934 nl_srv_exit();
5935
5936err_reg_netdev:
5937 unregister_netdevice_notifier(&hdd_netdev_notifier);
5938
5939err_free_power_on_lock:
5940 free_riva_power_on_lock("wlan");
5941
5942err_unregister_pmops:
5943 hddDevTmUnregisterNotifyCallback(pHddCtx);
5944 hddDeregisterPmOps(pHddCtx);
5945
5946#ifdef WLAN_BTAMP_FEATURE
5947err_bap_stop:
5948 WLANBAP_Stop(pVosContext);
5949#endif
5950
5951#ifdef WLAN_BTAMP_FEATURE
5952err_bap_close:
5953 WLANBAP_Close(pVosContext);
5954#endif
5955
Jeff Johnson295189b2012-06-20 16:38:30 -07005956err_close_adapter:
5957 hdd_close_all_adapters( pHddCtx );
5958
5959err_vosstop:
5960 vos_stop(pVosContext);
5961
5962err_vosclose:
5963 status = vos_sched_close( pVosContext );
5964 if (!VOS_IS_STATUS_SUCCESS(status)) {
5965 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5966 "%s: Failed to close VOSS Scheduler", __func__);
5967 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5968 }
5969 vos_close(pVosContext );
5970
Jeff Johnson295189b2012-06-20 16:38:30 -07005971err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005972 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005973
5974err_wdclose:
5975 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5976 vos_watchdog_close(pVosContext);
5977
Jeff Johnson295189b2012-06-20 16:38:30 -07005978err_wiphy_reg:
5979 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005980
5981err_config:
5982 kfree(pHddCtx->cfg_ini);
5983 pHddCtx->cfg_ini= NULL;
5984
5985err_free_hdd_context:
5986 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 wiphy_free(wiphy) ;
5988 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 VOS_BUG(1);
5990
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005991 if (hdd_is_ssr_required())
5992 {
5993 /* WDI timeout had happened during load, so SSR is needed here */
5994 subsystem_restart("wcnss");
5995 msleep(5000);
5996 }
5997 hdd_set_ssr_required (VOS_FALSE);
5998
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005999 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006000
6001success:
6002 EXIT();
6003 return 0;
6004}
6005
6006/**---------------------------------------------------------------------------
6007
Jeff Johnson32d95a32012-09-10 13:15:23 -07006008 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006009
Jeff Johnson32d95a32012-09-10 13:15:23 -07006010 This is the driver entry point - called in different timeline depending
6011 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006012
6013 \param - None
6014
6015 \return - 0 for success, non zero for failure
6016
6017 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006018static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006019{
6020 VOS_STATUS status;
6021 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006022 struct device *dev = NULL;
6023 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006024#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6025 int max_retries = 0;
6026#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006027
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306028#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6029 vos_wconn_trace_init();
6030#endif
6031
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 ENTER();
6033
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006034#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006035 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006037
6038 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6039 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6040
6041 //Power Up Libra WLAN card first if not already powered up
6042 status = vos_chipPowerUp(NULL,NULL,NULL);
6043 if (!VOS_IS_STATUS_SUCCESS(status))
6044 {
6045 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6046 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306047#ifdef WLAN_OPEN_SOURCE
6048 wake_lock_destroy(&wlan_wake_lock);
6049#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006050 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 }
6052
Jeff Johnson295189b2012-06-20 16:38:30 -07006053#ifdef ANI_BUS_TYPE_PCI
6054
6055 dev = wcnss_wlan_get_device();
6056
6057#endif // ANI_BUS_TYPE_PCI
6058
6059#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006060
6061#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6062 /* wait until WCNSS driver downloads NV */
6063 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6064 msleep(1000);
6065 }
6066 if (max_retries >= 5) {
6067 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306068#ifdef WLAN_OPEN_SOURCE
6069 wake_lock_destroy(&wlan_wake_lock);
6070#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006071 return -ENODEV;
6072 }
6073#endif
6074
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 dev = wcnss_wlan_get_device();
6076#endif // ANI_BUS_TYPE_PLATFORM
6077
6078
6079 do {
6080 if (NULL == dev) {
6081 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6082 ret_status = -1;
6083 break;
6084 }
6085
6086#ifdef MEMORY_DEBUG
6087 vos_mem_init();
6088#endif
6089
6090#ifdef TIMER_MANAGER
6091 vos_timer_manager_init();
6092#endif
6093
6094 /* Preopen VOSS so that it is ready to start at least SAL */
6095 status = vos_preOpen(&pVosContext);
6096
6097 if (!VOS_IS_STATUS_SUCCESS(status))
6098 {
6099 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6100 ret_status = -1;
6101 break;
6102 }
6103
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006104#ifndef MODULE
6105 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6106 */
6107 hdd_set_conparam((v_UINT_t)con_mode);
6108#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006109
6110 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006111 if (hdd_wlan_startup(dev))
6112 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006113 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006114 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 vos_preClose( &pVosContext );
6116 ret_status = -1;
6117 break;
6118 }
6119
6120 /* Cancel the vote for XO Core ON
6121 * This is done here for safety purposes in case we re-initialize without turning
6122 * it OFF in any error scenario.
6123 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006124 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006126 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6128 {
6129 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6130 " Power consumed will be high\n");
6131 }
6132 } while (0);
6133
6134 if (0 != ret_status)
6135 {
6136 //Assert Deep sleep signal now to put Libra HW in lowest power state
6137 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6138 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6139
6140 //Vote off any PMIC voltage supplies
6141 vos_chipPowerDown(NULL, NULL, NULL);
6142#ifdef TIMER_MANAGER
6143 vos_timer_exit();
6144#endif
6145#ifdef MEMORY_DEBUG
6146 vos_mem_exit();
6147#endif
6148
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006149#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006150 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6153 }
6154 else
6155 {
6156 //Send WLAN UP indication to Nlink Service
6157 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6158
6159 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 }
6161
6162 EXIT();
6163
6164 return ret_status;
6165}
6166
Jeff Johnson32d95a32012-09-10 13:15:23 -07006167/**---------------------------------------------------------------------------
6168
6169 \brief hdd_module_init() - Init Function
6170
6171 This is the driver entry point (invoked when module is loaded using insmod)
6172
6173 \param - None
6174
6175 \return - 0 for success, non zero for failure
6176
6177 --------------------------------------------------------------------------*/
6178#ifdef MODULE
6179static int __init hdd_module_init ( void)
6180{
6181 return hdd_driver_init();
6182}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006183#else /* #ifdef MODULE */
6184static int __init hdd_module_init ( void)
6185{
6186 /* Driver initialization is delayed to fwpath_changed_handler */
6187 return 0;
6188}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006189#endif /* #ifdef MODULE */
6190
Jeff Johnson295189b2012-06-20 16:38:30 -07006191
6192/**---------------------------------------------------------------------------
6193
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006194 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006195
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006196 This is the driver exit point (invoked when module is unloaded using rmmod
6197 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006198
6199 \param - None
6200
6201 \return - None
6202
6203 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006204static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006205{
6206 hdd_context_t *pHddCtx = NULL;
6207 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006208 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006209
6210 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6211
6212 //Get the global vos context
6213 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6214
6215 if(!pVosContext)
6216 {
6217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6218 goto done;
6219 }
6220
6221 //Get the HDD context.
6222 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6223
6224 if(!pHddCtx)
6225 {
6226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6227 }
6228 else
6229 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006230 while(isWDresetInProgress()) {
6231 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6232 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006233 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006234
6235 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6236 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6237 "%s:SSR never completed, fatal error", __func__);
6238 VOS_BUG(0);
6239 }
6240 }
6241
Jeff Johnson295189b2012-06-20 16:38:30 -07006242
6243 pHddCtx->isLoadUnloadInProgress = TRUE;
6244 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6245
6246 //Do all the cleanup before deregistering the driver
6247 hdd_wlan_exit(pHddCtx);
6248 }
6249
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 vos_preClose( &pVosContext );
6251
6252#ifdef TIMER_MANAGER
6253 vos_timer_exit();
6254#endif
6255#ifdef MEMORY_DEBUG
6256 vos_mem_exit();
6257#endif
6258
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306259#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6260 vos_wconn_trace_exit();
6261#endif
6262
Jeff Johnson295189b2012-06-20 16:38:30 -07006263done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006264#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006266#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006267 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6268}
6269
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006270/**---------------------------------------------------------------------------
6271
6272 \brief hdd_module_exit() - Exit function
6273
6274 This is the driver exit point (invoked when module is unloaded using rmmod)
6275
6276 \param - None
6277
6278 \return - None
6279
6280 --------------------------------------------------------------------------*/
6281static void __exit hdd_module_exit(void)
6282{
6283 hdd_driver_exit();
6284}
6285
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006286#ifdef MODULE
6287static int fwpath_changed_handler(const char *kmessage,
6288 struct kernel_param *kp)
6289{
Jeff Johnson76052702013-04-16 13:55:05 -07006290 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006291}
6292
6293static int con_mode_handler(const char *kmessage,
6294 struct kernel_param *kp)
6295{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006296 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006297}
6298#else /* #ifdef MODULE */
6299/**---------------------------------------------------------------------------
6300
Jeff Johnson76052702013-04-16 13:55:05 -07006301 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006302
Jeff Johnson76052702013-04-16 13:55:05 -07006303 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006304 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006305 - invoked when module parameter fwpath is modified from userspace to signal
6306 initializing the WLAN driver or when con_mode is modified from userspace
6307 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006308
6309 \return - 0 for success, non zero for failure
6310
6311 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006312static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006313{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006314 int ret_status;
6315
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006316 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006317 ret_status = hdd_driver_init();
6318 wlan_hdd_inited = ret_status ? 0 : 1;
6319 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006320 }
6321
6322 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006323
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006324 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006325
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006326 ret_status = hdd_driver_init();
6327 wlan_hdd_inited = ret_status ? 0 : 1;
6328 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006329}
6330
Jeff Johnson295189b2012-06-20 16:38:30 -07006331/**---------------------------------------------------------------------------
6332
Jeff Johnson76052702013-04-16 13:55:05 -07006333 \brief fwpath_changed_handler() - Handler Function
6334
6335 Handle changes to the fwpath parameter
6336
6337 \return - 0 for success, non zero for failure
6338
6339 --------------------------------------------------------------------------*/
6340static int fwpath_changed_handler(const char *kmessage,
6341 struct kernel_param *kp)
6342{
6343 int ret;
6344
6345 ret = param_set_copystring(kmessage, kp);
6346 if (0 == ret)
6347 ret = kickstart_driver();
6348 return ret;
6349}
6350
6351/**---------------------------------------------------------------------------
6352
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006353 \brief con_mode_handler() -
6354
6355 Handler function for module param con_mode when it is changed by userspace
6356 Dynamically linked - do nothing
6357 Statically linked - exit and init driver, as in rmmod and insmod
6358
Jeff Johnson76052702013-04-16 13:55:05 -07006359 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006360
Jeff Johnson76052702013-04-16 13:55:05 -07006361 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006362
6363 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006364static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006365{
Jeff Johnson76052702013-04-16 13:55:05 -07006366 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006367
Jeff Johnson76052702013-04-16 13:55:05 -07006368 ret = param_set_int(kmessage, kp);
6369 if (0 == ret)
6370 ret = kickstart_driver();
6371 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006372}
6373#endif /* #ifdef MODULE */
6374
6375/**---------------------------------------------------------------------------
6376
Jeff Johnson295189b2012-06-20 16:38:30 -07006377 \brief hdd_get_conparam() -
6378
6379 This is the driver exit point (invoked when module is unloaded using rmmod)
6380
6381 \param - None
6382
6383 \return - tVOS_CON_MODE
6384
6385 --------------------------------------------------------------------------*/
6386tVOS_CON_MODE hdd_get_conparam ( void )
6387{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006388#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006390#else
6391 return (tVOS_CON_MODE)curr_con_mode;
6392#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006393}
6394void hdd_set_conparam ( v_UINT_t newParam )
6395{
6396 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006397#ifndef MODULE
6398 curr_con_mode = con_mode;
6399#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006400}
6401/**---------------------------------------------------------------------------
6402
6403 \brief hdd_softap_sta_deauth() - function
6404
6405 This to take counter measure to handle deauth req from HDD
6406
6407 \param - pAdapter - Pointer to the HDD
6408
6409 \param - enable - boolean value
6410
6411 \return - None
6412
6413 --------------------------------------------------------------------------*/
6414
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006415VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006416{
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006418 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006419
6420 ENTER();
6421
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306422 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006423
6424 //Ignore request to deauth bcmc station
6425 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006426 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006427
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006428 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006429
6430 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006431 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006432}
6433
6434/**---------------------------------------------------------------------------
6435
6436 \brief hdd_softap_sta_disassoc() - function
6437
6438 This to take counter measure to handle deauth req from HDD
6439
6440 \param - pAdapter - Pointer to the HDD
6441
6442 \param - enable - boolean value
6443
6444 \return - None
6445
6446 --------------------------------------------------------------------------*/
6447
6448void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6449{
6450 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6451
6452 ENTER();
6453
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306454 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006455
6456 //Ignore request to disassoc bcmc station
6457 if( pDestMacAddress[0] & 0x1 )
6458 return;
6459
6460 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6461}
6462
6463void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
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_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006470
6471 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6472}
6473
Jeff Johnson295189b2012-06-20 16:38:30 -07006474/**---------------------------------------------------------------------------
6475 *
6476 * \brief hdd_get__concurrency_mode() -
6477 *
6478 *
6479 * \param - None
6480 *
6481 * \return - CONCURRENCY MODE
6482 *
6483 * --------------------------------------------------------------------------*/
6484tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6485{
6486 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6487 hdd_context_t *pHddCtx;
6488
6489 if (NULL != pVosContext)
6490 {
6491 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6492 if (NULL != pHddCtx)
6493 {
6494 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6495 }
6496 }
6497
6498 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006499 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006500 return VOS_STA;
6501}
6502
6503/* Decide whether to allow/not the apps power collapse.
6504 * Allow apps power collapse if we are in connected state.
6505 * if not, allow only if we are in IMPS */
6506v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6507{
6508 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006509 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006510 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006511 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6512 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6513 hdd_adapter_t *pAdapter = NULL;
6514 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006515 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006516
Jeff Johnson295189b2012-06-20 16:38:30 -07006517 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6518 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006519
Yathish9f22e662012-12-10 14:21:35 -08006520 concurrent_state = hdd_get_concurrency_mode();
6521
6522#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6523 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6524 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6525 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6526 return TRUE;
6527#endif
6528
Jeff Johnson295189b2012-06-20 16:38:30 -07006529 /*loop through all adapters. TBD fix for Concurrency */
6530 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6531 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6532 {
6533 pAdapter = pAdapterNode->pAdapter;
6534 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6535 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6536 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006537 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006538 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006539 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006540 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6541 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006542 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006543 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006544 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6545 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006546 return FALSE;
6547 }
6548 }
6549 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6550 pAdapterNode = pNext;
6551 }
6552 return TRUE;
6553}
6554
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006555/* Decides whether to send suspend notification to Riva
6556 * if any adapter is in BMPS; then it is required */
6557v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6558{
6559 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6560 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6561
6562 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6563 {
6564 return TRUE;
6565 }
6566 return FALSE;
6567}
6568
Jeff Johnson295189b2012-06-20 16:38:30 -07006569void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6570{
6571 switch(mode)
6572 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006573 case VOS_STA_MODE:
6574 case VOS_P2P_CLIENT_MODE:
6575 case VOS_P2P_GO_MODE:
6576 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006577 pHddCtx->concurrency_mode |= (1 << mode);
6578 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006579 break;
6580 default:
6581 break;
6582
6583 }
6584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6585 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6586}
6587
6588
6589void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6590{
6591 switch(mode)
6592 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006593 case VOS_STA_MODE:
6594 case VOS_P2P_CLIENT_MODE:
6595 case VOS_P2P_GO_MODE:
6596 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 pHddCtx->no_of_sessions[mode]--;
6598 if (!(pHddCtx->no_of_sessions[mode]))
6599 pHddCtx->concurrency_mode &= (~(1 << mode));
6600 break;
6601 default:
6602 break;
6603 }
6604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6605 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6606}
6607
Jeff Johnsone7245742012-09-05 17:12:55 -07006608/**---------------------------------------------------------------------------
6609 *
6610 * \brief wlan_hdd_restart_init
6611 *
6612 * This function initalizes restart timer/flag. An internal function.
6613 *
6614 * \param - pHddCtx
6615 *
6616 * \return - None
6617 *
6618 * --------------------------------------------------------------------------*/
6619
6620static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6621{
6622 /* Initialize */
6623 pHddCtx->hdd_restart_retries = 0;
6624 atomic_set(&pHddCtx->isRestartInProgress, 0);
6625 vos_timer_init(&pHddCtx->hdd_restart_timer,
6626 VOS_TIMER_TYPE_SW,
6627 wlan_hdd_restart_timer_cb,
6628 pHddCtx);
6629}
6630/**---------------------------------------------------------------------------
6631 *
6632 * \brief wlan_hdd_restart_deinit
6633 *
6634 * This function cleans up the resources used. An internal function.
6635 *
6636 * \param - pHddCtx
6637 *
6638 * \return - None
6639 *
6640 * --------------------------------------------------------------------------*/
6641
6642static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6643{
6644
6645 VOS_STATUS vos_status;
6646 /* Block any further calls */
6647 atomic_set(&pHddCtx->isRestartInProgress, 1);
6648 /* Cleanup */
6649 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6650 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006651 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006652 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6653 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006654 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006655
6656}
6657
6658/**---------------------------------------------------------------------------
6659 *
6660 * \brief wlan_hdd_framework_restart
6661 *
6662 * This function uses a cfg80211 API to start a framework initiated WLAN
6663 * driver module unload/load.
6664 *
6665 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6666 *
6667 *
6668 * \param - pHddCtx
6669 *
6670 * \return - VOS_STATUS_SUCCESS: Success
6671 * VOS_STATUS_E_EMPTY: Adapter is Empty
6672 * VOS_STATUS_E_NOMEM: No memory
6673
6674 * --------------------------------------------------------------------------*/
6675
6676static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6677{
6678 VOS_STATUS status = VOS_STATUS_SUCCESS;
6679 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006680 int len = (sizeof (struct ieee80211_mgmt));
6681 struct ieee80211_mgmt *mgmt = NULL;
6682
6683 /* Prepare the DEAUTH managment frame with reason code */
6684 mgmt = kzalloc(len, GFP_KERNEL);
6685 if(mgmt == NULL)
6686 {
6687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6688 "%s: memory allocation failed (%d bytes)", __func__, len);
6689 return VOS_STATUS_E_NOMEM;
6690 }
6691 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006692
6693 /* Iterate over all adapters/devices */
6694 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6695 do
6696 {
6697 if( (status == VOS_STATUS_SUCCESS) &&
6698 pAdapterNode &&
6699 pAdapterNode->pAdapter)
6700 {
6701 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6702 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6703 pAdapterNode->pAdapter->dev->name,
6704 pAdapterNode->pAdapter->device_mode,
6705 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006706 /*
6707 * CFG80211 event to restart the driver
6708 *
6709 * 'cfg80211_send_unprot_deauth' sends a
6710 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6711 * of SME(Linux Kernel) state machine.
6712 *
6713 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6714 * the driver.
6715 *
6716 */
6717
6718 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006719 }
6720 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6721 pAdapterNode = pNext;
6722 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6723
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006724
6725 /* Free the allocated management frame */
6726 kfree(mgmt);
6727
Jeff Johnsone7245742012-09-05 17:12:55 -07006728 /* Retry until we unload or reach max count */
6729 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6730 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6731
6732 return status;
6733
6734}
6735/**---------------------------------------------------------------------------
6736 *
6737 * \brief wlan_hdd_restart_timer_cb
6738 *
6739 * Restart timer callback. An internal function.
6740 *
6741 * \param - User data:
6742 *
6743 * \return - None
6744 *
6745 * --------------------------------------------------------------------------*/
6746
6747void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6748{
6749 hdd_context_t *pHddCtx = usrDataForCallback;
6750 wlan_hdd_framework_restart(pHddCtx);
6751 return;
6752
6753}
6754
6755
6756/**---------------------------------------------------------------------------
6757 *
6758 * \brief wlan_hdd_restart_driver
6759 *
6760 * This function sends an event to supplicant to restart the WLAN driver.
6761 *
6762 * This function is called from vos_wlanRestart.
6763 *
6764 * \param - pHddCtx
6765 *
6766 * \return - VOS_STATUS_SUCCESS: Success
6767 * VOS_STATUS_E_EMPTY: Adapter is Empty
6768 * VOS_STATUS_E_ALREADY: Request already in progress
6769
6770 * --------------------------------------------------------------------------*/
6771VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6772{
6773 VOS_STATUS status = VOS_STATUS_SUCCESS;
6774
6775 /* A tight check to make sure reentrancy */
6776 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6777 {
6778 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6779 "%s: WLAN restart is already in progress", __func__);
6780
6781 return VOS_STATUS_E_ALREADY;
6782 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006783 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006784#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006785 wcnss_reset_intr();
6786#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006787
Jeff Johnsone7245742012-09-05 17:12:55 -07006788 return status;
6789}
6790
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006791/*
6792 * API to find if there is any STA or P2P-Client is connected
6793 */
6794VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6795{
6796 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6797}
Jeff Johnsone7245742012-09-05 17:12:55 -07006798
Jeff Johnson295189b2012-06-20 16:38:30 -07006799//Register the module init/exit functions
6800module_init(hdd_module_init);
6801module_exit(hdd_module_exit);
6802
6803MODULE_LICENSE("Dual BSD/GPL");
6804MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6805MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6806
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006807module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6808 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006809
Jeff Johnson76052702013-04-16 13:55:05 -07006810module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006811 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);