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