blob: 67ed8d54ec5bdba116cdbf19e98bea2e644b9f66 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Rajeev Kumar8b373292014-01-08 20:36:55 -08002 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08003 *
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>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530106#include <linux/inetdevice.h>
107#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include "wlan_hdd_cfg80211.h"
109#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700111int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include "sapApi.h"
113#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700114#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include <mach/subsystem_restart.h>
116#include <wlan_hdd_hostapd.h>
117#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "wlan_hdd_dev_pwr.h"
120#ifdef WLAN_BTAMP_FEATURE
121#include "bap_hdd_misc.h"
122#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700123#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700124#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800125#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530126#ifdef FEATURE_WLAN_TDLS
127#include "wlan_hdd_tdls.h"
128#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700129#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700130
131#ifdef MODULE
132#define WLAN_MODULE_NAME module_name(THIS_MODULE)
133#else
134#define WLAN_MODULE_NAME "wlan"
135#endif
136
137#ifdef TIMER_MANAGER
138#define TIMER_MANAGER_STR " +TIMER_MANAGER"
139#else
140#define TIMER_MANAGER_STR ""
141#endif
142
143#ifdef MEMORY_DEBUG
144#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
145#else
146#define MEMORY_DEBUG_STR ""
147#endif
148
149/* the Android framework expects this param even though we don't use it */
150#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700151static char fwpath_buffer[BUF_LEN];
152static struct kparam_string fwpath = {
153 .string = fwpath_buffer,
154 .maxlen = BUF_LEN,
155};
Arif Hussain66559122013-11-21 10:11:40 -0800156
157static char *country_code;
158static int enable_11d = -1;
159static int enable_dfs_chan_scan = -1;
160
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700161#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700162static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700163#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
Jeff Johnsone7245742012-09-05 17:12:55 -0700165/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800166 * spinlock for synchronizing asynchronous request/response
167 * (full description of use in wlan_hdd_main.h)
168 */
169DEFINE_SPINLOCK(hdd_context_lock);
170
171/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700172 * The rate at which the driver sends RESTART event to supplicant
173 * once the function 'vos_wlanRestart()' is called
174 *
175 */
176#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
177#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700178
179/*
180 * Size of Driver command strings from upper layer
181 */
182#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
183#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
184
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700185#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
186#define TID_MIN_VALUE 0
187#define TID_MAX_VALUE 15
188static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
189 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800190static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
191 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700192#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
193
Srinivas Girigowda4081bb12014-01-06 17:12:58 -0800194#define WLAN_PRIV_DATA_MAX_LEN 4096
195
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700196/*
197 * Driver miracast parameters 0-Disabled
198 * 1-Source, 2-Sink
199 */
200#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
201#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
202
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800203#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700204static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700205#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700206/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700207static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700210static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
211static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
212static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
213void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800214void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700215
Jeff Johnson295189b2012-06-20 16:38:30 -0700216v_U16_t hdd_select_queue(struct net_device *dev,
217 struct sk_buff *skb);
218
219#ifdef WLAN_FEATURE_PACKET_FILTERING
220static void hdd_set_multicast_list(struct net_device *dev);
221#endif
222
223void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700224int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700225
226extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700227
Srinivas Girigowdade697412013-02-14 16:31:48 -0800228#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
229void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
230static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700231static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
232 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
233 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700234static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
235 tANI_U8 *pTargetApBssid,
236 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800237#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700238#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
239VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
240#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
241
Jeff Johnson295189b2012-06-20 16:38:30 -0700242static int hdd_netdev_notifier_call(struct notifier_block * nb,
243 unsigned long state,
244 void *ndev)
245{
246 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700247 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700248 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700249#ifdef WLAN_BTAMP_FEATURE
250 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700251#endif
252
253 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700254 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700255 (strncmp(dev->name, "p2p", 3)))
256 return NOTIFY_DONE;
257
258 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 return NOTIFY_DONE;
260
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700262 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700263
Jeff Johnson27cee452013-03-27 11:10:24 -0700264 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800266 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 VOS_ASSERT(0);
268 return NOTIFY_DONE;
269 }
270
Jeff Johnson27cee452013-03-27 11:10:24 -0700271 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
272 if (NULL == pHddCtx)
273 {
274 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
275 VOS_ASSERT(0);
276 return NOTIFY_DONE;
277 }
278
279 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
280 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281
282 switch (state) {
283 case NETDEV_REGISTER:
284 break;
285
286 case NETDEV_UNREGISTER:
287 break;
288
289 case NETDEV_UP:
290 break;
291
292 case NETDEV_DOWN:
293 break;
294
295 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700296 if(TRUE == pAdapter->isLinkUpSvcNeeded)
297 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 break;
299
300 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700301 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700302 {
303 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800304 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530305 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800307 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
309 if(!result)
310 {
311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800312 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700313 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700314 }
315 }
316 else
317 {
318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700319 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 }
321#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700322 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323 status = WLANBAP_StopAmp();
324 if(VOS_STATUS_SUCCESS != status )
325 {
326 pHddCtx->isAmpAllowed = VOS_TRUE;
327 hddLog(VOS_TRACE_LEVEL_FATAL,
328 "%s: Failed to stop AMP", __func__);
329 }
330 else
331 {
332 //a state m/c implementation in PAL is TBD to avoid this delay
333 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700334 if ( pHddCtx->isAmpAllowed )
335 {
336 WLANBAP_DeregisterFromHCI();
337 pHddCtx->isAmpAllowed = VOS_FALSE;
338 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700339 }
340#endif //WLAN_BTAMP_FEATURE
341 break;
342
343 default:
344 break;
345 }
346
347 return NOTIFY_DONE;
348}
349
350struct notifier_block hdd_netdev_notifier = {
351 .notifier_call = hdd_netdev_notifier_call,
352};
353
354/*---------------------------------------------------------------------------
355 * Function definitions
356 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700357void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
358void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700359//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700360static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700361#ifndef MODULE
362/* current con_mode - used only for statically linked driver
363 * con_mode is changed by userspace to indicate a mode change which will
364 * result in calling the module exit and init functions. The module
365 * exit function will clean up based on the value of con_mode prior to it
366 * being changed by userspace. So curr_con_mode records the current con_mode
367 * for exit when con_mode becomes the next mode for init
368 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700369static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700370#endif
371
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800372/**---------------------------------------------------------------------------
373
374 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
375
376 Called immediately after the cfg.ini is read in order to configure
377 the desired trace levels.
378
379 \param - moduleId - module whose trace level is being configured
380 \param - bitmask - bitmask of log levels to be enabled
381
382 \return - void
383
384 --------------------------------------------------------------------------*/
385static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
386{
387 wpt_tracelevel level;
388
389 /* if the bitmask is the default value, then a bitmask was not
390 specified in cfg.ini, so leave the logging level alone (it
391 will remain at the "compiled in" default value) */
392 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
393 {
394 return;
395 }
396
397 /* a mask was specified. start by disabling all logging */
398 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
399
400 /* now cycle through the bitmask until all "set" bits are serviced */
401 level = VOS_TRACE_LEVEL_FATAL;
402 while (0 != bitmask)
403 {
404 if (bitmask & 1)
405 {
406 vos_trace_setValue(moduleId, level, 1);
407 }
408 level++;
409 bitmask >>= 1;
410 }
411}
412
413
Jeff Johnson295189b2012-06-20 16:38:30 -0700414/**---------------------------------------------------------------------------
415
416 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
417
418 Called immediately after the cfg.ini is read in order to configure
419 the desired trace levels in the WDI.
420
421 \param - moduleId - module whose trace level is being configured
422 \param - bitmask - bitmask of log levels to be enabled
423
424 \return - void
425
426 --------------------------------------------------------------------------*/
427static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
428{
429 wpt_tracelevel level;
430
431 /* if the bitmask is the default value, then a bitmask was not
432 specified in cfg.ini, so leave the logging level alone (it
433 will remain at the "compiled in" default value) */
434 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
435 {
436 return;
437 }
438
439 /* a mask was specified. start by disabling all logging */
440 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
441
442 /* now cycle through the bitmask until all "set" bits are serviced */
443 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
444 while (0 != bitmask)
445 {
446 if (bitmask & 1)
447 {
448 wpalTraceSetLevel(moduleId, level, 1);
449 }
450 level++;
451 bitmask >>= 1;
452 }
453}
Jeff Johnson295189b2012-06-20 16:38:30 -0700454
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530455/*
456 * FUNCTION: wlan_hdd_validate_context
457 * This function is used to check the HDD context
458 */
459int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
460{
461 ENTER();
462
463 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
464 {
465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
466 "%s: HDD context is Null", __func__);
467 return -ENODEV;
468 }
469
470 if (pHddCtx->isLogpInProgress)
471 {
472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
473 "%s: LOGP in Progress. Ignore!!!", __func__);
474 return -EAGAIN;
475 }
476
477 if (pHddCtx->isLoadUnloadInProgress)
478 {
479 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
480 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
481 return -EAGAIN;
482 }
483 return 0;
484}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700485#ifdef CONFIG_ENABLE_LINUX_REG
486void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
487{
488 hdd_adapter_t *pAdapter = NULL;
489 hdd_station_ctx_t *pHddStaCtx = NULL;
490 eCsrPhyMode phyMode;
491 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530492
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700493 if (NULL == pHddCtx)
494 {
495 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
496 "HDD Context is null !!");
497 return ;
498 }
499
500 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
501 if (NULL == pAdapter)
502 {
503 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
504 "pAdapter is null !!");
505 return ;
506 }
507
508 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
509 if (NULL == pHddStaCtx)
510 {
511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
512 "pHddStaCtx is null !!");
513 return ;
514 }
515
516 cfg_param = pHddCtx->cfg_ini;
517 if (NULL == cfg_param)
518 {
519 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
520 "cfg_params not available !!");
521 return ;
522 }
523
524 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
525
526 if (!pHddCtx->isVHT80Allowed)
527 {
528 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
529 (eCSR_DOT11_MODE_11ac == phyMode) ||
530 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
531 {
532 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
533 "Setting phymode to 11n!!");
534 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
535 }
536 }
537 else
538 {
539 /*New country Supports 11ac as well resetting value back from .ini*/
540 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
541 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
542 return ;
543 }
544
545 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
546 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
547 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
548 {
549 VOS_STATUS vosStatus;
550
551 // need to issue a disconnect to CSR.
552 INIT_COMPLETION(pAdapter->disconnect_comp_var);
553 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
554 pAdapter->sessionId,
555 eCSR_DISCONNECT_REASON_UNSPECIFIED );
556
557 if (VOS_STATUS_SUCCESS == vosStatus)
558 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
559 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
560
561 }
562}
563#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530564void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
565{
566 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
567 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
568 hdd_config_t *cfg_param;
569 eCsrPhyMode phyMode;
570
571 if (NULL == pHddCtx)
572 {
573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
574 "HDD Context is null !!");
575 return ;
576 }
577
578 cfg_param = pHddCtx->cfg_ini;
579
580 if (NULL == cfg_param)
581 {
582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
583 "cfg_params not available !!");
584 return ;
585 }
586
587 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
588
589 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
590 {
591 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
592 (eCSR_DOT11_MODE_11ac == phyMode) ||
593 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
594 {
595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
596 "Setting phymode to 11n!!");
597 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
598 }
599 }
600 else
601 {
602 /*New country Supports 11ac as well resetting value back from .ini*/
603 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
604 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
605 return ;
606 }
607
608 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
609 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
610 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
611 {
612 VOS_STATUS vosStatus;
613
614 // need to issue a disconnect to CSR.
615 INIT_COMPLETION(pAdapter->disconnect_comp_var);
616 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
617 pAdapter->sessionId,
618 eCSR_DISCONNECT_REASON_UNSPECIFIED );
619
620 if (VOS_STATUS_SUCCESS == vosStatus)
621 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
622 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
623
624 }
625}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700626#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530627
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700628void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
629{
630 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
631 hdd_config_t *cfg_param;
632
633 if (NULL == pHddCtx)
634 {
635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
636 "HDD Context is null !!");
637 return ;
638 }
639
640 cfg_param = pHddCtx->cfg_ini;
641
642 if (NULL == cfg_param)
643 {
644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
645 "cfg_params not available !!");
646 return ;
647 }
648
649 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
650 {
651 /*New country doesn't support DFS */
652 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
653 }
654 else
655 {
656 /*New country Supports DFS as well resetting value back from .ini*/
657 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
658 }
659
660}
661
Rajeev79dbe4c2013-10-05 11:03:42 +0530662#ifdef FEATURE_WLAN_BATCH_SCAN
663
664/**---------------------------------------------------------------------------
665
666 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
667 input string
668
669 This function extracts assigned integer from string in below format:
670 "STRING=10" : extracts integer 10 from this string
671
672 \param - pInPtr Pointer to input string
673 \param - base Base for string to int conversion(10 for decimal 16 for hex)
674 \param - pOutPtr Pointer to variable in which extracted integer needs to be
675 assigned
676 \param - pLastArg to tell whether it is last arguement in input string or
677 not
678
679 \return - NULL for failure cases
680 pointer to next arguement in input string for success cases
681 --------------------------------------------------------------------------*/
682static tANI_U8 *
683hdd_extract_assigned_int_from_str
684(
685 tANI_U8 *pInPtr,
686 tANI_U8 base,
687 tANI_U32 *pOutPtr,
688 tANI_U8 *pLastArg
689)
690{
691 int tempInt;
692 int v = 0;
693 char buf[32];
694 int val = 0;
695 *pLastArg = FALSE;
696
697 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
698 if (NULL == pInPtr)
699 {
700 return NULL;
701 }
702
703 pInPtr++;
704
705 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
706
707 val = sscanf(pInPtr, "%32s ", buf);
708 if (val < 0 && val > strlen(pInPtr))
709 {
710 return NULL;
711 }
712 pInPtr += val;
713 v = kstrtos32(buf, base, &tempInt);
714 if (v < 0)
715 {
716 return NULL;
717 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800718 if (tempInt < 0)
719 {
720 tempInt = 0;
721 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530722 *pOutPtr = tempInt;
723
724 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
725 if (NULL == pInPtr)
726 {
727 *pLastArg = TRUE;
728 return NULL;
729 }
730 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
731
732 return pInPtr;
733}
734
735/**---------------------------------------------------------------------------
736
737 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
738 input string
739
740 This function extracts assigned character from string in below format:
741 "STRING=A" : extracts char 'A' from this string
742
743 \param - pInPtr Pointer to input string
744 \param - pOutPtr Pointer to variable in which extracted char needs to be
745 assigned
746 \param - pLastArg to tell whether it is last arguement in input string or
747 not
748
749 \return - NULL for failure cases
750 pointer to next arguement in input string for success cases
751 --------------------------------------------------------------------------*/
752static tANI_U8 *
753hdd_extract_assigned_char_from_str
754(
755 tANI_U8 *pInPtr,
756 tANI_U8 *pOutPtr,
757 tANI_U8 *pLastArg
758)
759{
760 *pLastArg = FALSE;
761
762 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
763 if (NULL == pInPtr)
764 {
765 return NULL;
766 }
767
768 pInPtr++;
769
770 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
771
772 *pOutPtr = *pInPtr;
773
774 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
775 if (NULL == pInPtr)
776 {
777 *pLastArg = TRUE;
778 return NULL;
779 }
780 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
781
782 return pInPtr;
783}
784
785
786/**---------------------------------------------------------------------------
787
788 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
789
790 This function parses set batch scan command in below format:
791 WLS_BATCHING_SET <space> followed by below arguements
792 "SCANFREQ=XX" : Optional defaults to 30 sec
793 "MSCAN=XX" : Required number of scans to attempt to batch
794 "BESTN=XX" : Best Network (RSSI) defaults to 16
795 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
796 A. implies only 5 GHz , B. implies only 2.4GHz
797 "RTT=X" : optional defaults to 0
798 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
799 error
800
801 For example input commands:
802 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
803 translated into set batch scan with following parameters:
804 a) Frequence 60 seconds
805 b) Batch 10 scans together
806 c) Best RSSI to be 20
807 d) 5GHz band only
808 e) RTT is equal to 0
809
810 \param - pValue Pointer to input channel list
811 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
812
813 \return - 0 for success non-zero for failure
814
815 --------------------------------------------------------------------------*/
816static int
817hdd_parse_set_batchscan_command
818(
819 tANI_U8 *pValue,
820 tSirSetBatchScanReq *pHddSetBatchScanReq
821)
822{
823 tANI_U8 *inPtr = pValue;
824 tANI_U8 val = 0;
825 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800826 tANI_U32 nScanFreq;
827 tANI_U32 nMscan;
828 tANI_U32 nBestN;
829 tANI_U8 ucRfBand;
830 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800831 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530832
833 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800834 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
835 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
836 nRtt = 0;
837 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530838
839 /*go to space after WLS_BATCHING_SET command*/
840 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
841 /*no argument after the command*/
842 if (NULL == inPtr)
843 {
844 return -EINVAL;
845 }
846
847 /*no space after the command*/
848 else if (SPACE_ASCII_VALUE != *inPtr)
849 {
850 return -EINVAL;
851 }
852
853 /*removing empty spaces*/
854 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
855
856 /*no argument followed by spaces*/
857 if ('\0' == *inPtr)
858 {
859 return -EINVAL;
860 }
861
862 /*check and parse SCANFREQ*/
863 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
864 {
865 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800866 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800867
Rajeev Kumarc933d982013-11-18 20:04:20 -0800868 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800869 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800870 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800871 }
872
Rajeev79dbe4c2013-10-05 11:03:42 +0530873 if ( (NULL == inPtr) || (TRUE == lastArg))
874 {
875 return -EINVAL;
876 }
877 }
878
879 /*check and parse MSCAN*/
880 if ((strncmp(inPtr, "MSCAN", 5) == 0))
881 {
882 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800883 &nMscan, &lastArg);
884
885 if (0 == nMscan)
886 {
887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
888 "invalid MSCAN=%d", nMscan);
889 return -EINVAL;
890 }
891
Rajeev79dbe4c2013-10-05 11:03:42 +0530892 if (TRUE == lastArg)
893 {
894 goto done;
895 }
896 else if (NULL == inPtr)
897 {
898 return -EINVAL;
899 }
900 }
901 else
902 {
903 return -EINVAL;
904 }
905
906 /*check and parse BESTN*/
907 if ((strncmp(inPtr, "BESTN", 5) == 0))
908 {
909 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800910 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800911
Rajeev Kumarc933d982013-11-18 20:04:20 -0800912 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800913 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800914 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800915 }
916
Rajeev79dbe4c2013-10-05 11:03:42 +0530917 if (TRUE == lastArg)
918 {
919 goto done;
920 }
921 else if (NULL == inPtr)
922 {
923 return -EINVAL;
924 }
925 }
926
927 /*check and parse CHANNEL*/
928 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
929 {
930 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800931
Rajeev79dbe4c2013-10-05 11:03:42 +0530932 if (('A' == val) || ('a' == val))
933 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800934 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530935 }
936 else if (('B' == val) || ('b' == val))
937 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800938 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530939 }
940 else
941 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800942 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
943 }
944
945 if (TRUE == lastArg)
946 {
947 goto done;
948 }
949 else if (NULL == inPtr)
950 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530951 return -EINVAL;
952 }
953 }
954
955 /*check and parse RTT*/
956 if ((strncmp(inPtr, "RTT", 3) == 0))
957 {
958 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800959 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530960 if (TRUE == lastArg)
961 {
962 goto done;
963 }
964 if (NULL == inPtr)
965 {
966 return -EINVAL;
967 }
968 }
969
970
971done:
972
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800973 pHddSetBatchScanReq->scanFrequency = nScanFreq;
974 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
975 pHddSetBatchScanReq->bestNetwork = nBestN;
976 pHddSetBatchScanReq->rfBand = ucRfBand;
977 pHddSetBatchScanReq->rtt = nRtt;
978
Rajeev79dbe4c2013-10-05 11:03:42 +0530979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
980 "Received WLS_BATCHING_SET with SCANFREQ=%d "
981 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
982 pHddSetBatchScanReq->scanFrequency,
983 pHddSetBatchScanReq->numberOfScansToBatch,
984 pHddSetBatchScanReq->bestNetwork,
985 pHddSetBatchScanReq->rfBand,
986 pHddSetBatchScanReq->rtt);
987
988 return 0;
989}/*End of hdd_parse_set_batchscan_command*/
990
991/**---------------------------------------------------------------------------
992
993 \brief hdd_set_batch_scan_req_callback () - This function is called after
994 receiving set batch scan response from FW and it saves set batch scan
995 response data FW to HDD context and sets the completion event on
996 which hdd_ioctl is waiting
997
998 \param - callbackContext Pointer to HDD adapter
999 \param - pRsp Pointer to set batch scan response data received from FW
1000
1001 \return - nothing
1002
1003 --------------------------------------------------------------------------*/
1004static void hdd_set_batch_scan_req_callback
1005(
1006 void *callbackContext,
1007 tSirSetBatchScanRsp *pRsp
1008)
1009{
1010 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1011 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1012
1013 /*sanity check*/
1014 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1015 {
1016 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1017 "%s: Invalid pAdapter magic", __func__);
1018 VOS_ASSERT(0);
1019 return;
1020 }
1021 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1022
1023 /*save set batch scan response*/
1024 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1025
1026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1027 "Received set batch scan rsp from FW with nScansToBatch=%d",
1028 pHddSetBatchScanRsp->nScansToBatch);
1029
1030 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1031 complete(&pAdapter->hdd_set_batch_scan_req_var);
1032
1033 return;
1034}/*End of hdd_set_batch_scan_req_callback*/
1035
1036
1037/**---------------------------------------------------------------------------
1038
1039 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1040 info in hdd batch scan response queue
1041
1042 \param - pAdapter Pointer to hdd adapter
1043 \param - pAPMetaInfo Pointer to access point meta info
1044 \param - scanId scan ID of batch scan response
1045 \param - isLastAp tells whether AP is last AP in batch scan response or not
1046
1047 \return - nothing
1048
1049 --------------------------------------------------------------------------*/
1050static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1051 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1052{
1053 tHddBatchScanRsp *pHead;
1054 tHddBatchScanRsp *pNode;
1055 tHddBatchScanRsp *pPrev;
1056 tHddBatchScanRsp *pTemp;
1057 tANI_U8 ssidLen;
1058
1059 /*head of hdd batch scan response queue*/
1060 pHead = pAdapter->pBatchScanRsp;
1061
1062 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1063 if (NULL == pNode)
1064 {
1065 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1066 "%s: Could not allocate memory", __func__);
1067 VOS_ASSERT(0);
1068 return;
1069 }
1070
1071 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1072 sizeof(pNode->ApInfo.bssid));
1073 ssidLen = strlen(pApMetaInfo->ssid);
1074 if (SIR_MAX_SSID_SIZE < ssidLen)
1075 {
1076 /*invalid scan result*/
1077 vos_mem_free(pNode);
1078 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1080 return;
1081 }
1082 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1083 /*null terminate ssid*/
1084 pNode->ApInfo.ssid[ssidLen] = '\0';
1085 pNode->ApInfo.ch = pApMetaInfo->ch;
1086 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1087 pNode->ApInfo.age = pApMetaInfo->timestamp;
1088 pNode->ApInfo.batchId = scanId;
1089 pNode->ApInfo.isLastAp = isLastAp;
1090
1091 pNode->pNext = NULL;
1092 if (NULL == pHead)
1093 {
1094 pAdapter->pBatchScanRsp = pNode;
1095 }
1096 else
1097 {
1098 pTemp = pHead;
1099 while (NULL != pTemp)
1100 {
1101 pPrev = pTemp;
1102 pTemp = pTemp->pNext;
1103 }
1104 pPrev->pNext = pNode;
1105 }
1106
1107 return;
1108}/*End of hdd_populate_batch_scan_rsp_queue*/
1109
1110/**---------------------------------------------------------------------------
1111
1112 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1113 receiving batch scan response indication from FW. It saves get batch scan
1114 response data in HDD batch scan response queue. This callback sets the
1115 completion event on which hdd_ioctl is waiting only after getting complete
1116 batch scan response data from FW
1117
1118 \param - callbackContext Pointer to HDD adapter
1119 \param - pRsp Pointer to get batch scan response data received from FW
1120
1121 \return - nothing
1122
1123 --------------------------------------------------------------------------*/
1124static void hdd_batch_scan_result_ind_callback
1125(
1126 void *callbackContext,
1127 void *pRsp
1128)
1129{
1130 v_BOOL_t isLastAp;
1131 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001132 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301133 tANI_U32 numberScanList;
1134 tANI_U32 nextScanListOffset;
1135 tANI_U32 nextApMetaInfoOffset;
1136 hdd_adapter_t* pAdapter;
1137 tpSirBatchScanList pScanList;
1138 tpSirBatchScanNetworkInfo pApMetaInfo;
1139 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1140 tSirSetBatchScanReq *pReq;
1141
1142 pAdapter = (hdd_adapter_t *)callbackContext;
1143 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001144 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301145 {
1146 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1147 "%s: Invalid pAdapter magic", __func__);
1148 VOS_ASSERT(0);
1149 return;
1150 }
1151
1152 /*initialize locals*/
1153 pReq = &pAdapter->hddSetBatchScanReq;
1154 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1155 isLastAp = FALSE;
1156 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001157 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301158 numberScanList = 0;
1159 nextScanListOffset = 0;
1160 nextApMetaInfoOffset = 0;
1161 pScanList = NULL;
1162 pApMetaInfo = NULL;
1163
1164 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1165 {
1166 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1167 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1168 isLastAp = TRUE;
1169 goto done;
1170 }
1171
1172 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1174 "Batch scan rsp: numberScalList %d", numberScanList);
1175
1176 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1177 {
1178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1179 "%s: numberScanList %d", __func__, numberScanList);
1180 isLastAp = TRUE;
1181 goto done;
1182 }
1183
1184 while (numberScanList)
1185 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001186 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301187 nextScanListOffset);
1188 if (NULL == pScanList)
1189 {
1190 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1191 "%s: pScanList is %p", __func__, pScanList);
1192 isLastAp = TRUE;
1193 goto done;
1194 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001195 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301196 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001197 "Batch scan rsp: numApMetaInfo %d scanId %d",
1198 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301199
1200 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1201 {
1202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1203 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1204 isLastAp = TRUE;
1205 goto done;
1206 }
1207
Rajeev Kumarce651e42013-10-21 18:57:15 -07001208 /*Initialize next AP meta info offset for next scan list*/
1209 nextApMetaInfoOffset = 0;
1210
Rajeev79dbe4c2013-10-05 11:03:42 +05301211 while (numApMetaInfo)
1212 {
1213 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1214 nextApMetaInfoOffset);
1215 if (NULL == pApMetaInfo)
1216 {
1217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1218 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1219 isLastAp = TRUE;
1220 goto done;
1221 }
1222 /*calculate AP age*/
1223 pApMetaInfo->timestamp =
1224 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1225
1226 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001227 "%s: bssId "MAC_ADDRESS_STR
1228 " ch %d rssi %d timestamp %d", __func__,
1229 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1230 pApMetaInfo->ch, pApMetaInfo->rssi,
1231 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301232
1233 /*mark last AP in batch scan response*/
1234 if ((TRUE == pBatchScanRsp->isLastResult) &&
1235 (1 == numberScanList) && (1 == numApMetaInfo))
1236 {
1237 isLastAp = TRUE;
1238 }
1239
1240 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1241 /*store batch scan repsonse in hdd queue*/
1242 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1243 pScanList->scanId, isLastAp);
1244 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1245
1246 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1247 numApMetaInfo--;
1248 }
1249
Rajeev Kumarce651e42013-10-21 18:57:15 -07001250 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1251 + (sizeof(tSirBatchScanNetworkInfo)
1252 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301253 numberScanList--;
1254 }
1255
1256done:
1257
1258 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1259 requested from hdd_ioctl*/
1260 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1261 (TRUE == isLastAp))
1262 {
1263 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1264 complete(&pAdapter->hdd_get_batch_scan_req_var);
1265 }
1266
1267 return;
1268}/*End of hdd_batch_scan_result_ind_callback*/
1269
1270/**---------------------------------------------------------------------------
1271
1272 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1273 response as per batch scan FR request format by putting proper markers
1274
1275 \param - pDest pointer to destination buffer
1276 \param - cur_len current length
1277 \param - tot_len total remaining size which can be written to user space
1278 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1279 \param - pAdapter Pointer to HDD adapter
1280
1281 \return - ret no of characters written
1282
1283 --------------------------------------------------------------------------*/
1284static tANI_U32
1285hdd_format_batch_scan_rsp
1286(
1287 tANI_U8 *pDest,
1288 tANI_U32 cur_len,
1289 tANI_U32 tot_len,
1290 tHddBatchScanRsp *pApMetaInfo,
1291 hdd_adapter_t* pAdapter
1292)
1293{
1294 tANI_U32 ret = 0;
1295 tANI_U32 rem_len = 0;
1296 tANI_U8 temp_len = 0;
1297 tANI_U8 temp_total_len = 0;
1298 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1299 tANI_U8 *pTemp = temp;
1300
1301 /*Batch scan reponse needs to be returned to user space in
1302 following format:
1303 "scancount=X\n" where X is the number of scans in current batch
1304 batch
1305 "trunc\n" optional present if current scan truncated
1306 "bssid=XX:XX:XX:XX:XX:XX\n"
1307 "ssid=XXXX\n"
1308 "freq=X\n" frequency in Mhz
1309 "level=XX\n"
1310 "age=X\n" ms
1311 "dist=X\n" cm (-1 if not available)
1312 "errror=X\n" (-1if not available)
1313 "====\n" (end of ap marker)
1314 "####\n" (end of scan marker)
1315 "----\n" (end of results)*/
1316 /*send scan result in above format to user space based on
1317 available length*/
1318 /*The GET response may have more data than the driver can return in its
1319 buffer. In that case the buffer should be filled to the nearest complete
1320 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1321 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1322 The final buffer should end with "----\n"*/
1323
1324 /*sanity*/
1325 if (cur_len > tot_len)
1326 {
1327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1328 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1329 return 0;
1330 }
1331 else
1332 {
1333 rem_len = (tot_len - cur_len);
1334 }
1335
1336 /*end scan marker*/
1337 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1338 {
1339 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1340 pTemp += temp_len;
1341 temp_total_len += temp_len;
1342 }
1343
1344 /*bssid*/
1345 temp_len = snprintf(pTemp, sizeof(temp),
1346 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1347 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1348 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1349 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1350 pTemp += temp_len;
1351 temp_total_len += temp_len;
1352
1353 /*ssid*/
1354 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1355 pApMetaInfo->ApInfo.ssid);
1356 pTemp += temp_len;
1357 temp_total_len += temp_len;
1358
1359 /*freq*/
1360 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001361 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301362 pTemp += temp_len;
1363 temp_total_len += temp_len;
1364
1365 /*level*/
1366 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1367 pApMetaInfo->ApInfo.rssi);
1368 pTemp += temp_len;
1369 temp_total_len += temp_len;
1370
1371 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001372 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301373 pApMetaInfo->ApInfo.age);
1374 pTemp += temp_len;
1375 temp_total_len += temp_len;
1376
1377 /*dist*/
1378 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1379 pTemp += temp_len;
1380 temp_total_len += temp_len;
1381
1382 /*error*/
1383 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1384 pTemp += temp_len;
1385 temp_total_len += temp_len;
1386
1387 /*end AP marker*/
1388 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*last AP in batch scan response*/
1393 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1394 {
1395 /*end scan marker*/
1396 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1397 pTemp += temp_len;
1398 temp_total_len += temp_len;
1399
1400 /*end batch scan result marker*/
1401 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1402 pTemp += temp_len;
1403 temp_total_len += temp_len;
1404 }
1405
1406 if (temp_total_len < rem_len)
1407 {
1408 ret = temp_total_len + 1;
1409 strlcpy(pDest, temp, ret);
1410 pAdapter->isTruncated = FALSE;
1411 }
1412 else
1413 {
1414 pAdapter->isTruncated = TRUE;
1415 if (rem_len >= strlen("%%%%"))
1416 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001417 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301418 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001419 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301420 {
1421 ret = 0;
1422 }
1423 }
1424
1425 return ret;
1426
1427}/*End of hdd_format_batch_scan_rsp*/
1428
1429/**---------------------------------------------------------------------------
1430
1431 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1432 buffer starting with head of hdd batch scan response queue
1433
1434 \param - pAdapter Pointer to HDD adapter
1435 \param - pDest Pointer to user data buffer
1436 \param - cur_len current offset in user buffer
1437 \param - rem_len remaining no of bytes in user buffer
1438
1439 \return - number of bytes written in user buffer
1440
1441 --------------------------------------------------------------------------*/
1442
1443tANI_U32 hdd_populate_user_batch_scan_rsp
1444(
1445 hdd_adapter_t* pAdapter,
1446 tANI_U8 *pDest,
1447 tANI_U32 cur_len,
1448 tANI_U32 rem_len
1449)
1450{
1451 tHddBatchScanRsp *pHead;
1452 tHddBatchScanRsp *pPrev;
1453 tANI_U32 len;
1454
Kiet Lam34947452014-01-21 23:23:40 -08001455 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301456 pAdapter->isTruncated = FALSE;
1457
1458 /*head of hdd batch scan response queue*/
1459 pHead = pAdapter->pBatchScanRsp;
1460 while (pHead)
1461 {
1462 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1463 pAdapter);
1464 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001465 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301466 cur_len += len;
1467 if(TRUE == pAdapter->isTruncated)
1468 {
1469 /*result is truncated return rest of scan rsp in next req*/
1470 cur_len = rem_len;
1471 break;
1472 }
1473 pPrev = pHead;
1474 pHead = pHead->pNext;
1475 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001476 if (TRUE == pPrev->ApInfo.isLastAp)
1477 {
1478 pAdapter->prev_batch_id = 0;
1479 }
1480 else
1481 {
1482 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1483 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301484 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001485 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301486 }
1487
1488 return cur_len;
1489}/*End of hdd_populate_user_batch_scan_rsp*/
1490
1491/**---------------------------------------------------------------------------
1492
1493 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1494 scan response data from HDD queue to user space
1495 It does following in detail:
1496 a) if HDD has enough data in its queue then it 1st copies data to user
1497 space and then send get batch scan indication message to FW. In this
1498 case it does not wait on any event and batch scan response data will
1499 be populated in HDD response queue in MC thread context after receiving
1500 indication from FW
1501 b) else send get batch scan indication message to FW and wait on an event
1502 which will be set once HDD receives complete batch scan response from
1503 FW and then this function returns batch scan response to user space
1504
1505 \param - pAdapter Pointer to HDD adapter
1506 \param - pPrivData Pointer to priv_data
1507
1508 \return - 0 for success -EFAULT for failure
1509
1510 --------------------------------------------------------------------------*/
1511
1512int hdd_return_batch_scan_rsp_to_user
1513(
1514 hdd_adapter_t* pAdapter,
1515 hdd_priv_data_t *pPrivData,
1516 tANI_U8 *command
1517)
1518{
1519 tANI_U8 *pDest;
1520 tANI_U32 count = 0;
1521 tANI_U32 len = 0;
1522 tANI_U32 cur_len = 0;
1523 tANI_U32 rem_len = 0;
1524 eHalStatus halStatus;
1525 unsigned long rc;
1526 tSirTriggerBatchScanResultInd *pReq;
1527
1528 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1529 pReq->param = 0;/*batch scan client*/
1530 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1531 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1532
1533 cur_len = pPrivData->used_len;
1534 if (pPrivData->total_len > pPrivData->used_len)
1535 {
1536 rem_len = pPrivData->total_len - pPrivData->used_len;
1537 }
1538 else
1539 {
1540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1541 "%s: Invalid user data buffer total_len %d used_len %d",
1542 __func__, pPrivData->total_len, pPrivData->used_len);
1543 return -EFAULT;
1544 }
1545
1546 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1547 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1548 cur_len, rem_len);
1549 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1550
1551 /*enough scan result available in cache to return to user space or
1552 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001553 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301554 {
1555 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1556 halStatus = sme_TriggerBatchScanResultInd(
1557 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1558 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1559 pAdapter);
1560 if ( eHAL_STATUS_SUCCESS == halStatus )
1561 {
1562 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1563 {
1564 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1565 rc = wait_for_completion_timeout(
1566 &pAdapter->hdd_get_batch_scan_req_var,
1567 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1568 if (0 == rc)
1569 {
1570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1571 "%s: Timeout waiting to fetch batch scan rsp from fw",
1572 __func__);
1573 return -EFAULT;
1574 }
1575 }
1576
1577 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001578 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301579 pDest += len;
1580 cur_len += len;
1581
1582 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1583 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1584 cur_len, rem_len);
1585 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1586
1587 count = 0;
1588 len = (len - pPrivData->used_len);
1589 pDest = (command + pPrivData->used_len);
1590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001591 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301592 while(count < len)
1593 {
1594 printk("%c", *(pDest + count));
1595 count++;
1596 }
1597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: copy %d data to user buffer", __func__, len);
1599 if (copy_to_user(pPrivData->buf, pDest, len))
1600 {
1601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1602 "%s: failed to copy data to user buffer", __func__);
1603 return -EFAULT;
1604 }
1605 }
1606 else
1607 {
1608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1609 "sme_GetBatchScanScan returned failure halStatus %d",
1610 halStatus);
1611 return -EINVAL;
1612 }
1613 }
1614 else
1615 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301616 count = 0;
1617 len = (len - pPrivData->used_len);
1618 pDest = (command + pPrivData->used_len);
1619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001620 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301621 while(count < len)
1622 {
1623 printk("%c", *(pDest + count));
1624 count++;
1625 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001626 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1627 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301628 if (copy_to_user(pPrivData->buf, pDest, len))
1629 {
1630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1631 "%s: failed to copy data to user buffer", __func__);
1632 return -EFAULT;
1633 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301634 }
1635
1636 return 0;
1637} /*End of hdd_return_batch_scan_rsp_to_user*/
1638
Rajeev Kumar8b373292014-01-08 20:36:55 -08001639
1640/**---------------------------------------------------------------------------
1641
1642 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1643 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1644 WLS_BATCHING VERSION
1645 WLS_BATCHING SET
1646 WLS_BATCHING GET
1647 WLS_BATCHING STOP
1648
1649 \param - pAdapter Pointer to HDD adapter
1650 \param - pPrivdata Pointer to priv_data
1651 \param - command Pointer to command
1652
1653 \return - 0 for success -EFAULT for failure
1654
1655 --------------------------------------------------------------------------*/
1656
1657int hdd_handle_batch_scan_ioctl
1658(
1659 hdd_adapter_t *pAdapter,
1660 hdd_priv_data_t *pPrivdata,
1661 tANI_U8 *command
1662)
1663{
1664 int ret = 0;
1665
1666 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1667 {
1668 char extra[32];
1669 tANI_U8 len = 0;
1670 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1671
1672 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1673 {
1674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1675 "%s: Batch scan feature is not supported by FW", __func__);
1676 ret = -EINVAL;
1677 goto exit;
1678 }
1679
1680 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1681 version);
1682 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1683 {
1684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1685 "%s: failed to copy data to user buffer", __func__);
1686 ret = -EFAULT;
1687 goto exit;
1688 }
1689 ret = HDD_BATCH_SCAN_VERSION;
1690 }
1691 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1692 {
1693 int status;
1694 tANI_U8 *value = (command + 16);
1695 eHalStatus halStatus;
1696 unsigned long rc;
1697 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1698 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1699
1700 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1701 {
1702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1703 "%s: Batch scan feature is not supported by FW", __func__);
1704 ret = -EINVAL;
1705 goto exit;
1706 }
1707
1708 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1709 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1710 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1711 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1712 {
1713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1714 "Received WLS_BATCHING SET command in invalid mode %d "
1715 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1716 pAdapter->device_mode);
1717 ret = -EINVAL;
1718 goto exit;
1719 }
1720
1721 status = hdd_parse_set_batchscan_command(value, pReq);
1722 if (status)
1723 {
1724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1725 "Invalid WLS_BATCHING SET command");
1726 ret = -EINVAL;
1727 goto exit;
1728 }
1729
1730
1731 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1732 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1733 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1734 pAdapter);
1735
1736 if ( eHAL_STATUS_SUCCESS == halStatus )
1737 {
1738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1739 "sme_SetBatchScanReq returned success halStatus %d",
1740 halStatus);
1741 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1742 {
1743 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1744 rc = wait_for_completion_timeout(
1745 &pAdapter->hdd_set_batch_scan_req_var,
1746 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1747 if (0 == rc)
1748 {
1749 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1750 "%s: Timeout waiting for set batch scan to complete",
1751 __func__);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755 }
1756 if ( !pRsp->nScansToBatch )
1757 {
1758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1759 "%s: Received set batch scan failure response from FW",
1760 __func__);
1761 ret = -EINVAL;
1762 goto exit;
1763 }
1764 /*As per the Batch Scan Framework API we should return the MIN of
1765 either MSCAN or the max # of scans firmware can cache*/
1766 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1767
1768 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1769
1770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1771 "%s: request MSCAN %d response MSCAN %d ret %d",
1772 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1773 }
1774 else
1775 {
1776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1777 "sme_SetBatchScanReq returned failure halStatus %d",
1778 halStatus);
1779 ret = -EINVAL;
1780 goto exit;
1781 }
1782 }
1783 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1784 {
1785 eHalStatus halStatus;
1786 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1787 pInd->param = 0;
1788
1789 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1790 {
1791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1792 "%s: Batch scan feature is not supported by FW", __func__);
1793 ret = -EINVAL;
1794 goto exit;
1795 }
1796
1797 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1798 {
1799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 "Batch scan is not yet enabled batch scan state %d",
1801 pAdapter->batchScanState);
1802 ret = -EINVAL;
1803 goto exit;
1804 }
1805
1806 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1807
1808 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1809 pAdapter->sessionId);
1810 if ( eHAL_STATUS_SUCCESS == halStatus )
1811 {
1812 ret = 0;
1813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1814 "sme_StopBatchScanInd returned success halStatus %d",
1815 halStatus);
1816 }
1817 else
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "sme_StopBatchScanInd returned failure halStatus %d",
1821 halStatus);
1822 ret = -EINVAL;
1823 goto exit;
1824 }
1825 }
1826 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1827 {
1828 tANI_U32 remain_len;
1829
1830 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1831 {
1832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1833 "%s: Batch scan feature is not supported by FW", __func__);
1834 ret = -EINVAL;
1835 goto exit;
1836 }
1837
1838 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1839 {
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1841 "Batch scan is not yet enabled could not return results"
1842 "Batch Scan state %d",
1843 pAdapter->batchScanState);
1844 ret = -EINVAL;
1845 goto exit;
1846 }
1847
1848 pPrivdata->used_len = 16;
1849 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1850 if (remain_len < pPrivdata->total_len)
1851 {
1852 /*Clear previous batch scan response data if any*/
1853 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1854 }
1855 else
1856 {
1857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1858 "Invalid total length from user space can't fetch batch"
1859 " scan response total_len %d used_len %d remain len %d",
1860 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1861 ret = -EINVAL;
1862 goto exit;
1863 }
1864 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1865 }
1866
1867exit:
1868
1869 return ret;
1870}
1871
1872
Rajeev79dbe4c2013-10-05 11:03:42 +05301873#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1874
Jeff Johnson295189b2012-06-20 16:38:30 -07001875int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1876{
1877 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1878 hdd_priv_data_t priv_data;
1879 tANI_U8 *command = NULL;
1880 int ret = 0;
1881
1882 if (NULL == pAdapter)
1883 {
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001885 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001886 ret = -ENODEV;
1887 goto exit;
1888 }
1889
Jeff Johnsone7245742012-09-05 17:12:55 -07001890 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001891 {
1892 ret = -EINVAL;
1893 goto exit;
1894 }
1895
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001896 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1897 {
1898 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1899 "%s:LOGP in Progress. Ignore!!!", __func__);
1900 ret = -EBUSY;
1901 goto exit;
1902 }
1903
Jeff Johnson295189b2012-06-20 16:38:30 -07001904 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1905 {
1906 ret = -EFAULT;
1907 goto exit;
1908 }
1909
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08001910 if (priv_data.total_len <= 0 ||
1911 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001912 {
1913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1914 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1915 priv_data.total_len);
1916 ret = -EINVAL;
1917 goto exit;
1918 }
1919
1920 /* Allocate +1 for '\0' */
1921 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 if (!command)
1923 {
1924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001925 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 ret = -ENOMEM;
1927 goto exit;
1928 }
1929
1930 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1931 {
1932 ret = -EFAULT;
1933 goto exit;
1934 }
1935
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001936 /* Making sure the command is NUL-terminated */
1937 command[priv_data.total_len] = '\0';
1938
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 if ((SIOCDEVPRIVATE + 1) == cmd)
1940 {
1941 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1942
1943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001944 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001945
1946 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1947 {
1948 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1949 sizeof(tSirMacAddr)))
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001952 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001953 ret = -EFAULT;
1954 }
1955 }
Amar Singhal0974e402013-02-12 14:27:46 -08001956 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 {
Amar Singhal0974e402013-02-12 14:27:46 -08001958 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001959 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001960
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001962
1963 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001964 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001965 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001966 "%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 -07001967 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001968 ret = hdd_setBand_helper(dev, ptr);
1969 }
Kiet Lamf040f472013-11-20 21:15:23 +05301970 else if(strncmp(command, "SETWMMPS", 8) == 0)
1971 {
1972 tANI_U8 *ptr = command;
1973 ret = hdd_wmmps_helper(pAdapter, ptr);
1974 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001975 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1976 {
1977 char *country_code;
1978
1979 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001980
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001981 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001982 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001983#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301984 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001985#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001986 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1987 (void *)(tSmeChangeCountryCallback)
1988 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301989 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001990 if (eHAL_STATUS_SUCCESS == ret)
1991 {
1992 ret = wait_for_completion_interruptible_timeout(
1993 &pAdapter->change_country_code,
1994 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1995 if (0 >= ret)
1996 {
1997 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1998 __func__);
1999 }
2000 }
2001 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002002 {
2003 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002004 "%s: SME Change Country code fail ret=%d", __func__, ret);
2005 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002006 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002007
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002008 }
2009 /*
2010 command should be a string having format
2011 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2012 */
Amar Singhal0974e402013-02-12 14:27:46 -08002013 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002014 {
Amar Singhal0974e402013-02-12 14:27:46 -08002015 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002016
2017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002018 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002019
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002020 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002021 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002022 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2023 {
2024 int suspend = 0;
2025 tANI_U8 *ptr = (tANI_U8*)command + 15;
2026
2027 suspend = *ptr - '0';
2028 hdd_set_wlan_suspend_mode(suspend);
2029 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002030#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2031 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2032 {
2033 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002034 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002035 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2036 eHalStatus status = eHAL_STATUS_SUCCESS;
2037
2038 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2039 value = value + 15;
2040
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002041 /* Convert the value from ascii to integer */
2042 ret = kstrtos8(value, 10, &rssi);
2043 if (ret < 0)
2044 {
2045 /* If the input value is greater than max value of datatype, then also
2046 kstrtou8 fails */
2047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2048 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002049 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002050 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2051 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2052 ret = -EINVAL;
2053 goto exit;
2054 }
2055
Srinivas Girigowdade697412013-02-14 16:31:48 -08002056 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002057
Srinivas Girigowdade697412013-02-14 16:31:48 -08002058 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2059 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2060 {
2061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2062 "Neighbor lookup threshold value %d is out of range"
2063 " (Min: %d Max: %d)", lookUpThreshold,
2064 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2065 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2066 ret = -EINVAL;
2067 goto exit;
2068 }
2069
2070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2071 "%s: Received Command to Set Roam trigger"
2072 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2073
2074 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2075 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2076 if (eHAL_STATUS_SUCCESS != status)
2077 {
2078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2079 "%s: Failed to set roam trigger, try again", __func__);
2080 ret = -EPERM;
2081 goto exit;
2082 }
2083
2084 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2085 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2086 }
2087 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2088 {
2089 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2090 int rssi = (-1) * lookUpThreshold;
2091 char extra[32];
2092 tANI_U8 len = 0;
2093
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002094 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002095 if (copy_to_user(priv_data.buf, &extra, len + 1))
2096 {
2097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2098 "%s: failed to copy data to user buffer", __func__);
2099 ret = -EFAULT;
2100 goto exit;
2101 }
2102 }
2103 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2104 {
2105 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002106 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002107 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002108
Srinivas Girigowdade697412013-02-14 16:31:48 -08002109 /* input refresh period is in terms of seconds */
2110 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2111 value = value + 18;
2112 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002113 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002114 if (ret < 0)
2115 {
2116 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002117 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002118 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002119 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002120 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002121 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2122 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002123 ret = -EINVAL;
2124 goto exit;
2125 }
2126
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002127 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2128 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002129 {
2130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002131 "Roam scan period value %d is out of range"
2132 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002133 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2134 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002135 ret = -EINVAL;
2136 goto exit;
2137 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002138 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002139
2140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2141 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002142 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002143
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002144 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2145 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002146 }
2147 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2148 {
2149 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2150 char extra[32];
2151 tANI_U8 len = 0;
2152
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002153 len = scnprintf(extra, sizeof(extra), "%s %d",
2154 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002155 /* Returned value is in units of seconds */
2156 if (copy_to_user(priv_data.buf, &extra, len + 1))
2157 {
2158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2159 "%s: failed to copy data to user buffer", __func__);
2160 ret = -EFAULT;
2161 goto exit;
2162 }
2163 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002164 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2165 {
2166 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002167 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002168 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002169
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002170 /* input refresh period is in terms of seconds */
2171 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2172 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002173
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002174 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002175 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002176 if (ret < 0)
2177 {
2178 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002179 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002181 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002182 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002183 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2184 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2185 ret = -EINVAL;
2186 goto exit;
2187 }
2188
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002189 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2190 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2191 {
2192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2193 "Neighbor scan results refresh period value %d is out of range"
2194 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2195 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2196 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2197 ret = -EINVAL;
2198 goto exit;
2199 }
2200 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2201
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2203 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002204 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002205
2206 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2207 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2208 }
2209 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2210 {
2211 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2212 char extra[32];
2213 tANI_U8 len = 0;
2214
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002215 len = scnprintf(extra, sizeof(extra), "%s %d",
2216 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002217 /* Returned value is in units of seconds */
2218 if (copy_to_user(priv_data.buf, &extra, len + 1))
2219 {
2220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2221 "%s: failed to copy data to user buffer", __func__);
2222 ret = -EFAULT;
2223 goto exit;
2224 }
2225 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002226#ifdef FEATURE_WLAN_LFR
2227 /* SETROAMMODE */
2228 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2229 {
2230 tANI_U8 *value = command;
2231 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2232
2233 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2234 value = value + SIZE_OF_SETROAMMODE + 1;
2235
2236 /* Convert the value from ascii to integer */
2237 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2238 if (ret < 0)
2239 {
2240 /* If the input value is greater than max value of datatype, then also
2241 kstrtou8 fails */
2242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2243 "%s: kstrtou8 failed range [%d - %d]", __func__,
2244 CFG_LFR_FEATURE_ENABLED_MIN,
2245 CFG_LFR_FEATURE_ENABLED_MAX);
2246 ret = -EINVAL;
2247 goto exit;
2248 }
2249 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2250 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2251 {
2252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2253 "Roam Mode value %d is out of range"
2254 " (Min: %d Max: %d)", roamMode,
2255 CFG_LFR_FEATURE_ENABLED_MIN,
2256 CFG_LFR_FEATURE_ENABLED_MAX);
2257 ret = -EINVAL;
2258 goto exit;
2259 }
2260
2261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2262 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2263 /*
2264 * Note that
2265 * SETROAMMODE 0 is to enable LFR while
2266 * SETROAMMODE 1 is to disable LFR, but
2267 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2268 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2269 */
2270 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2271 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2272 else
2273 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2274
2275 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2276 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2277 }
2278 /* GETROAMMODE */
2279 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2280 {
2281 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2282 char extra[32];
2283 tANI_U8 len = 0;
2284
2285 /*
2286 * roamMode value shall be inverted because the sementics is different.
2287 */
2288 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2289 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2290 else
2291 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2292
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002293 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002294 if (copy_to_user(priv_data.buf, &extra, len + 1))
2295 {
2296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2297 "%s: failed to copy data to user buffer", __func__);
2298 ret = -EFAULT;
2299 goto exit;
2300 }
2301 }
2302#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002303#endif
2304#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2305 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2306 {
2307 tANI_U8 *value = command;
2308 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2309
2310 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2311 value = value + 13;
2312 /* Convert the value from ascii to integer */
2313 ret = kstrtou8(value, 10, &roamRssiDiff);
2314 if (ret < 0)
2315 {
2316 /* If the input value is greater than max value of datatype, then also
2317 kstrtou8 fails */
2318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2319 "%s: kstrtou8 failed range [%d - %d]", __func__,
2320 CFG_ROAM_RSSI_DIFF_MIN,
2321 CFG_ROAM_RSSI_DIFF_MAX);
2322 ret = -EINVAL;
2323 goto exit;
2324 }
2325
2326 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2327 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2328 {
2329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2330 "Roam rssi diff value %d is out of range"
2331 " (Min: %d Max: %d)", roamRssiDiff,
2332 CFG_ROAM_RSSI_DIFF_MIN,
2333 CFG_ROAM_RSSI_DIFF_MAX);
2334 ret = -EINVAL;
2335 goto exit;
2336 }
2337
2338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2339 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2340
2341 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2342 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2343 }
2344 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2345 {
2346 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2347 char extra[32];
2348 tANI_U8 len = 0;
2349
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002350 len = scnprintf(extra, sizeof(extra), "%s %d",
2351 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002352 if (copy_to_user(priv_data.buf, &extra, len + 1))
2353 {
2354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2355 "%s: failed to copy data to user buffer", __func__);
2356 ret = -EFAULT;
2357 goto exit;
2358 }
2359 }
2360#endif
2361#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2362 else if (strncmp(command, "GETBAND", 7) == 0)
2363 {
2364 int band = -1;
2365 char extra[32];
2366 tANI_U8 len = 0;
2367 hdd_getBand_helper(pHddCtx, &band);
2368
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002369 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 if (copy_to_user(priv_data.buf, &extra, len + 1))
2371 {
2372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2373 "%s: failed to copy data to user buffer", __func__);
2374 ret = -EFAULT;
2375 goto exit;
2376 }
2377 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002378 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2379 {
2380 tANI_U8 *value = command;
2381 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2382 tANI_U8 numChannels = 0;
2383 eHalStatus status = eHAL_STATUS_SUCCESS;
2384
2385 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2386 if (eHAL_STATUS_SUCCESS != status)
2387 {
2388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2389 "%s: Failed to parse channel list information", __func__);
2390 ret = -EINVAL;
2391 goto exit;
2392 }
2393
2394 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2395 {
2396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2397 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2398 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2399 ret = -EINVAL;
2400 goto exit;
2401 }
2402 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2403 numChannels);
2404 if (eHAL_STATUS_SUCCESS != status)
2405 {
2406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2407 "%s: Failed to update channel list information", __func__);
2408 ret = -EINVAL;
2409 goto exit;
2410 }
2411 }
2412 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2413 {
2414 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2415 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002416 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002417 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002418 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002419
2420 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2421 ChannelList, &numChannels ))
2422 {
2423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2424 "%s: failed to get roam scan channel list", __func__);
2425 ret = -EFAULT;
2426 goto exit;
2427 }
2428 /* output channel list is of the format
2429 [Number of roam scan channels][Channel1][Channel2]... */
2430 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002431 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002432 for (j = 0; (j < numChannels); j++)
2433 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002434 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2435 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002436 }
2437
2438 if (copy_to_user(priv_data.buf, &extra, len + 1))
2439 {
2440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2441 "%s: failed to copy data to user buffer", __func__);
2442 ret = -EFAULT;
2443 goto exit;
2444 }
2445 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002446 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2447 {
2448 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2449 char extra[32];
2450 tANI_U8 len = 0;
2451
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002452 /* Check if the features OKC/CCX/11R are supported simultaneously,
2453 then this operation is not permitted (return FAILURE) */
2454 if (ccxMode &&
2455 hdd_is_okc_mode_enabled(pHddCtx) &&
2456 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2457 {
2458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2459 "%s: OKC/CCX/11R are supported simultaneously"
2460 " hence this operation is not permitted!", __func__);
2461 ret = -EPERM;
2462 goto exit;
2463 }
2464
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002465 len = scnprintf(extra, sizeof(extra), "%s %d",
2466 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002467 if (copy_to_user(priv_data.buf, &extra, len + 1))
2468 {
2469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2470 "%s: failed to copy data to user buffer", __func__);
2471 ret = -EFAULT;
2472 goto exit;
2473 }
2474 }
2475 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2476 {
2477 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2478 char extra[32];
2479 tANI_U8 len = 0;
2480
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002481 /* Check if the features OKC/CCX/11R are supported simultaneously,
2482 then this operation is not permitted (return FAILURE) */
2483 if (okcMode &&
2484 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2485 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2486 {
2487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2488 "%s: OKC/CCX/11R are supported simultaneously"
2489 " hence this operation is not permitted!", __func__);
2490 ret = -EPERM;
2491 goto exit;
2492 }
2493
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002494 len = scnprintf(extra, sizeof(extra), "%s %d",
2495 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002496 if (copy_to_user(priv_data.buf, &extra, len + 1))
2497 {
2498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2499 "%s: failed to copy data to user buffer", __func__);
2500 ret = -EFAULT;
2501 goto exit;
2502 }
2503 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002504 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002505 {
2506 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2507 char extra[32];
2508 tANI_U8 len = 0;
2509
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002510 len = scnprintf(extra, sizeof(extra), "%s %d",
2511 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002512 if (copy_to_user(priv_data.buf, &extra, len + 1))
2513 {
2514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2515 "%s: failed to copy data to user buffer", __func__);
2516 ret = -EFAULT;
2517 goto exit;
2518 }
2519 }
2520 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2521 {
2522 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2523 char extra[32];
2524 tANI_U8 len = 0;
2525
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002526 len = scnprintf(extra, sizeof(extra), "%s %d",
2527 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002528 if (copy_to_user(priv_data.buf, &extra, len + 1))
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2531 "%s: failed to copy data to user buffer", __func__);
2532 ret = -EFAULT;
2533 goto exit;
2534 }
2535 }
2536 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2537 {
2538 tANI_U8 *value = command;
2539 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2540
2541 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2542 value = value + 26;
2543 /* Convert the value from ascii to integer */
2544 ret = kstrtou8(value, 10, &minTime);
2545 if (ret < 0)
2546 {
2547 /* If the input value is greater than max value of datatype, then also
2548 kstrtou8 fails */
2549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2550 "%s: kstrtou8 failed range [%d - %d]", __func__,
2551 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2552 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2553 ret = -EINVAL;
2554 goto exit;
2555 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002556 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2557 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2558 {
2559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2560 "scan min channel time value %d is out of range"
2561 " (Min: %d Max: %d)", minTime,
2562 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2563 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2564 ret = -EINVAL;
2565 goto exit;
2566 }
2567
2568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2569 "%s: Received Command to change channel min time = %d", __func__, minTime);
2570
2571 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2572 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2573 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002574 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2575 {
2576 tANI_U8 *value = command;
2577 tANI_U8 channel = 0;
2578 tANI_U8 dwellTime = 0;
2579 tANI_U8 bufLen = 0;
2580 tANI_U8 *buf = NULL;
2581 tSirMacAddr targetApBssid;
2582 eHalStatus status = eHAL_STATUS_SUCCESS;
2583 struct ieee80211_channel chan;
2584 tANI_U8 finalLen = 0;
2585 tANI_U8 *finalBuf = NULL;
2586 tANI_U8 temp = 0;
2587 u64 cookie;
2588 hdd_station_ctx_t *pHddStaCtx = NULL;
2589 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2590
2591 /* if not associated, no need to send action frame */
2592 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2593 {
2594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2595 ret = -EINVAL;
2596 goto exit;
2597 }
2598
2599 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2600 &dwellTime, &buf, &bufLen);
2601 if (eHAL_STATUS_SUCCESS != status)
2602 {
2603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2604 "%s: Failed to parse send action frame data", __func__);
2605 ret = -EINVAL;
2606 goto exit;
2607 }
2608
2609 /* if the target bssid is different from currently associated AP,
2610 then no need to send action frame */
2611 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2612 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2613 {
2614 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2615 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002616 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002617 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002618 goto exit;
2619 }
2620
2621 /* if the channel number is different from operating channel then
2622 no need to send action frame */
2623 if (channel != pHddStaCtx->conn_info.operationChannel)
2624 {
2625 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2626 "%s: channel(%d) is different from operating channel(%d)",
2627 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2628 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002629 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002630 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002631 goto exit;
2632 }
2633 chan.center_freq = sme_ChnToFreq(channel);
2634
2635 finalLen = bufLen + 24;
2636 finalBuf = vos_mem_malloc(finalLen);
2637 if (NULL == finalBuf)
2638 {
2639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2640 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002641 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002642 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002643 goto exit;
2644 }
2645 vos_mem_zero(finalBuf, finalLen);
2646
2647 /* Fill subtype */
2648 temp = SIR_MAC_MGMT_ACTION << 4;
2649 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2650
2651 /* Fill type */
2652 temp = SIR_MAC_MGMT_FRAME;
2653 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2654
2655 /* Fill destination address (bssid of the AP) */
2656 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2657
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002658 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002659 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2660
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002661 /* Fill BSSID (AP mac address) */
2662 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002663
2664 /* Fill received buffer from 24th address */
2665 vos_mem_copy(finalBuf + 24, buf, bufLen);
2666
Jeff Johnson11c33152013-04-16 17:52:40 -07002667 /* done with the parsed buffer */
2668 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002669 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002670
Yue Maf49ba872013-08-19 12:04:25 -07002671 wlan_hdd_action( NULL,
2672#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2673 &(pAdapter->wdev),
2674#else
2675 dev,
2676#endif
2677 &chan, 0,
2678#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2679 NL80211_CHAN_HT20, 1,
2680#endif
2681 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002682 1, &cookie );
2683 vos_mem_free(finalBuf);
2684 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002685 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2686 {
2687 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2688 char extra[32];
2689 tANI_U8 len = 0;
2690
2691 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002692 len = scnprintf(extra, sizeof(extra), "%s %d",
2693 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002694 if (copy_to_user(priv_data.buf, &extra, len + 1))
2695 {
2696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2697 "%s: failed to copy data to user buffer", __func__);
2698 ret = -EFAULT;
2699 goto exit;
2700 }
2701 }
2702 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2703 {
2704 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002705 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002706
2707 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2708 value = value + 19;
2709 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002710 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002711 if (ret < 0)
2712 {
2713 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002714 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002716 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002717 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2718 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2719 ret = -EINVAL;
2720 goto exit;
2721 }
2722
2723 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2724 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2725 {
2726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2727 "lfr mode value %d is out of range"
2728 " (Min: %d Max: %d)", maxTime,
2729 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2730 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2731 ret = -EINVAL;
2732 goto exit;
2733 }
2734
2735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2736 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2737
2738 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2739 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2740 }
2741 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2742 {
2743 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2744 char extra[32];
2745 tANI_U8 len = 0;
2746
2747 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002748 len = scnprintf(extra, sizeof(extra), "%s %d",
2749 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002750 if (copy_to_user(priv_data.buf, &extra, len + 1))
2751 {
2752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2753 "%s: failed to copy data to user buffer", __func__);
2754 ret = -EFAULT;
2755 goto exit;
2756 }
2757 }
2758 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2759 {
2760 tANI_U8 *value = command;
2761 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2762
2763 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2764 value = value + 16;
2765 /* Convert the value from ascii to integer */
2766 ret = kstrtou16(value, 10, &val);
2767 if (ret < 0)
2768 {
2769 /* If the input value is greater than max value of datatype, then also
2770 kstrtou16 fails */
2771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2772 "%s: kstrtou16 failed range [%d - %d]", __func__,
2773 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2774 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2775 ret = -EINVAL;
2776 goto exit;
2777 }
2778
2779 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2780 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2781 {
2782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2783 "scan home time value %d is out of range"
2784 " (Min: %d Max: %d)", val,
2785 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2786 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2787 ret = -EINVAL;
2788 goto exit;
2789 }
2790
2791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2792 "%s: Received Command to change scan home time = %d", __func__, val);
2793
2794 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2795 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2796 }
2797 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2798 {
2799 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2800 char extra[32];
2801 tANI_U8 len = 0;
2802
2803 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002804 len = scnprintf(extra, sizeof(extra), "%s %d",
2805 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002806 if (copy_to_user(priv_data.buf, &extra, len + 1))
2807 {
2808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2809 "%s: failed to copy data to user buffer", __func__);
2810 ret = -EFAULT;
2811 goto exit;
2812 }
2813 }
2814 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2815 {
2816 tANI_U8 *value = command;
2817 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2818
2819 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2820 value = value + 17;
2821 /* Convert the value from ascii to integer */
2822 ret = kstrtou8(value, 10, &val);
2823 if (ret < 0)
2824 {
2825 /* If the input value is greater than max value of datatype, then also
2826 kstrtou8 fails */
2827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2828 "%s: kstrtou8 failed range [%d - %d]", __func__,
2829 CFG_ROAM_INTRA_BAND_MIN,
2830 CFG_ROAM_INTRA_BAND_MAX);
2831 ret = -EINVAL;
2832 goto exit;
2833 }
2834
2835 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2836 (val > CFG_ROAM_INTRA_BAND_MAX))
2837 {
2838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2839 "intra band mode value %d is out of range"
2840 " (Min: %d Max: %d)", val,
2841 CFG_ROAM_INTRA_BAND_MIN,
2842 CFG_ROAM_INTRA_BAND_MAX);
2843 ret = -EINVAL;
2844 goto exit;
2845 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2847 "%s: Received Command to change intra band = %d", __func__, val);
2848
2849 pHddCtx->cfg_ini->nRoamIntraBand = val;
2850 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2851 }
2852 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2853 {
2854 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2855 char extra[32];
2856 tANI_U8 len = 0;
2857
2858 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002859 len = scnprintf(extra, sizeof(extra), "%s %d",
2860 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002861 if (copy_to_user(priv_data.buf, &extra, len + 1))
2862 {
2863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2864 "%s: failed to copy data to user buffer", __func__);
2865 ret = -EFAULT;
2866 goto exit;
2867 }
2868 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002869 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2870 {
2871 tANI_U8 *value = command;
2872 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2873
2874 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2875 value = value + 15;
2876 /* Convert the value from ascii to integer */
2877 ret = kstrtou8(value, 10, &nProbes);
2878 if (ret < 0)
2879 {
2880 /* If the input value is greater than max value of datatype, then also
2881 kstrtou8 fails */
2882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2883 "%s: kstrtou8 failed range [%d - %d]", __func__,
2884 CFG_ROAM_SCAN_N_PROBES_MIN,
2885 CFG_ROAM_SCAN_N_PROBES_MAX);
2886 ret = -EINVAL;
2887 goto exit;
2888 }
2889
2890 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2891 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2892 {
2893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2894 "NProbes value %d is out of range"
2895 " (Min: %d Max: %d)", nProbes,
2896 CFG_ROAM_SCAN_N_PROBES_MIN,
2897 CFG_ROAM_SCAN_N_PROBES_MAX);
2898 ret = -EINVAL;
2899 goto exit;
2900 }
2901
2902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2903 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2904
2905 pHddCtx->cfg_ini->nProbes = nProbes;
2906 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2907 }
2908 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2909 {
2910 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2911 char extra[32];
2912 tANI_U8 len = 0;
2913
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002914 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002915 if (copy_to_user(priv_data.buf, &extra, len + 1))
2916 {
2917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2918 "%s: failed to copy data to user buffer", __func__);
2919 ret = -EFAULT;
2920 goto exit;
2921 }
2922 }
2923 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2924 {
2925 tANI_U8 *value = command;
2926 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2927
2928 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2929 /* input value is in units of msec */
2930 value = value + 20;
2931 /* Convert the value from ascii to integer */
2932 ret = kstrtou16(value, 10, &homeAwayTime);
2933 if (ret < 0)
2934 {
2935 /* If the input value is greater than max value of datatype, then also
2936 kstrtou8 fails */
2937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2938 "%s: kstrtou8 failed range [%d - %d]", __func__,
2939 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2940 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2941 ret = -EINVAL;
2942 goto exit;
2943 }
2944
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002945 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2946 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2947 {
2948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2949 "homeAwayTime value %d is out of range"
2950 " (Min: %d Max: %d)", homeAwayTime,
2951 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2952 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2953 ret = -EINVAL;
2954 goto exit;
2955 }
2956
2957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2958 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002959 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2960 {
2961 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2962 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2963 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002964 }
2965 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2966 {
2967 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2968 char extra[32];
2969 tANI_U8 len = 0;
2970
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002971 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002972 if (copy_to_user(priv_data.buf, &extra, len + 1))
2973 {
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2975 "%s: failed to copy data to user buffer", __func__);
2976 ret = -EFAULT;
2977 goto exit;
2978 }
2979 }
2980 else if (strncmp(command, "REASSOC", 7) == 0)
2981 {
2982 tANI_U8 *value = command;
2983 tANI_U8 channel = 0;
2984 tSirMacAddr targetApBssid;
2985 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002986#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2987 tCsrHandoffRequest handoffInfo;
2988#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002989 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002990 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2991
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002992 /* if not associated, no need to proceed with reassoc */
2993 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2994 {
2995 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2996 ret = -EINVAL;
2997 goto exit;
2998 }
2999
3000 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3001 if (eHAL_STATUS_SUCCESS != status)
3002 {
3003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3004 "%s: Failed to parse reassoc command data", __func__);
3005 ret = -EINVAL;
3006 goto exit;
3007 }
3008
3009 /* if the target bssid is same as currently associated AP,
3010 then no need to proceed with reassoc */
3011 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3012 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3013 {
3014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3015 ret = -EINVAL;
3016 goto exit;
3017 }
3018
3019 /* Check channel number is a valid channel number */
3020 if(VOS_STATUS_SUCCESS !=
3021 wlan_hdd_validate_operation_channel(pAdapter, channel))
3022 {
3023 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003024 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003025 return -EINVAL;
3026 }
3027
3028 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003029#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3030 handoffInfo.channel = channel;
3031 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3032 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3033#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003034 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003035 else if (strncmp(command, "SETWESMODE", 10) == 0)
3036 {
3037 tANI_U8 *value = command;
3038 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3039
3040 /* Move pointer to ahead of SETWESMODE<delimiter> */
3041 value = value + 11;
3042 /* Convert the value from ascii to integer */
3043 ret = kstrtou8(value, 10, &wesMode);
3044 if (ret < 0)
3045 {
3046 /* If the input value is greater than max value of datatype, then also
3047 kstrtou8 fails */
3048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3049 "%s: kstrtou8 failed range [%d - %d]", __func__,
3050 CFG_ENABLE_WES_MODE_NAME_MIN,
3051 CFG_ENABLE_WES_MODE_NAME_MAX);
3052 ret = -EINVAL;
3053 goto exit;
3054 }
3055
3056 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3057 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3058 {
3059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3060 "WES Mode value %d is out of range"
3061 " (Min: %d Max: %d)", wesMode,
3062 CFG_ENABLE_WES_MODE_NAME_MIN,
3063 CFG_ENABLE_WES_MODE_NAME_MAX);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3068 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3069
3070 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3071 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3072 }
3073 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3074 {
3075 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3076 char extra[32];
3077 tANI_U8 len = 0;
3078
Arif Hussain826d9412013-11-12 16:44:54 -08003079 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003080 if (copy_to_user(priv_data.buf, &extra, len + 1))
3081 {
3082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3083 "%s: failed to copy data to user buffer", __func__);
3084 ret = -EFAULT;
3085 goto exit;
3086 }
3087 }
3088#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003089#ifdef FEATURE_WLAN_LFR
3090 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3091 {
3092 tANI_U8 *value = command;
3093 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3094
3095 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3096 value = value + 12;
3097 /* Convert the value from ascii to integer */
3098 ret = kstrtou8(value, 10, &lfrMode);
3099 if (ret < 0)
3100 {
3101 /* If the input value is greater than max value of datatype, then also
3102 kstrtou8 fails */
3103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3104 "%s: kstrtou8 failed range [%d - %d]", __func__,
3105 CFG_LFR_FEATURE_ENABLED_MIN,
3106 CFG_LFR_FEATURE_ENABLED_MAX);
3107 ret = -EINVAL;
3108 goto exit;
3109 }
3110
3111 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3112 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3113 {
3114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3115 "lfr mode value %d is out of range"
3116 " (Min: %d Max: %d)", lfrMode,
3117 CFG_LFR_FEATURE_ENABLED_MIN,
3118 CFG_LFR_FEATURE_ENABLED_MAX);
3119 ret = -EINVAL;
3120 goto exit;
3121 }
3122
3123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3124 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3125
3126 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3127 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3128 }
3129#endif
3130#ifdef WLAN_FEATURE_VOWIFI_11R
3131 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3132 {
3133 tANI_U8 *value = command;
3134 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3135
3136 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3137 value = value + 18;
3138 /* Convert the value from ascii to integer */
3139 ret = kstrtou8(value, 10, &ft);
3140 if (ret < 0)
3141 {
3142 /* If the input value is greater than max value of datatype, then also
3143 kstrtou8 fails */
3144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3145 "%s: kstrtou8 failed range [%d - %d]", __func__,
3146 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3147 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3148 ret = -EINVAL;
3149 goto exit;
3150 }
3151
3152 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3153 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3154 {
3155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3156 "ft mode value %d is out of range"
3157 " (Min: %d Max: %d)", ft,
3158 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3159 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3160 ret = -EINVAL;
3161 goto exit;
3162 }
3163
3164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3165 "%s: Received Command to change ft mode = %d", __func__, ft);
3166
3167 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3168 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3169 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303170
3171 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3172 {
3173 tANI_U8 *value = command;
3174 tSirMacAddr targetApBssid;
3175 tANI_U8 trigger = 0;
3176 eHalStatus status = eHAL_STATUS_SUCCESS;
3177 hdd_station_ctx_t *pHddStaCtx = NULL;
3178 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3179
3180 /* if not associated, no need to proceed with reassoc */
3181 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3182 {
3183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3184 ret = -EINVAL;
3185 goto exit;
3186 }
3187
3188 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3189 if (eHAL_STATUS_SUCCESS != status)
3190 {
3191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3192 "%s: Failed to parse reassoc command data", __func__);
3193 ret = -EINVAL;
3194 goto exit;
3195 }
3196
3197 /* if the target bssid is same as currently associated AP,
3198 then no need to proceed with reassoc */
3199 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3200 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3201 {
3202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3203 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3204 __func__);
3205 ret = -EINVAL;
3206 goto exit;
3207 }
3208
3209 /* Proceed with scan/roam */
3210 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3211 &targetApBssid[0],
3212 (tSmeFastRoamTrigger)(trigger));
3213 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003214#endif
3215#ifdef FEATURE_WLAN_CCX
3216 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3217 {
3218 tANI_U8 *value = command;
3219 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
3220
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003221 /* Check if the features OKC/CCX/11R are supported simultaneously,
3222 then this operation is not permitted (return FAILURE) */
3223 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3224 hdd_is_okc_mode_enabled(pHddCtx) &&
3225 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3226 {
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3228 "%s: OKC/CCX/11R are supported simultaneously"
3229 " hence this operation is not permitted!", __func__);
3230 ret = -EPERM;
3231 goto exit;
3232 }
3233
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003234 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3235 value = value + 11;
3236 /* Convert the value from ascii to integer */
3237 ret = kstrtou8(value, 10, &ccxMode);
3238 if (ret < 0)
3239 {
3240 /* If the input value is greater than max value of datatype, then also
3241 kstrtou8 fails */
3242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3243 "%s: kstrtou8 failed range [%d - %d]", __func__,
3244 CFG_CCX_FEATURE_ENABLED_MIN,
3245 CFG_CCX_FEATURE_ENABLED_MAX);
3246 ret = -EINVAL;
3247 goto exit;
3248 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003249 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3250 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3251 {
3252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3253 "Ccx mode value %d is out of range"
3254 " (Min: %d Max: %d)", ccxMode,
3255 CFG_CCX_FEATURE_ENABLED_MIN,
3256 CFG_CCX_FEATURE_ENABLED_MAX);
3257 ret = -EINVAL;
3258 goto exit;
3259 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3261 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3262
3263 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3264 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3265 }
3266#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003267 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3268 {
3269 tANI_U8 *value = command;
3270 tANI_BOOLEAN roamScanControl = 0;
3271
3272 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3273 value = value + 19;
3274 /* Convert the value from ascii to integer */
3275 ret = kstrtou8(value, 10, &roamScanControl);
3276 if (ret < 0)
3277 {
3278 /* If the input value is greater than max value of datatype, then also
3279 kstrtou8 fails */
3280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3281 "%s: kstrtou8 failed ", __func__);
3282 ret = -EINVAL;
3283 goto exit;
3284 }
3285
3286 if (0 != roamScanControl)
3287 {
3288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3289 "roam scan control invalid value = %d",
3290 roamScanControl);
3291 ret = -EINVAL;
3292 goto exit;
3293 }
3294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3295 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3296
3297 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3298 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003299#ifdef FEATURE_WLAN_OKC
3300 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3301 {
3302 tANI_U8 *value = command;
3303 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3304
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003305 /* Check if the features OKC/CCX/11R are supported simultaneously,
3306 then this operation is not permitted (return FAILURE) */
3307 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3308 hdd_is_okc_mode_enabled(pHddCtx) &&
3309 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3310 {
3311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3312 "%s: OKC/CCX/11R are supported simultaneously"
3313 " hence this operation is not permitted!", __func__);
3314 ret = -EPERM;
3315 goto exit;
3316 }
3317
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003318 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3319 value = value + 11;
3320 /* Convert the value from ascii to integer */
3321 ret = kstrtou8(value, 10, &okcMode);
3322 if (ret < 0)
3323 {
3324 /* If the input value is greater than max value of datatype, then also
3325 kstrtou8 fails */
3326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3327 "%s: kstrtou8 failed range [%d - %d]", __func__,
3328 CFG_OKC_FEATURE_ENABLED_MIN,
3329 CFG_OKC_FEATURE_ENABLED_MAX);
3330 ret = -EINVAL;
3331 goto exit;
3332 }
3333
3334 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3335 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3336 {
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3338 "Okc mode value %d is out of range"
3339 " (Min: %d Max: %d)", okcMode,
3340 CFG_OKC_FEATURE_ENABLED_MIN,
3341 CFG_OKC_FEATURE_ENABLED_MAX);
3342 ret = -EINVAL;
3343 goto exit;
3344 }
3345
3346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3347 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3348
3349 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3350 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003351#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003352 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3353 {
3354 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3355 char extra[32];
3356 tANI_U8 len = 0;
3357
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003358 len = scnprintf(extra, sizeof(extra), "%s %d",
3359 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003360 if (copy_to_user(priv_data.buf, &extra, len + 1))
3361 {
3362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3363 "%s: failed to copy data to user buffer", __func__);
3364 ret = -EFAULT;
3365 goto exit;
3366 }
3367 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303368#ifdef WLAN_FEATURE_PACKET_FILTERING
3369 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3370 {
3371 tANI_U8 filterType = 0;
3372 tANI_U8 *value = command;
3373
3374 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3375 value = value + 22;
3376
3377 /* Convert the value from ascii to integer */
3378 ret = kstrtou8(value, 10, &filterType);
3379 if (ret < 0)
3380 {
3381 /* If the input value is greater than max value of datatype,
3382 * then also kstrtou8 fails
3383 */
3384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3385 "%s: kstrtou8 failed range ", __func__);
3386 ret = -EINVAL;
3387 goto exit;
3388 }
3389
3390 if (filterType != 0 && filterType != 1)
3391 {
3392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3393 "%s: Accepted Values are 0 and 1 ", __func__);
3394 ret = -EINVAL;
3395 goto exit;
3396 }
3397 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3398 pAdapter->sessionId);
3399 }
3400#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303401 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3402 {
3403 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303404 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303405 if ('1' == *dhcpPhase)
3406 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3408 FL("BTCOEXMODE %d"), *dhcpPhase);
3409
3410 pHddCtx->btCoexModeSet = TRUE;
3411
3412 /* Firmware failing to process DHCP START/STOP indications.
3413 * So, for now commentig below code, once issue is resolved,
3414 * follwing will be uncommented.
3415 */
3416 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303417 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3418 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303419 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303420 }
3421 else if ('2' == *dhcpPhase)
3422 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3424 FL("BTCOEXMODE %d"), *dhcpPhase);
3425
3426 pHddCtx->btCoexModeSet = FALSE;
3427
3428 /* Firmware failing to process DHCP START/STOP indications.
3429 * So, for now commentig below code, once issue is resolved,
3430 * follwing will be uncommented.
3431 */
3432 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303433 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3434 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303435 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303436 }
3437 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003438 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3439 {
3440 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3441 }
3442 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3443 {
3444 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3445 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303446 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3447 {
3448 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3449 char extra[32];
3450 tANI_U8 len = 0;
3451
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003452 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303453 (int)pCfg->nActiveMaxChnTime);
3454 if (copy_to_user(priv_data.buf, &extra, len + 1))
3455 {
3456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3457 "%s: failed to copy data to user buffer", __func__);
3458 ret = -EFAULT;
3459 goto exit;
3460 }
3461 ret = len;
3462 }
3463 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3464 {
3465 tANI_U8 *value = command;
3466 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3467 int val = 0, temp;
3468
3469 value = value + 13;
3470 temp = kstrtou32(value, 10, &val);
3471 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3472 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3473 {
3474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3475 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3476 ret = -EFAULT;
3477 goto exit;
3478 }
3479 pCfg->nActiveMaxChnTime = val;
3480 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003481 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3482 {
3483 tANI_U8 filterType = 0;
3484 tANI_U8 *value;
3485 value = command + 9;
3486
3487 /* Convert the value from ascii to integer */
3488 ret = kstrtou8(value, 10, &filterType);
3489 if (ret < 0)
3490 {
3491 /* If the input value is greater than max value of datatype,
3492 * then also kstrtou8 fails
3493 */
3494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3495 "%s: kstrtou8 failed range ", __func__);
3496 ret = -EINVAL;
3497 goto exit;
3498 }
3499 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3500 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3501 {
3502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3503 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3504 " 2-Sink ", __func__);
3505 ret = -EINVAL;
3506 goto exit;
3507 }
3508 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3509 pHddCtx->drvr_miracast = filterType;
3510 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3511 }
Leo Chang614d2072013-08-22 14:59:44 -07003512 else if (strncmp(command, "SETMCRATE", 9) == 0)
3513 {
Leo Chang614d2072013-08-22 14:59:44 -07003514 tANI_U8 *value = command;
3515 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003516 tSirRateUpdateInd *rateUpdate;
3517 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003518
3519 /* Only valid for SAP mode */
3520 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3521 {
3522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3523 "%s: SAP mode is not running", __func__);
3524 ret = -EFAULT;
3525 goto exit;
3526 }
3527
3528 /* Move pointer to ahead of SETMCRATE<delimiter> */
3529 /* input value is in units of hundred kbps */
3530 value = value + 10;
3531 /* Convert the value from ascii to integer, decimal base */
3532 ret = kstrtouint(value, 10, &targetRate);
3533
Leo Chang1f98cbd2013-10-17 15:03:52 -07003534 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3535 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003536 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003537 hddLog(VOS_TRACE_LEVEL_ERROR,
3538 "%s: SETMCRATE indication alloc fail", __func__);
3539 ret = -EFAULT;
3540 goto exit;
3541 }
3542 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3543
3544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3545 "MC Target rate %d", targetRate);
3546 /* Ignore unicast */
3547 rateUpdate->ucastDataRate = -1;
3548 rateUpdate->mcastDataRate24GHz = targetRate;
3549 rateUpdate->mcastDataRate5GHz = targetRate;
3550 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3551 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3552 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3553 if (eHAL_STATUS_SUCCESS != status)
3554 {
3555 hddLog(VOS_TRACE_LEVEL_ERROR,
3556 "%s: SET_MC_RATE failed", __func__);
3557 vos_mem_free(rateUpdate);
3558 ret = -EFAULT;
3559 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003560 }
3561 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303562#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003563 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303564 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003565 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303566 }
3567#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003568#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3569 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3570 {
3571 tANI_U8 *value = command;
3572 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3573 tANI_U8 numChannels = 0;
3574 eHalStatus status = eHAL_STATUS_SUCCESS;
3575
3576 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3577 if (eHAL_STATUS_SUCCESS != status)
3578 {
3579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3580 "%s: Failed to parse channel list information", __func__);
3581 ret = -EINVAL;
3582 goto exit;
3583 }
3584
3585 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3586 {
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3588 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3589 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3590 ret = -EINVAL;
3591 goto exit;
3592 }
3593 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3594 ChannelList,
3595 numChannels);
3596 if (eHAL_STATUS_SUCCESS != status)
3597 {
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3599 "%s: Failed to update channel list information", __func__);
3600 ret = -EINVAL;
3601 goto exit;
3602 }
3603 }
3604 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3605 {
3606 tANI_U8 *value = command;
3607 char extra[128] = {0};
3608 int len = 0;
3609 tANI_U8 tid = 0;
3610 hdd_station_ctx_t *pHddStaCtx = NULL;
3611 tAniTrafStrmMetrics tsmMetrics;
3612 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3613
3614 /* if not associated, return error */
3615 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3616 {
3617 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3618 ret = -EINVAL;
3619 goto exit;
3620 }
3621
3622 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3623 value = value + 12;
3624 /* Convert the value from ascii to integer */
3625 ret = kstrtou8(value, 10, &tid);
3626 if (ret < 0)
3627 {
3628 /* If the input value is greater than max value of datatype, then also
3629 kstrtou8 fails */
3630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3631 "%s: kstrtou8 failed range [%d - %d]", __func__,
3632 TID_MIN_VALUE,
3633 TID_MAX_VALUE);
3634 ret = -EINVAL;
3635 goto exit;
3636 }
3637
3638 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3639 {
3640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3641 "tid value %d is out of range"
3642 " (Min: %d Max: %d)", tid,
3643 TID_MIN_VALUE,
3644 TID_MAX_VALUE);
3645 ret = -EINVAL;
3646 goto exit;
3647 }
3648
3649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3650 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3651
3652 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3653 {
3654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3655 "%s: failed to get tsm stats", __func__);
3656 ret = -EFAULT;
3657 goto exit;
3658 }
3659
3660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3661 "UplinkPktQueueDly(%d)\n"
3662 "UplinkPktQueueDlyHist[0](%d)\n"
3663 "UplinkPktQueueDlyHist[1](%d)\n"
3664 "UplinkPktQueueDlyHist[2](%d)\n"
3665 "UplinkPktQueueDlyHist[3](%d)\n"
3666 "UplinkPktTxDly(%lu)\n"
3667 "UplinkPktLoss(%d)\n"
3668 "UplinkPktCount(%d)\n"
3669 "RoamingCount(%d)\n"
3670 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3671 tsmMetrics.UplinkPktQueueDlyHist[0],
3672 tsmMetrics.UplinkPktQueueDlyHist[1],
3673 tsmMetrics.UplinkPktQueueDlyHist[2],
3674 tsmMetrics.UplinkPktQueueDlyHist[3],
3675 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3676 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3677
3678 /* Output TSM stats is of the format
3679 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3680 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003681 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003682 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3683 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3684 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3685 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3686 tsmMetrics.RoamingDly);
3687
3688 if (copy_to_user(priv_data.buf, &extra, len + 1))
3689 {
3690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3691 "%s: failed to copy data to user buffer", __func__);
3692 ret = -EFAULT;
3693 goto exit;
3694 }
3695 }
3696 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3697 {
3698 tANI_U8 *value = command;
3699 tANI_U8 *cckmIe = NULL;
3700 tANI_U8 cckmIeLen = 0;
3701 eHalStatus status = eHAL_STATUS_SUCCESS;
3702
3703 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3704 if (eHAL_STATUS_SUCCESS != status)
3705 {
3706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3707 "%s: Failed to parse cckm ie data", __func__);
3708 ret = -EINVAL;
3709 goto exit;
3710 }
3711
3712 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3713 {
3714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3715 "%s: CCKM Ie input length is more than max[%d]", __func__,
3716 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003717 vos_mem_free(cckmIe);
3718 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003719 ret = -EINVAL;
3720 goto exit;
3721 }
3722 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003723 vos_mem_free(cckmIe);
3724 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003725 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003726 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3727 {
3728 tANI_U8 *value = command;
3729 tCsrCcxBeaconReq ccxBcnReq;
3730 eHalStatus status = eHAL_STATUS_SUCCESS;
3731 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3732 if (eHAL_STATUS_SUCCESS != status)
3733 {
3734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3735 "%s: Failed to parse ccx beacon req", __func__);
3736 ret = -EINVAL;
3737 goto exit;
3738 }
3739
3740 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3741 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003742#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003743 else {
3744 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3745 __func__, command);
3746 }
3747
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 }
3749exit:
3750 if (command)
3751 {
3752 kfree(command);
3753 }
3754 return ret;
3755}
3756
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003757
3758
3759#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003760/**---------------------------------------------------------------------------
3761
3762 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3763
3764 This function parses the ccx beacon request passed in the format
3765 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3766 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3767 <space>Scan Mode N<space>Meas Duration N
3768 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3769 then take N.
3770 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3771 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3772 This function does not take care of removing duplicate channels from the list
3773
3774 \param - pValue Pointer to data
3775 \param - pCcxBcnReq output pointer to store parsed ie information
3776
3777 \return - 0 for success non-zero for failure
3778
3779 --------------------------------------------------------------------------*/
3780static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3781 tCsrCcxBeaconReq *pCcxBcnReq)
3782{
3783 tANI_U8 *inPtr = pValue;
3784 int tempInt = 0;
3785 int j = 0, i = 0, v = 0;
3786 char buf[32];
3787
3788 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3789 /*no argument after the command*/
3790 if (NULL == inPtr)
3791 {
3792 return -EINVAL;
3793 }
3794 /*no space after the command*/
3795 else if (SPACE_ASCII_VALUE != *inPtr)
3796 {
3797 return -EINVAL;
3798 }
3799
3800 /*removing empty spaces*/
3801 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3802
3803 /*no argument followed by spaces*/
3804 if ('\0' == *inPtr) return -EINVAL;
3805
3806 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003807 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003808 if (1 != v) return -EINVAL;
3809
3810 v = kstrtos32(buf, 10, &tempInt);
3811 if ( v < 0) return -EINVAL;
3812
3813 pCcxBcnReq->numBcnReqIe = tempInt;
3814
3815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3816 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3817
3818 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3819 {
3820 for (i = 0; i < 4; i++)
3821 {
3822 /*inPtr pointing to the beginning of first space after number of ie fields*/
3823 inPtr = strpbrk( inPtr, " " );
3824 /*no ie data after the number of ie fields argument*/
3825 if (NULL == inPtr) return -EINVAL;
3826
3827 /*removing empty space*/
3828 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3829
3830 /*no ie data after the number of ie fields argument and spaces*/
3831 if ( '\0' == *inPtr ) return -EINVAL;
3832
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003833 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003834 if (1 != v) return -EINVAL;
3835
3836 v = kstrtos32(buf, 10, &tempInt);
3837 if (v < 0) return -EINVAL;
3838
3839 switch (i)
3840 {
3841 case 0: /* Measurement token */
3842 if (tempInt <= 0)
3843 {
3844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3845 "Invalid Measurement Token(%d)", tempInt);
3846 return -EINVAL;
3847 }
3848 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3849 break;
3850
3851 case 1: /* Channel number */
3852 if ((tempInt <= 0) ||
3853 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3854 {
3855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3856 "Invalid Channel Number(%d)", tempInt);
3857 return -EINVAL;
3858 }
3859 pCcxBcnReq->bcnReq[j].channel = tempInt;
3860 break;
3861
3862 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003863 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003864 {
3865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3866 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3867 return -EINVAL;
3868 }
3869 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3870 break;
3871
3872 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003873 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3874 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003875 {
3876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3877 "Invalid Measurement Duration(%d)", tempInt);
3878 return -EINVAL;
3879 }
3880 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3881 break;
3882 }
3883 }
3884 }
3885
3886 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3887 {
3888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3889 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3890 j,
3891 pCcxBcnReq->bcnReq[j].measurementToken,
3892 pCcxBcnReq->bcnReq[j].channel,
3893 pCcxBcnReq->bcnReq[j].scanMode,
3894 pCcxBcnReq->bcnReq[j].measurementDuration);
3895 }
3896
3897 return VOS_STATUS_SUCCESS;
3898}
3899
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003900static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3901{
3902 struct statsContext *pStatsContext = NULL;
3903 hdd_adapter_t *pAdapter = NULL;
3904
3905 if (NULL == pContext)
3906 {
3907 hddLog(VOS_TRACE_LEVEL_ERROR,
3908 "%s: Bad param, pContext [%p]",
3909 __func__, pContext);
3910 return;
3911 }
3912
Jeff Johnson72a40512013-12-19 10:14:15 -08003913 /* there is a race condition that exists between this callback
3914 function and the caller since the caller could time out either
3915 before or while this code is executing. we use a spinlock to
3916 serialize these actions */
3917 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003918
3919 pStatsContext = pContext;
3920 pAdapter = pStatsContext->pAdapter;
3921 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3922 {
3923 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003924 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003925 hddLog(VOS_TRACE_LEVEL_WARN,
3926 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3927 __func__, pAdapter, pStatsContext->magic);
3928 return;
3929 }
3930
Jeff Johnson72a40512013-12-19 10:14:15 -08003931 /* context is valid so caller is still waiting */
3932
3933 /* paranoia: invalidate the magic */
3934 pStatsContext->magic = 0;
3935
3936 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003937 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3938 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3939 tsmMetrics.UplinkPktQueueDlyHist,
3940 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3941 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3942 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3943 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3944 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3945 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3946 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3947
Jeff Johnson72a40512013-12-19 10:14:15 -08003948 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003949 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003950
3951 /* serialization is complete */
3952 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003953}
3954
3955
3956
3957static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3958 tAniTrafStrmMetrics* pTsmMetrics)
3959{
3960 hdd_station_ctx_t *pHddStaCtx = NULL;
3961 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003962 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003963 long lrc;
3964 struct statsContext context;
3965 hdd_context_t *pHddCtx = NULL;
3966
3967 if (NULL == pAdapter)
3968 {
3969 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3970 return VOS_STATUS_E_FAULT;
3971 }
3972
3973 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3974 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3975
3976 /* we are connected prepare our callback context */
3977 init_completion(&context.completion);
3978 context.pAdapter = pAdapter;
3979 context.magic = STATS_CONTEXT_MAGIC;
3980
3981 /* query tsm stats */
3982 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3983 pHddStaCtx->conn_info.staId[ 0 ],
3984 pHddStaCtx->conn_info.bssId,
3985 &context, pHddCtx->pvosContext, tid);
3986
3987 if (eHAL_STATUS_SUCCESS != hstatus)
3988 {
Jeff Johnson72a40512013-12-19 10:14:15 -08003989 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
3990 __func__);
3991 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003992 }
3993 else
3994 {
3995 /* request was sent -- wait for the response */
3996 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3997 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003998 if (lrc <= 0)
3999 {
4000 hddLog(VOS_TRACE_LEVEL_ERROR,
4001 "%s: SME %s while retrieving statistics",
4002 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004003 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004004 }
4005 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004006
Jeff Johnson72a40512013-12-19 10:14:15 -08004007 /* either we never sent a request, we sent a request and received a
4008 response or we sent a request and timed out. if we never sent a
4009 request or if we sent a request and got a response, we want to
4010 clear the magic out of paranoia. if we timed out there is a
4011 race condition such that the callback function could be
4012 executing at the same time we are. of primary concern is if the
4013 callback function had already verified the "magic" but had not
4014 yet set the completion variable when a timeout occurred. we
4015 serialize these activities by invalidating the magic while
4016 holding a shared spinlock which will cause us to block if the
4017 callback is currently executing */
4018 spin_lock(&hdd_context_lock);
4019 context.magic = 0;
4020 spin_unlock(&hdd_context_lock);
4021
4022 if (VOS_STATUS_SUCCESS == vstatus)
4023 {
4024 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4025 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4026 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4027 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4028 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4029 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4030 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4031 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4032 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4033 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4034 }
4035 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004036}
4037#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4038
Srinivas Girigowdade697412013-02-14 16:31:48 -08004039#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4040void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4041{
4042 eCsrBand band = -1;
4043 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4044 switch (band)
4045 {
4046 case eCSR_BAND_ALL:
4047 *pBand = WLAN_HDD_UI_BAND_AUTO;
4048 break;
4049
4050 case eCSR_BAND_24:
4051 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4052 break;
4053
4054 case eCSR_BAND_5G:
4055 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4056 break;
4057
4058 default:
4059 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4060 *pBand = -1;
4061 break;
4062 }
4063}
4064
4065/**---------------------------------------------------------------------------
4066
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004067 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4068
4069 This function parses the send action frame data passed in the format
4070 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4071
Srinivas Girigowda56076852013-08-20 14:00:50 -07004072 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004073 \param - pTargetApBssid Pointer to target Ap bssid
4074 \param - pChannel Pointer to the Target AP channel
4075 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4076 \param - pBuf Pointer to data
4077 \param - pBufLen Pointer to data length
4078
4079 \return - 0 for success non-zero for failure
4080
4081 --------------------------------------------------------------------------*/
4082VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4083 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4084{
4085 tANI_U8 *inPtr = pValue;
4086 tANI_U8 *dataEnd;
4087 int tempInt;
4088 int j = 0;
4089 int i = 0;
4090 int v = 0;
4091 tANI_U8 tempBuf[32];
4092 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004093 /* 12 hexa decimal digits, 5 ':' and '\0' */
4094 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004095
4096 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4097 /*no argument after the command*/
4098 if (NULL == inPtr)
4099 {
4100 return -EINVAL;
4101 }
4102
4103 /*no space after the command*/
4104 else if (SPACE_ASCII_VALUE != *inPtr)
4105 {
4106 return -EINVAL;
4107 }
4108
4109 /*removing empty spaces*/
4110 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4111
4112 /*no argument followed by spaces*/
4113 if ('\0' == *inPtr)
4114 {
4115 return -EINVAL;
4116 }
4117
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004118 v = sscanf(inPtr, "%17s", macAddress);
4119 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004120 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4122 "Invalid MAC address or All hex inputs are not read (%d)", v);
4123 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004124 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004125
4126 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4127 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4128 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4129 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4130 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4131 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004132
4133 /* point to the next argument */
4134 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4135 /*no argument after the command*/
4136 if (NULL == inPtr) return -EINVAL;
4137
4138 /*removing empty spaces*/
4139 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4140
4141 /*no argument followed by spaces*/
4142 if ('\0' == *inPtr)
4143 {
4144 return -EINVAL;
4145 }
4146
4147 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004148 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004149 if (1 != v) return -EINVAL;
4150
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004151 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304152 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4153 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004154
4155 *pChannel = tempInt;
4156
4157 /* point to the next argument */
4158 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4159 /*no argument after the command*/
4160 if (NULL == inPtr) return -EINVAL;
4161 /*removing empty spaces*/
4162 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4163
4164 /*no argument followed by spaces*/
4165 if ('\0' == *inPtr)
4166 {
4167 return -EINVAL;
4168 }
4169
4170 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004171 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004172 if (1 != v) return -EINVAL;
4173
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004174 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004175 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004176
4177 *pDwellTime = tempInt;
4178
4179 /* point to the next argument */
4180 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4181 /*no argument after the command*/
4182 if (NULL == inPtr) return -EINVAL;
4183 /*removing empty spaces*/
4184 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4185
4186 /*no argument followed by spaces*/
4187 if ('\0' == *inPtr)
4188 {
4189 return -EINVAL;
4190 }
4191
4192 /* find the length of data */
4193 dataEnd = inPtr;
4194 while(('\0' != *dataEnd) )
4195 {
4196 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004197 }
Kiet Lambe150c22013-11-21 16:30:32 +05304198 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004199 if ( *pBufLen <= 0) return -EINVAL;
4200
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004201 /* Allocate the number of bytes based on the number of input characters
4202 whether it is even or odd.
4203 if the number of input characters are even, then we need N/2 byte.
4204 if the number of input characters are odd, then we need do (N+1)/2 to
4205 compensate rounding off.
4206 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4207 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4208 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004209 if (NULL == *pBuf)
4210 {
4211 hddLog(VOS_TRACE_LEVEL_FATAL,
4212 "%s: vos_mem_alloc failed ", __func__);
4213 return -EINVAL;
4214 }
4215
4216 /* the buffer received from the upper layer is character buffer,
4217 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4218 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4219 and f0 in 3rd location */
4220 for (i = 0, j = 0; j < *pBufLen; j += 2)
4221 {
Kiet Lambe150c22013-11-21 16:30:32 +05304222 if( j+1 == *pBufLen)
4223 {
4224 tempByte = hdd_parse_hex(inPtr[j]);
4225 }
4226 else
4227 {
4228 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4229 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004230 (*pBuf)[i++] = tempByte;
4231 }
4232 *pBufLen = i;
4233 return VOS_STATUS_SUCCESS;
4234}
4235
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004236/**---------------------------------------------------------------------------
4237
Srinivas Girigowdade697412013-02-14 16:31:48 -08004238 \brief hdd_parse_channellist() - HDD Parse channel list
4239
4240 This function parses the channel list passed in the format
4241 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004242 if the Number of channels (N) does not match with the actual number of channels passed
4243 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4244 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4245 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4246 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004247
4248 \param - pValue Pointer to input channel list
4249 \param - ChannelList Pointer to local output array to record channel list
4250 \param - pNumChannels Pointer to number of roam scan channels
4251
4252 \return - 0 for success non-zero for failure
4253
4254 --------------------------------------------------------------------------*/
4255VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4256{
4257 tANI_U8 *inPtr = pValue;
4258 int tempInt;
4259 int j = 0;
4260 int v = 0;
4261 char buf[32];
4262
4263 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4264 /*no argument after the command*/
4265 if (NULL == inPtr)
4266 {
4267 return -EINVAL;
4268 }
4269
4270 /*no space after the command*/
4271 else if (SPACE_ASCII_VALUE != *inPtr)
4272 {
4273 return -EINVAL;
4274 }
4275
4276 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004277 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004278
4279 /*no argument followed by spaces*/
4280 if ('\0' == *inPtr)
4281 {
4282 return -EINVAL;
4283 }
4284
4285 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004286 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004287 if (1 != v) return -EINVAL;
4288
Srinivas Girigowdade697412013-02-14 16:31:48 -08004289 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004290 if ((v < 0) ||
4291 (tempInt <= 0) ||
4292 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4293 {
4294 return -EINVAL;
4295 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004296
4297 *pNumChannels = tempInt;
4298
4299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4300 "Number of channels are: %d", *pNumChannels);
4301
4302 for (j = 0; j < (*pNumChannels); j++)
4303 {
4304 /*inPtr pointing to the beginning of first space after number of channels*/
4305 inPtr = strpbrk( inPtr, " " );
4306 /*no channel list after the number of channels argument*/
4307 if (NULL == inPtr)
4308 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004309 if (0 != j)
4310 {
4311 *pNumChannels = j;
4312 return VOS_STATUS_SUCCESS;
4313 }
4314 else
4315 {
4316 return -EINVAL;
4317 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004318 }
4319
4320 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004321 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004322
4323 /*no channel list after the number of channels argument and spaces*/
4324 if ( '\0' == *inPtr )
4325 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004326 if (0 != j)
4327 {
4328 *pNumChannels = j;
4329 return VOS_STATUS_SUCCESS;
4330 }
4331 else
4332 {
4333 return -EINVAL;
4334 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004335 }
4336
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004337 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004338 if (1 != v) return -EINVAL;
4339
Srinivas Girigowdade697412013-02-14 16:31:48 -08004340 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004341 if ((v < 0) ||
4342 (tempInt <= 0) ||
4343 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4344 {
4345 return -EINVAL;
4346 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004347 pChannelList[j] = tempInt;
4348
4349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4350 "Channel %d added to preferred channel list",
4351 pChannelList[j] );
4352 }
4353
Srinivas Girigowdade697412013-02-14 16:31:48 -08004354 return VOS_STATUS_SUCCESS;
4355}
4356
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004357
4358/**---------------------------------------------------------------------------
4359
4360 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4361
4362 This function parses the reasoc command data passed in the format
4363 REASSOC<space><bssid><space><channel>
4364
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004365 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004366 \param - pTargetApBssid Pointer to target Ap bssid
4367 \param - pChannel Pointer to the Target AP channel
4368
4369 \return - 0 for success non-zero for failure
4370
4371 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004372VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4373 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004374{
4375 tANI_U8 *inPtr = pValue;
4376 int tempInt;
4377 int v = 0;
4378 tANI_U8 tempBuf[32];
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004379 /* 12 hexa decimal digits, 5 ':' and '\0' */
4380 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004381
4382 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4383 /*no argument after the command*/
4384 if (NULL == inPtr)
4385 {
4386 return -EINVAL;
4387 }
4388
4389 /*no space after the command*/
4390 else if (SPACE_ASCII_VALUE != *inPtr)
4391 {
4392 return -EINVAL;
4393 }
4394
4395 /*removing empty spaces*/
4396 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4397
4398 /*no argument followed by spaces*/
4399 if ('\0' == *inPtr)
4400 {
4401 return -EINVAL;
4402 }
4403
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004404 v = sscanf(inPtr, "%17s", macAddress);
4405 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004406 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4408 "Invalid MAC address or All hex inputs are not read (%d)", v);
4409 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004410 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004411
4412 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4413 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4414 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4415 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4416 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4417 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004418
4419 /* point to the next argument */
4420 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4421 /*no argument after the command*/
4422 if (NULL == inPtr) return -EINVAL;
4423
4424 /*removing empty spaces*/
4425 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4426
4427 /*no argument followed by spaces*/
4428 if ('\0' == *inPtr)
4429 {
4430 return -EINVAL;
4431 }
4432
4433 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004434 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004435 if (1 != v) return -EINVAL;
4436
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004437 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004438 if ((v < 0) ||
4439 (tempInt <= 0) ||
4440 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4441 {
4442 return -EINVAL;
4443 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004444
4445 *pChannel = tempInt;
4446 return VOS_STATUS_SUCCESS;
4447}
4448
4449#endif
4450
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004451#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4452/**---------------------------------------------------------------------------
4453
4454 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4455
4456 This function parses the SETCCKM IE command
4457 SETCCKMIE<space><ie data>
4458
4459 \param - pValue Pointer to input data
4460 \param - pCckmIe Pointer to output cckm Ie
4461 \param - pCckmIeLen Pointer to output cckm ie length
4462
4463 \return - 0 for success non-zero for failure
4464
4465 --------------------------------------------------------------------------*/
4466VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4467 tANI_U8 *pCckmIeLen)
4468{
4469 tANI_U8 *inPtr = pValue;
4470 tANI_U8 *dataEnd;
4471 int j = 0;
4472 int i = 0;
4473 tANI_U8 tempByte = 0;
4474
4475 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4476 /*no argument after the command*/
4477 if (NULL == inPtr)
4478 {
4479 return -EINVAL;
4480 }
4481
4482 /*no space after the command*/
4483 else if (SPACE_ASCII_VALUE != *inPtr)
4484 {
4485 return -EINVAL;
4486 }
4487
4488 /*removing empty spaces*/
4489 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4490
4491 /*no argument followed by spaces*/
4492 if ('\0' == *inPtr)
4493 {
4494 return -EINVAL;
4495 }
4496
4497 /* find the length of data */
4498 dataEnd = inPtr;
4499 while(('\0' != *dataEnd) )
4500 {
4501 dataEnd++;
4502 ++(*pCckmIeLen);
4503 }
4504 if ( *pCckmIeLen <= 0) return -EINVAL;
4505
4506 /* Allocate the number of bytes based on the number of input characters
4507 whether it is even or odd.
4508 if the number of input characters are even, then we need N/2 byte.
4509 if the number of input characters are odd, then we need do (N+1)/2 to
4510 compensate rounding off.
4511 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4512 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4513 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4514 if (NULL == *pCckmIe)
4515 {
4516 hddLog(VOS_TRACE_LEVEL_FATAL,
4517 "%s: vos_mem_alloc failed ", __func__);
4518 return -EINVAL;
4519 }
4520 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4521 /* the buffer received from the upper layer is character buffer,
4522 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4523 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4524 and f0 in 3rd location */
4525 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4526 {
4527 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4528 (*pCckmIe)[i++] = tempByte;
4529 }
4530 *pCckmIeLen = i;
4531
4532 return VOS_STATUS_SUCCESS;
4533}
4534#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4535
Jeff Johnson295189b2012-06-20 16:38:30 -07004536/**---------------------------------------------------------------------------
4537
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004538 \brief hdd_is_valid_mac_address() - Validate MAC address
4539
4540 This function validates whether the given MAC address is valid or not
4541 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4542 where X is the hexa decimal digit character and separated by ':'
4543 This algorithm works even if MAC address is not separated by ':'
4544
4545 This code checks given input string mac contains exactly 12 hexadecimal digits.
4546 and a separator colon : appears in the input string only after
4547 an even number of hex digits.
4548
4549 \param - pMacAddr pointer to the input MAC address
4550 \return - 1 for valid and 0 for invalid
4551
4552 --------------------------------------------------------------------------*/
4553
4554v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4555{
4556 int xdigit = 0;
4557 int separator = 0;
4558 while (*pMacAddr)
4559 {
4560 if (isxdigit(*pMacAddr))
4561 {
4562 xdigit++;
4563 }
4564 else if (':' == *pMacAddr)
4565 {
4566 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4567 break;
4568
4569 ++separator;
4570 }
4571 else
4572 {
4573 separator = -1;
4574 /* Invalid MAC found */
4575 return 0;
4576 }
4577 ++pMacAddr;
4578 }
4579 return (xdigit == 12 && (separator == 5 || separator == 0));
4580}
4581
4582/**---------------------------------------------------------------------------
4583
Jeff Johnson295189b2012-06-20 16:38:30 -07004584 \brief hdd_open() - HDD Open function
4585
4586 This is called in response to ifconfig up
4587
4588 \param - dev Pointer to net_device structure
4589
4590 \return - 0 for success non-zero for failure
4591
4592 --------------------------------------------------------------------------*/
4593int hdd_open (struct net_device *dev)
4594{
4595 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4596 hdd_context_t *pHddCtx;
4597 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4598 VOS_STATUS status;
4599 v_BOOL_t in_standby = TRUE;
4600
4601 if (NULL == pAdapter)
4602 {
4603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004604 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 return -ENODEV;
4606 }
4607
4608 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4609 if (NULL == pHddCtx)
4610 {
4611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004612 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 return -ENODEV;
4614 }
4615
4616 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4617 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4618 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004619 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4620 {
4621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304622 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004623 in_standby = FALSE;
4624 break;
4625 }
4626 else
4627 {
4628 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4629 pAdapterNode = pNext;
4630 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 }
4632
4633 if (TRUE == in_standby)
4634 {
4635 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4636 {
4637 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4638 "wlan out of power save", __func__);
4639 return -EINVAL;
4640 }
4641 }
4642
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004643 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4645 {
4646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004647 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 /* Enable TX queues only when we are connected */
4649 netif_tx_start_all_queues(dev);
4650 }
4651
4652 return 0;
4653}
4654
4655int hdd_mon_open (struct net_device *dev)
4656{
4657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4658
4659 if(pAdapter == NULL) {
4660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004661 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004662 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 }
4664
4665 netif_start_queue(dev);
4666
4667 return 0;
4668}
4669/**---------------------------------------------------------------------------
4670
4671 \brief hdd_stop() - HDD stop function
4672
4673 This is called in response to ifconfig down
4674
4675 \param - dev Pointer to net_device structure
4676
4677 \return - 0 for success non-zero for failure
4678
4679 --------------------------------------------------------------------------*/
4680
4681int hdd_stop (struct net_device *dev)
4682{
4683 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4684 hdd_context_t *pHddCtx;
4685 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4686 VOS_STATUS status;
4687 v_BOOL_t enter_standby = TRUE;
4688
4689 ENTER();
4690
4691 if (NULL == pAdapter)
4692 {
4693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004694 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004695 return -ENODEV;
4696 }
4697
4698 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4699 if (NULL == pHddCtx)
4700 {
4701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004702 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004703 return -ENODEV;
4704 }
4705
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004706 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004707 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4708 netif_tx_disable(pAdapter->dev);
4709 netif_carrier_off(pAdapter->dev);
4710
4711
4712 /* SoftAP ifaces should never go in power save mode
4713 making sure same here. */
4714 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4715 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004716 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 )
4718 {
4719 /* SoftAP mode, so return from here */
4720 EXIT();
4721 return 0;
4722 }
4723
4724 /* Find if any iface is up then
4725 if any iface is up then can't put device to sleep/ power save mode. */
4726 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4727 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4728 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004729 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4730 {
4731 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304732 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004733 enter_standby = FALSE;
4734 break;
4735 }
4736 else
4737 {
4738 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4739 pAdapterNode = pNext;
4740 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004741 }
4742
4743 if (TRUE == enter_standby)
4744 {
4745 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4746 "entering standby", __func__);
4747 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4748 {
4749 /*log and return success*/
4750 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4751 "wlan in power save", __func__);
4752 }
4753 }
4754
4755 EXIT();
4756 return 0;
4757}
4758
4759/**---------------------------------------------------------------------------
4760
4761 \brief hdd_uninit() - HDD uninit function
4762
4763 This is called during the netdev unregister to uninitialize all data
4764associated with the device
4765
4766 \param - dev Pointer to net_device structure
4767
4768 \return - void
4769
4770 --------------------------------------------------------------------------*/
4771static void hdd_uninit (struct net_device *dev)
4772{
4773 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4774
4775 ENTER();
4776
4777 do
4778 {
4779 if (NULL == pAdapter)
4780 {
4781 hddLog(VOS_TRACE_LEVEL_FATAL,
4782 "%s: NULL pAdapter", __func__);
4783 break;
4784 }
4785
4786 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4787 {
4788 hddLog(VOS_TRACE_LEVEL_FATAL,
4789 "%s: Invalid magic", __func__);
4790 break;
4791 }
4792
4793 if (NULL == pAdapter->pHddCtx)
4794 {
4795 hddLog(VOS_TRACE_LEVEL_FATAL,
4796 "%s: NULL pHddCtx", __func__);
4797 break;
4798 }
4799
4800 if (dev != pAdapter->dev)
4801 {
4802 hddLog(VOS_TRACE_LEVEL_FATAL,
4803 "%s: Invalid device reference", __func__);
4804 /* we haven't validated all cases so let this go for now */
4805 }
4806
4807 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4808
4809 /* after uninit our adapter structure will no longer be valid */
4810 pAdapter->dev = NULL;
4811 pAdapter->magic = 0;
4812 } while (0);
4813
4814 EXIT();
4815}
4816
4817/**---------------------------------------------------------------------------
4818
4819 \brief hdd_release_firmware() -
4820
4821 This function calls the release firmware API to free the firmware buffer.
4822
4823 \param - pFileName Pointer to the File Name.
4824 pCtx - Pointer to the adapter .
4825
4826
4827 \return - 0 for success, non zero for failure
4828
4829 --------------------------------------------------------------------------*/
4830
4831VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4832{
4833 VOS_STATUS status = VOS_STATUS_SUCCESS;
4834 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4835 ENTER();
4836
4837
4838 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4839
4840 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4841
4842 if(pHddCtx->fw) {
4843 release_firmware(pHddCtx->fw);
4844 pHddCtx->fw = NULL;
4845 }
4846 else
4847 status = VOS_STATUS_E_FAILURE;
4848 }
4849 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4850 if(pHddCtx->nv) {
4851 release_firmware(pHddCtx->nv);
4852 pHddCtx->nv = NULL;
4853 }
4854 else
4855 status = VOS_STATUS_E_FAILURE;
4856
4857 }
4858
4859 EXIT();
4860 return status;
4861}
4862
4863/**---------------------------------------------------------------------------
4864
4865 \brief hdd_request_firmware() -
4866
4867 This function reads the firmware file using the request firmware
4868 API and returns the the firmware data and the firmware file size.
4869
4870 \param - pfileName - Pointer to the file name.
4871 - pCtx - Pointer to the adapter .
4872 - ppfw_data - Pointer to the pointer of the firmware data.
4873 - pSize - Pointer to the file size.
4874
4875 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4876
4877 --------------------------------------------------------------------------*/
4878
4879
4880VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4881{
4882 int status;
4883 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4884 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4885 ENTER();
4886
4887 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4888
4889 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4890
4891 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4892 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4893 __func__, pfileName);
4894 retval = VOS_STATUS_E_FAILURE;
4895 }
4896
4897 else {
4898 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4899 *pSize = pHddCtx->fw->size;
4900 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4901 __func__, *pSize);
4902 }
4903 }
4904 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4905
4906 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4907
4908 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4909 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4910 __func__, pfileName);
4911 retval = VOS_STATUS_E_FAILURE;
4912 }
4913
4914 else {
4915 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4916 *pSize = pHddCtx->nv->size;
4917 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4918 __func__, *pSize);
4919 }
4920 }
4921
4922 EXIT();
4923 return retval;
4924}
4925/**---------------------------------------------------------------------------
4926 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4927
4928 This is the function invoked by SME to inform the result of a full power
4929 request issued by HDD
4930
4931 \param - callbackcontext - Pointer to cookie
4932 status - result of request
4933
4934 \return - None
4935
4936--------------------------------------------------------------------------*/
4937void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4938{
4939 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4940
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004941 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 if(&pHddCtx->full_pwr_comp_var)
4943 {
4944 complete(&pHddCtx->full_pwr_comp_var);
4945 }
4946}
4947
4948/**---------------------------------------------------------------------------
4949
4950 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4951
4952 This is the function invoked by SME to inform the result of BMPS
4953 request issued by HDD
4954
4955 \param - callbackcontext - Pointer to cookie
4956 status - result of request
4957
4958 \return - None
4959
4960--------------------------------------------------------------------------*/
4961void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4962{
4963
4964 struct completion *completion_var = (struct completion*) callbackContext;
4965
Arif Hussain6d2a3322013-11-17 19:50:10 -08004966 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004967 if(completion_var != NULL)
4968 {
4969 complete(completion_var);
4970 }
4971}
4972
4973/**---------------------------------------------------------------------------
4974
4975 \brief hdd_get_cfg_file_size() -
4976
4977 This function reads the configuration file using the request firmware
4978 API and returns the configuration file size.
4979
4980 \param - pCtx - Pointer to the adapter .
4981 - pFileName - Pointer to the file name.
4982 - pBufSize - Pointer to the buffer size.
4983
4984 \return - 0 for success, non zero for failure
4985
4986 --------------------------------------------------------------------------*/
4987
4988VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4989{
4990 int status;
4991 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4992
4993 ENTER();
4994
4995 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4996
4997 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4999 status = VOS_STATUS_E_FAILURE;
5000 }
5001 else {
5002 *pBufSize = pHddCtx->fw->size;
5003 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5004 release_firmware(pHddCtx->fw);
5005 pHddCtx->fw = NULL;
5006 }
5007
5008 EXIT();
5009 return VOS_STATUS_SUCCESS;
5010}
5011
5012/**---------------------------------------------------------------------------
5013
5014 \brief hdd_read_cfg_file() -
5015
5016 This function reads the configuration file using the request firmware
5017 API and returns the cfg data and the buffer size of the configuration file.
5018
5019 \param - pCtx - Pointer to the adapter .
5020 - pFileName - Pointer to the file name.
5021 - pBuffer - Pointer to the data buffer.
5022 - pBufSize - Pointer to the buffer size.
5023
5024 \return - 0 for success, non zero for failure
5025
5026 --------------------------------------------------------------------------*/
5027
5028VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5029 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5030{
5031 int status;
5032 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5033
5034 ENTER();
5035
5036 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5037
5038 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5039 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5040 return VOS_STATUS_E_FAILURE;
5041 }
5042 else {
5043 if(*pBufSize != pHddCtx->fw->size) {
5044 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5045 "file size", __func__);
5046 release_firmware(pHddCtx->fw);
5047 pHddCtx->fw = NULL;
5048 return VOS_STATUS_E_FAILURE;
5049 }
5050 else {
5051 if(pBuffer) {
5052 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5053 }
5054 release_firmware(pHddCtx->fw);
5055 pHddCtx->fw = NULL;
5056 }
5057 }
5058
5059 EXIT();
5060
5061 return VOS_STATUS_SUCCESS;
5062}
5063
5064/**---------------------------------------------------------------------------
5065
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 \brief hdd_set_mac_address() -
5067
5068 This function sets the user specified mac address using
5069 the command ifconfig wlanX hw ether <mac adress>.
5070
5071 \param - dev - Pointer to the net device.
5072 - addr - Pointer to the sockaddr.
5073 \return - 0 for success, non zero for failure
5074
5075 --------------------------------------------------------------------------*/
5076
5077static int hdd_set_mac_address(struct net_device *dev, void *addr)
5078{
5079 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5080 struct sockaddr *psta_mac_addr = addr;
5081 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5082
5083 ENTER();
5084
5085 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5086
5087#ifdef HDD_SESSIONIZE
5088 // set the MAC address though the STA ID CFG.
5089 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5090 (v_U8_t *)&pAdapter->macAddressCurrent,
5091 sizeof( pAdapter->macAddressCurrent ),
5092 hdd_set_mac_addr_cb, VOS_FALSE );
5093#endif
5094
5095 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5096
5097 EXIT();
5098 return halStatus;
5099}
5100
5101tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5102{
5103 int i;
5104 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5105 {
5106 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5107 break;
5108 }
5109
5110 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5111 return NULL;
5112
5113 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5114 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5115}
5116
5117void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5118{
5119 int i;
5120 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5121 {
5122 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5123 {
5124 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5125 break;
5126 }
5127 }
5128 return;
5129}
5130
5131#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5132 static struct net_device_ops wlan_drv_ops = {
5133 .ndo_open = hdd_open,
5134 .ndo_stop = hdd_stop,
5135 .ndo_uninit = hdd_uninit,
5136 .ndo_start_xmit = hdd_hard_start_xmit,
5137 .ndo_tx_timeout = hdd_tx_timeout,
5138 .ndo_get_stats = hdd_stats,
5139 .ndo_do_ioctl = hdd_ioctl,
5140 .ndo_set_mac_address = hdd_set_mac_address,
5141 .ndo_select_queue = hdd_select_queue,
5142#ifdef WLAN_FEATURE_PACKET_FILTERING
5143#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5144 .ndo_set_rx_mode = hdd_set_multicast_list,
5145#else
5146 .ndo_set_multicast_list = hdd_set_multicast_list,
5147#endif //LINUX_VERSION_CODE
5148#endif
5149 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 static struct net_device_ops wlan_mon_drv_ops = {
5151 .ndo_open = hdd_mon_open,
5152 .ndo_stop = hdd_stop,
5153 .ndo_uninit = hdd_uninit,
5154 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5155 .ndo_tx_timeout = hdd_tx_timeout,
5156 .ndo_get_stats = hdd_stats,
5157 .ndo_do_ioctl = hdd_ioctl,
5158 .ndo_set_mac_address = hdd_set_mac_address,
5159 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005160
5161#endif
5162
5163void hdd_set_station_ops( struct net_device *pWlanDev )
5164{
5165#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 pWlanDev->netdev_ops = &wlan_drv_ops;
5167#else
5168 pWlanDev->open = hdd_open;
5169 pWlanDev->stop = hdd_stop;
5170 pWlanDev->uninit = hdd_uninit;
5171 pWlanDev->hard_start_xmit = NULL;
5172 pWlanDev->tx_timeout = hdd_tx_timeout;
5173 pWlanDev->get_stats = hdd_stats;
5174 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 pWlanDev->set_mac_address = hdd_set_mac_address;
5176#endif
5177}
5178
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005179static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005180{
5181 struct net_device *pWlanDev = NULL;
5182 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 /*
5184 * cfg80211 initialization and registration....
5185 */
5186 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5187
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 if(pWlanDev != NULL)
5189 {
5190
5191 //Save the pointer to the net_device in the HDD adapter
5192 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5193
Jeff Johnson295189b2012-06-20 16:38:30 -07005194 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5195
5196 pAdapter->dev = pWlanDev;
5197 pAdapter->pHddCtx = pHddCtx;
5198 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5199
5200 init_completion(&pAdapter->session_open_comp_var);
5201 init_completion(&pAdapter->session_close_comp_var);
5202 init_completion(&pAdapter->disconnect_comp_var);
5203 init_completion(&pAdapter->linkup_event_var);
5204 init_completion(&pAdapter->cancel_rem_on_chan_var);
5205 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5207 init_completion(&pAdapter->offchannel_tx_event);
5208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005210#ifdef FEATURE_WLAN_TDLS
5211 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005212 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005213 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305214 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005215#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005216 init_completion(&pHddCtx->mc_sus_event_var);
5217 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305218 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005219 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005220 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005221
Rajeev79dbe4c2013-10-05 11:03:42 +05305222#ifdef FEATURE_WLAN_BATCH_SCAN
5223 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5224 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5225 pAdapter->pBatchScanRsp = NULL;
5226 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005227 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05305228 mutex_init(&pAdapter->hdd_batch_scan_lock);
5229#endif
5230
Jeff Johnson295189b2012-06-20 16:38:30 -07005231 pAdapter->isLinkUpSvcNeeded = FALSE;
5232 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5233 //Init the net_device structure
5234 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5235
5236 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5237 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5238 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5239 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5240
5241 hdd_set_station_ops( pAdapter->dev );
5242
5243 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005244 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5245 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5246 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005247 /* set pWlanDev's parent to underlying device */
5248 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5249 }
5250
5251 return pAdapter;
5252}
5253
5254VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5255{
5256 struct net_device *pWlanDev = pAdapter->dev;
5257 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5258 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5259 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5260
5261 if( rtnl_lock_held )
5262 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005263 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005264 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5265 {
5266 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5267 return VOS_STATUS_E_FAILURE;
5268 }
5269 }
5270 if (register_netdevice(pWlanDev))
5271 {
5272 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5273 return VOS_STATUS_E_FAILURE;
5274 }
5275 }
5276 else
5277 {
5278 if(register_netdev(pWlanDev))
5279 {
5280 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5281 return VOS_STATUS_E_FAILURE;
5282 }
5283 }
5284 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5285
5286 return VOS_STATUS_SUCCESS;
5287}
5288
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005289static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005290{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005291 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005292
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005293 if (NULL == pAdapter)
5294 {
5295 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5296 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005298
5299 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5300 {
5301 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5302 return eHAL_STATUS_NOT_INITIALIZED;
5303 }
5304
5305 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5306
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005307#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005308 /* need to make sure all of our scheduled work has completed.
5309 * This callback is called from MC thread context, so it is safe to
5310 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005311 *
5312 * Even though this is called from MC thread context, if there is a faulty
5313 * work item in the system, that can hang this call forever. So flushing
5314 * this global work queue is not safe; and now we make sure that
5315 * individual work queues are stopped correctly. But the cancel work queue
5316 * is a GPL only API, so the proprietary version of the driver would still
5317 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005318 */
5319 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005320#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005321
5322 /* We can be blocked while waiting for scheduled work to be
5323 * flushed, and the adapter structure can potentially be freed, in
5324 * which case the magic will have been reset. So make sure the
5325 * magic is still good, and hence the adapter structure is still
5326 * valid, before signaling completion */
5327 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5328 {
5329 complete(&pAdapter->session_close_comp_var);
5330 }
5331
Jeff Johnson295189b2012-06-20 16:38:30 -07005332 return eHAL_STATUS_SUCCESS;
5333}
5334
5335VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5336{
5337 struct net_device *pWlanDev = pAdapter->dev;
5338 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5339 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5340 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5341 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5342 int rc = 0;
5343
5344 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005345 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 //Open a SME session for future operation
5347 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005348 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005349 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5350 {
5351 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005352 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 halStatus, halStatus );
5354 status = VOS_STATUS_E_FAILURE;
5355 goto error_sme_open;
5356 }
5357
5358 //Block on a completion variable. Can't wait forever though.
5359 rc = wait_for_completion_interruptible_timeout(
5360 &pAdapter->session_open_comp_var,
5361 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5362 if (!rc)
5363 {
5364 hddLog(VOS_TRACE_LEVEL_FATAL,
5365 "Session is not opened within timeout period code %08d", rc );
5366 status = VOS_STATUS_E_FAILURE;
5367 goto error_sme_open;
5368 }
5369
5370 // Register wireless extensions
5371 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5372 {
5373 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005374 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005375 halStatus, halStatus );
5376 status = VOS_STATUS_E_FAILURE;
5377 goto error_register_wext;
5378 }
5379 //Safe to register the hard_start_xmit function again
5380#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5381 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5382#else
5383 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5384#endif
5385
5386 //Set the Connection State to Not Connected
5387 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5388
5389 //Set the default operation channel
5390 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5391
5392 /* Make the default Auth Type as OPEN*/
5393 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5394
5395 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5396 {
5397 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005398 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005399 status, status );
5400 goto error_init_txrx;
5401 }
5402
5403 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5404
5405 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5406 {
5407 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005408 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 status, status );
5410 goto error_wmm_init;
5411 }
5412
5413 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5414
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005415#ifdef FEATURE_WLAN_TDLS
5416 if(0 != wlan_hdd_tdls_init(pAdapter))
5417 {
5418 status = VOS_STATUS_E_FAILURE;
5419 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5420 goto error_tdls_init;
5421 }
5422 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5423#endif
5424
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 return VOS_STATUS_SUCCESS;
5426
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005427#ifdef FEATURE_WLAN_TDLS
5428error_tdls_init:
5429 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5430 hdd_wmm_adapter_close(pAdapter);
5431#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005432error_wmm_init:
5433 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5434 hdd_deinit_tx_rx(pAdapter);
5435error_init_txrx:
5436 hdd_UnregisterWext(pWlanDev);
5437error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005438 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 {
5440 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005441 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005443 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005444 {
5445 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005446 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005448 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 }
5450}
5451error_sme_open:
5452 return status;
5453}
5454
Jeff Johnson295189b2012-06-20 16:38:30 -07005455void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5456{
5457 hdd_cfg80211_state_t *cfgState;
5458
5459 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5460
5461 if( NULL != cfgState->buf )
5462 {
5463 int rc;
5464 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5465 rc = wait_for_completion_interruptible_timeout(
5466 &pAdapter->tx_action_cnf_event,
5467 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5468 if(!rc)
5469 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005471 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005472 }
5473 }
5474 return;
5475}
Jeff Johnson295189b2012-06-20 16:38:30 -07005476
5477void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5478{
5479 ENTER();
5480 switch ( pAdapter->device_mode )
5481 {
5482 case WLAN_HDD_INFRA_STATION:
5483 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005484 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005485 {
5486 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5487 {
5488 hdd_deinit_tx_rx( pAdapter );
5489 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5490 }
5491
5492 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5493 {
5494 hdd_wmm_adapter_close( pAdapter );
5495 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5496 }
5497
Jeff Johnson295189b2012-06-20 16:38:30 -07005498 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005499#ifdef FEATURE_WLAN_TDLS
5500 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5501 {
5502 wlan_hdd_tdls_exit(pAdapter);
5503 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5504 }
5505#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005506
5507 break;
5508 }
5509
5510 case WLAN_HDD_SOFTAP:
5511 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305513
5514 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5515 {
5516 hdd_wmm_adapter_close( pAdapter );
5517 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5518 }
5519
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005521
5522 hdd_unregister_hostapd(pAdapter);
5523 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 break;
5526 }
5527
5528 case WLAN_HDD_MONITOR:
5529 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5532 {
5533 hdd_deinit_tx_rx( pAdapter );
5534 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5535 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 if(NULL != pAdapterforTx)
5537 {
5538 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5539 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005540 break;
5541 }
5542
5543
5544 default:
5545 break;
5546 }
5547
5548 EXIT();
5549}
5550
5551void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5552{
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305553 struct net_device *pWlanDev;
5554
5555 ENTER();
5556 if (NULL == pAdapter)
5557 {
5558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5559 "%s: HDD adapter is Null", __func__);
5560 return;
5561 }
5562
5563 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005564
Rajeev79dbe4c2013-10-05 11:03:42 +05305565#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305566 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5567 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005568 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305569 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5570 )
5571 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005572 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305573 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005574 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5575 {
5576 hdd_deinit_batch_scan(pAdapter);
5577 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305578 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005579 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305580#endif
5581
Jeff Johnson295189b2012-06-20 16:38:30 -07005582 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5583 if( rtnl_held )
5584 {
5585 unregister_netdevice(pWlanDev);
5586 }
5587 else
5588 {
5589 unregister_netdev(pWlanDev);
5590 }
5591 // note that the pAdapter is no longer valid at this point
5592 // since the memory has been reclaimed
5593 }
5594
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305595 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005596}
5597
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005598void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5599{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305600 VOS_STATUS status;
5601 hdd_adapter_t *pAdapter = NULL;
5602 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005603
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305604 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005605
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305606 /*loop through all adapters.*/
5607 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005608 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305609 pAdapter = pAdapterNode->pAdapter;
5610 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5611 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005612
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305613 { // we skip this registration for modes other than STA and P2P client modes.
5614 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5615 pAdapterNode = pNext;
5616 continue;
5617 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005618
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305619 //Apply Dynamic DTIM For P2P
5620 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5621 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5622 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5623 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5624 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5625 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5626 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5627 (eConnectionState_Associated ==
5628 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5629 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5630 {
5631 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005632
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305633 powerRequest.uIgnoreDTIM = 1;
5634 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5635
5636 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5637 {
5638 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5639 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5640 }
5641 else
5642 {
5643 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5644 }
5645
5646 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5647 * specified during Enter/Exit BMPS when LCD off*/
5648 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5649 NULL, eANI_BOOLEAN_FALSE);
5650 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5651 NULL, eANI_BOOLEAN_FALSE);
5652
5653 /* switch to the DTIM specified in cfg.ini */
5654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5655 "Switch to DTIM %d", powerRequest.uListenInterval);
5656 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5657 break;
5658
5659 }
5660
5661 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5662 pAdapterNode = pNext;
5663 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005664}
5665
5666void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5667{
5668 /*Switch back to DTIM 1*/
5669 tSirSetPowerParamsReq powerRequest = { 0 };
5670
5671 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5672 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005673 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005674
5675 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5676 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5677 NULL, eANI_BOOLEAN_FALSE);
5678 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5679 NULL, eANI_BOOLEAN_FALSE);
5680
5681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5682 "Switch to DTIM%d",powerRequest.uListenInterval);
5683 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5684
5685}
5686
Jeff Johnson295189b2012-06-20 16:38:30 -07005687VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5688{
5689 VOS_STATUS status = VOS_STATUS_SUCCESS;
5690
5691 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5692 {
5693 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5694 }
5695
5696 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5697 {
5698 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5699 }
5700
5701 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5702 {
5703 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5704 }
5705
5706 return status;
5707}
5708
5709VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5710{
5711 hdd_adapter_t *pAdapter = NULL;
5712 eHalStatus halStatus;
5713 VOS_STATUS status = VOS_STATUS_E_INVAL;
5714 v_BOOL_t disableBmps = FALSE;
5715 v_BOOL_t disableImps = FALSE;
5716
5717 switch(session_type)
5718 {
5719 case WLAN_HDD_INFRA_STATION:
5720 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005721 case WLAN_HDD_P2P_CLIENT:
5722 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 //Exit BMPS -> Is Sta/P2P Client is already connected
5724 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5725 if((NULL != pAdapter)&&
5726 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5727 {
5728 disableBmps = TRUE;
5729 }
5730
5731 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5732 if((NULL != pAdapter)&&
5733 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5734 {
5735 disableBmps = TRUE;
5736 }
5737
5738 //Exit both Bmps and Imps incase of Go/SAP Mode
5739 if((WLAN_HDD_SOFTAP == session_type) ||
5740 (WLAN_HDD_P2P_GO == session_type))
5741 {
5742 disableBmps = TRUE;
5743 disableImps = TRUE;
5744 }
5745
5746 if(TRUE == disableImps)
5747 {
5748 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5749 {
5750 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5751 }
5752 }
5753
5754 if(TRUE == disableBmps)
5755 {
5756 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5757 {
5758 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5759
5760 if(eHAL_STATUS_SUCCESS != halStatus)
5761 {
5762 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005763 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 VOS_ASSERT(0);
5765 return status;
5766 }
5767 }
5768
5769 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5770 {
5771 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5772
5773 if(eHAL_STATUS_SUCCESS != halStatus)
5774 {
5775 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005776 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 VOS_ASSERT(0);
5778 return status;
5779 }
5780 }
5781 }
5782
5783 if((TRUE == disableBmps) ||
5784 (TRUE == disableImps))
5785 {
5786 /* Now, get the chip into Full Power now */
5787 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5788 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5789 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5790
5791 if(halStatus != eHAL_STATUS_SUCCESS)
5792 {
5793 if(halStatus == eHAL_STATUS_PMC_PENDING)
5794 {
5795 //Block on a completion variable. Can't wait forever though
5796 wait_for_completion_interruptible_timeout(
5797 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5798 }
5799 else
5800 {
5801 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005802 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005803 VOS_ASSERT(0);
5804 return status;
5805 }
5806 }
5807
5808 status = VOS_STATUS_SUCCESS;
5809 }
5810
5811 break;
5812 }
5813 return status;
5814}
5815
5816hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005817 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 tANI_U8 rtnl_held )
5819{
5820 hdd_adapter_t *pAdapter = NULL;
5821 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5822 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5823 VOS_STATUS exitbmpsStatus;
5824
Arif Hussain6d2a3322013-11-17 19:50:10 -08005825 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005826
5827 //Disable BMPS incase of Concurrency
5828 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5829
5830 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5831 {
5832 //Fail to Exit BMPS
5833 VOS_ASSERT(0);
5834 return NULL;
5835 }
5836
5837 switch(session_type)
5838 {
5839 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005841 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005842 {
5843 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5844
5845 if( NULL == pAdapter )
5846 return NULL;
5847
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305848#ifdef FEATURE_WLAN_TDLS
5849 /* A Mutex Lock is introduced while changing/initializing the mode to
5850 * protect the concurrent access for the Adapters by TDLS module.
5851 */
5852 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5853 {
5854 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5855 "%s: unable to lock list", __func__);
5856 return NULL;
5857 }
5858#endif
5859
Jeff Johnsone7245742012-09-05 17:12:55 -07005860 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5861 NL80211_IFTYPE_P2P_CLIENT:
5862 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005863
Jeff Johnson295189b2012-06-20 16:38:30 -07005864 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305865#ifdef FEATURE_WLAN_TDLS
5866 mutex_unlock(&pHddCtx->tdls_lock);
5867#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305868
5869 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 if( VOS_STATUS_SUCCESS != status )
5871 goto err_free_netdev;
5872
5873 status = hdd_register_interface( pAdapter, rtnl_held );
5874 if( VOS_STATUS_SUCCESS != status )
5875 {
5876 hdd_deinit_adapter(pHddCtx, pAdapter);
5877 goto err_free_netdev;
5878 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305879
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305880 // Workqueue which gets scheduled in IPv4 notification callback.
5881 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5882
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305883#ifdef WLAN_NS_OFFLOAD
5884 // Workqueue which gets scheduled in IPv6 notification callback.
5885 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5886#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 //Stop the Interface TX queue.
5888 netif_tx_disable(pAdapter->dev);
5889 //netif_tx_disable(pWlanDev);
5890 netif_carrier_off(pAdapter->dev);
5891
5892 break;
5893 }
5894
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005896 case WLAN_HDD_SOFTAP:
5897 {
5898 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5899 if( NULL == pAdapter )
5900 return NULL;
5901
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5903 NL80211_IFTYPE_AP:
5904 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 pAdapter->device_mode = session_type;
5906
5907 status = hdd_init_ap_mode(pAdapter);
5908 if( VOS_STATUS_SUCCESS != status )
5909 goto err_free_netdev;
5910
5911 status = hdd_register_hostapd( pAdapter, rtnl_held );
5912 if( VOS_STATUS_SUCCESS != status )
5913 {
5914 hdd_deinit_adapter(pHddCtx, pAdapter);
5915 goto err_free_netdev;
5916 }
5917
5918 netif_tx_disable(pAdapter->dev);
5919 netif_carrier_off(pAdapter->dev);
5920
5921 hdd_set_conparam( 1 );
5922 break;
5923 }
5924 case WLAN_HDD_MONITOR:
5925 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5927 if( NULL == pAdapter )
5928 return NULL;
5929
5930 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5931 pAdapter->device_mode = session_type;
5932 status = hdd_register_interface( pAdapter, rtnl_held );
5933#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5934 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5935#else
5936 pAdapter->dev->open = hdd_mon_open;
5937 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5938#endif
5939 hdd_init_tx_rx( pAdapter );
5940 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5941 //Set adapter to be used for data tx. It will use either GO or softap.
5942 pAdapter->sessionCtx.monitor.pAdapterForTx =
5943 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5945 {
5946 pAdapter->sessionCtx.monitor.pAdapterForTx =
5947 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 /* This workqueue will be used to transmit management packet over
5950 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005951 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5952 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5953 return NULL;
5954 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005955
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5957 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005958 }
5959 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005960 case WLAN_HDD_FTM:
5961 {
5962 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5963
5964 if( NULL == pAdapter )
5965 return NULL;
5966 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5967 * message while loading driver in FTM mode. */
5968 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5969 pAdapter->device_mode = session_type;
5970 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305971
5972 hdd_init_tx_rx( pAdapter );
5973
5974 //Stop the Interface TX queue.
5975 netif_tx_disable(pAdapter->dev);
5976 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005977 }
5978 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005979 default:
5980 {
5981 VOS_ASSERT(0);
5982 return NULL;
5983 }
5984 }
5985
Jeff Johnson295189b2012-06-20 16:38:30 -07005986 if( VOS_STATUS_SUCCESS == status )
5987 {
5988 //Add it to the hdd's session list.
5989 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5990 if( NULL == pHddAdapterNode )
5991 {
5992 status = VOS_STATUS_E_NOMEM;
5993 }
5994 else
5995 {
5996 pHddAdapterNode->pAdapter = pAdapter;
5997 status = hdd_add_adapter_back ( pHddCtx,
5998 pHddAdapterNode );
5999 }
6000 }
6001
6002 if( VOS_STATUS_SUCCESS != status )
6003 {
6004 if( NULL != pAdapter )
6005 {
6006 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6007 pAdapter = NULL;
6008 }
6009 if( NULL != pHddAdapterNode )
6010 {
6011 vos_mem_free( pHddAdapterNode );
6012 }
6013
6014 goto resume_bmps;
6015 }
6016
6017 if(VOS_STATUS_SUCCESS == status)
6018 {
6019 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6020
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006021 //Initialize the WoWL service
6022 if(!hdd_init_wowl(pAdapter))
6023 {
6024 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6025 goto err_free_netdev;
6026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006028 return pAdapter;
6029
6030err_free_netdev:
6031 free_netdev(pAdapter->dev);
6032 wlan_hdd_release_intf_addr( pHddCtx,
6033 pAdapter->macAddressCurrent.bytes );
6034
6035resume_bmps:
6036 //If bmps disabled enable it
6037 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6038 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306039 if (pHddCtx->hdd_wlan_suspended)
6040 {
6041 hdd_set_pwrparams(pHddCtx);
6042 }
6043 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 }
6045 return NULL;
6046}
6047
6048VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6049 tANI_U8 rtnl_held )
6050{
6051 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6052 VOS_STATUS status;
6053
6054 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6055 if( VOS_STATUS_SUCCESS != status )
6056 return status;
6057
6058 while ( pCurrent->pAdapter != pAdapter )
6059 {
6060 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6061 if( VOS_STATUS_SUCCESS != status )
6062 break;
6063
6064 pCurrent = pNext;
6065 }
6066 pAdapterNode = pCurrent;
6067 if( VOS_STATUS_SUCCESS == status )
6068 {
6069 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6070 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306071
6072#ifdef FEATURE_WLAN_TDLS
6073
6074 /* A Mutex Lock is introduced while changing/initializing the mode to
6075 * protect the concurrent access for the Adapters by TDLS module.
6076 */
6077 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6078 {
6079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6080 "%s: unable to lock list", __func__);
6081 return VOS_STATUS_E_FAILURE;
6082 }
6083#endif
6084
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 hdd_remove_adapter( pHddCtx, pAdapterNode );
6086 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006087 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006088
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306089#ifdef FEATURE_WLAN_TDLS
6090 mutex_unlock(&pHddCtx->tdls_lock);
6091#endif
6092
Jeff Johnson295189b2012-06-20 16:38:30 -07006093
6094 /* If there is a single session of STA/P2P client, re-enable BMPS */
6095 if ((!vos_concurrent_sessions_running()) &&
6096 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6097 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6098 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306099 if (pHddCtx->hdd_wlan_suspended)
6100 {
6101 hdd_set_pwrparams(pHddCtx);
6102 }
6103 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006104 }
6105
6106 return VOS_STATUS_SUCCESS;
6107 }
6108
6109 return VOS_STATUS_E_FAILURE;
6110}
6111
6112VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6113{
6114 hdd_adapter_list_node_t *pHddAdapterNode;
6115 VOS_STATUS status;
6116
6117 ENTER();
6118
6119 do
6120 {
6121 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6122 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6123 {
6124 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6125 vos_mem_free( pHddAdapterNode );
6126 }
6127 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6128
6129 EXIT();
6130
6131 return VOS_STATUS_SUCCESS;
6132}
6133
6134void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6135{
6136 v_U8_t addIE[1] = {0};
6137
6138 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6139 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6140 eANI_BOOLEAN_FALSE) )
6141 {
6142 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006143 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 }
6145
6146 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6147 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6148 eANI_BOOLEAN_FALSE) )
6149 {
6150 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006151 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 }
6153
6154 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6155 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6156 eANI_BOOLEAN_FALSE) )
6157 {
6158 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006159 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 }
6161}
6162
6163VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6164{
6165 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6166 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6167 union iwreq_data wrqu;
6168
6169 ENTER();
6170
6171 switch(pAdapter->device_mode)
6172 {
6173 case WLAN_HDD_INFRA_STATION:
6174 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006175 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6177 {
6178 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6179 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6180 pAdapter->sessionId,
6181 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6182 else
6183 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6184 pAdapter->sessionId,
6185 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6186 //success implies disconnect command got queued up successfully
6187 if(halStatus == eHAL_STATUS_SUCCESS)
6188 {
6189 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6190 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6191 }
6192 memset(&wrqu, '\0', sizeof(wrqu));
6193 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6194 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6195 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6196 }
6197 else
6198 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306199 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006200 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306201#ifdef WLAN_OPEN_SOURCE
6202#ifdef WLAN_NS_OFFLOAD
6203 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6204#endif
6205#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306206 if (pAdapter->ipv4_notifier_registered)
6207 {
6208 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6209 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6210 pAdapter->ipv4_notifier_registered = false;
6211 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306212#ifdef WLAN_OPEN_SOURCE
6213 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6214#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6216 {
6217 INIT_COMPLETION(pAdapter->session_close_comp_var);
6218 if (eHAL_STATUS_SUCCESS ==
6219 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6220 hdd_smeCloseSessionCallback, pAdapter))
6221 {
6222 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006223 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006224 &pAdapter->session_close_comp_var,
6225 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6226 }
6227 }
6228
6229 break;
6230
6231 case WLAN_HDD_SOFTAP:
6232 case WLAN_HDD_P2P_GO:
6233 //Any softap specific cleanup here...
6234 mutex_lock(&pHddCtx->sap_lock);
6235 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6236 {
6237 VOS_STATUS status;
6238 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6239
6240 //Stop Bss.
6241 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6242 if (VOS_IS_STATUS_SUCCESS(status))
6243 {
6244 hdd_hostapd_state_t *pHostapdState =
6245 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6246
6247 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6248
6249 if (!VOS_IS_STATUS_SUCCESS(status))
6250 {
6251 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006252 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006253 }
6254 }
6255 else
6256 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006257 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 }
6259 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6260
6261 if (eHAL_STATUS_FAILURE ==
6262 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6263 0, NULL, eANI_BOOLEAN_FALSE))
6264 {
6265 hddLog(LOGE,
6266 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 }
6269
6270 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6271 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6272 eANI_BOOLEAN_FALSE) )
6273 {
6274 hddLog(LOGE,
6275 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6276 }
6277
6278 // Reset WNI_CFG_PROBE_RSP Flags
6279 wlan_hdd_reset_prob_rspies(pAdapter);
6280 kfree(pAdapter->sessionCtx.ap.beacon);
6281 pAdapter->sessionCtx.ap.beacon = NULL;
6282 }
6283 mutex_unlock(&pHddCtx->sap_lock);
6284 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006285
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006287#ifdef WLAN_OPEN_SOURCE
6288 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6289#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006291
Jeff Johnson295189b2012-06-20 16:38:30 -07006292 default:
6293 break;
6294 }
6295
6296 EXIT();
6297 return VOS_STATUS_SUCCESS;
6298}
6299
6300VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6301{
6302 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6303 VOS_STATUS status;
6304 hdd_adapter_t *pAdapter;
6305
6306 ENTER();
6307
6308 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6309
6310 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6311 {
6312 pAdapter = pAdapterNode->pAdapter;
6313 netif_tx_disable(pAdapter->dev);
6314 netif_carrier_off(pAdapter->dev);
6315
6316 hdd_stop_adapter( pHddCtx, pAdapter );
6317
6318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6319 pAdapterNode = pNext;
6320 }
6321
6322 EXIT();
6323
6324 return VOS_STATUS_SUCCESS;
6325}
6326
Rajeev Kumarf999e582014-01-09 17:33:29 -08006327
6328#ifdef FEATURE_WLAN_BATCH_SCAN
6329/**---------------------------------------------------------------------------
6330
6331 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6332 structures
6333
6334 \param - pAdapter Pointer to HDD adapter
6335
6336 \return - None
6337
6338 --------------------------------------------------------------------------*/
6339void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6340{
6341 tHddBatchScanRsp *pNode;
6342 tHddBatchScanRsp *pPrev;
6343
6344 if (pAdapter)
6345 {
6346 pNode = pAdapter->pBatchScanRsp;
6347 while (pNode)
6348 {
6349 pPrev = pNode;
6350 pNode = pNode->pNext;
6351 vos_mem_free((v_VOID_t * )pPrev);
6352 }
6353 pAdapter->pBatchScanRsp = NULL;
6354 }
6355
6356 pAdapter->pBatchScanRsp = NULL;
6357 pAdapter->numScanList = 0;
6358 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6359 pAdapter->prev_batch_id = 0;
6360
6361 return;
6362}
6363#endif
6364
6365
Jeff Johnson295189b2012-06-20 16:38:30 -07006366VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6367{
6368 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6369 VOS_STATUS status;
6370 hdd_adapter_t *pAdapter;
6371
6372 ENTER();
6373
6374 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6375
6376 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6377 {
6378 pAdapter = pAdapterNode->pAdapter;
6379 netif_tx_disable(pAdapter->dev);
6380 netif_carrier_off(pAdapter->dev);
6381
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006382 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6383
Jeff Johnson295189b2012-06-20 16:38:30 -07006384 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306385 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6386 {
6387 hdd_wmm_adapter_close( pAdapter );
6388 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006390
Rajeev Kumarf999e582014-01-09 17:33:29 -08006391#ifdef FEATURE_WLAN_BATCH_SCAN
6392 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6393 {
6394 hdd_deinit_batch_scan(pAdapter);
6395 }
6396#endif
6397
Jeff Johnson295189b2012-06-20 16:38:30 -07006398 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6399 pAdapterNode = pNext;
6400 }
6401
6402 EXIT();
6403
6404 return VOS_STATUS_SUCCESS;
6405}
6406
6407VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6408{
6409 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6410 VOS_STATUS status;
6411 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306412 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006413
6414 ENTER();
6415
6416 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6417
6418 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6419 {
6420 pAdapter = pAdapterNode->pAdapter;
6421
6422 switch(pAdapter->device_mode)
6423 {
6424 case WLAN_HDD_INFRA_STATION:
6425 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006426 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306427
6428 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6429
Jeff Johnson295189b2012-06-20 16:38:30 -07006430 hdd_init_station_mode(pAdapter);
6431 /* Open the gates for HDD to receive Wext commands */
6432 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006433 pHddCtx->scan_info.mScanPending = FALSE;
6434 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006435
6436 //Trigger the initial scan
6437 hdd_wlan_initial_scan(pAdapter);
6438
6439 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306440 if (eConnectionState_Associated == connState ||
6441 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006442 {
6443 union iwreq_data wrqu;
6444 memset(&wrqu, '\0', sizeof(wrqu));
6445 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6446 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6447 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006448 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006449
Jeff Johnson295189b2012-06-20 16:38:30 -07006450 /* indicate disconnected event to nl80211 */
6451 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6452 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006453 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306454 else if (eConnectionState_Connecting == connState)
6455 {
6456 /*
6457 * Indicate connect failure to supplicant if we were in the
6458 * process of connecting
6459 */
6460 cfg80211_connect_result(pAdapter->dev, NULL,
6461 NULL, 0, NULL, 0,
6462 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6463 GFP_KERNEL);
6464 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006465 break;
6466
6467 case WLAN_HDD_SOFTAP:
6468 /* softAP can handle SSR */
6469 break;
6470
6471 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006472 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006473 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006474 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 break;
6476
6477 case WLAN_HDD_MONITOR:
6478 /* monitor interface start */
6479 break;
6480 default:
6481 break;
6482 }
6483
6484 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6485 pAdapterNode = pNext;
6486 }
6487
6488 EXIT();
6489
6490 return VOS_STATUS_SUCCESS;
6491}
6492
6493VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6494{
6495 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6496 hdd_adapter_t *pAdapter;
6497 VOS_STATUS status;
6498 v_U32_t roamId;
6499
6500 ENTER();
6501
6502 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6503
6504 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6505 {
6506 pAdapter = pAdapterNode->pAdapter;
6507
6508 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6509 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6510 {
6511 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6512 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6513
6514 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6515 init_completion(&pAdapter->disconnect_comp_var);
6516 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6517 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6518
6519 wait_for_completion_interruptible_timeout(
6520 &pAdapter->disconnect_comp_var,
6521 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6522
6523 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6524 pHddCtx->isAmpAllowed = VOS_FALSE;
6525 sme_RoamConnect(pHddCtx->hHal,
6526 pAdapter->sessionId, &(pWextState->roamProfile),
6527 &roamId);
6528 }
6529
6530 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6531 pAdapterNode = pNext;
6532 }
6533
6534 EXIT();
6535
6536 return VOS_STATUS_SUCCESS;
6537}
6538
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006539void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6540{
6541 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6542 VOS_STATUS status;
6543 hdd_adapter_t *pAdapter;
6544 hdd_station_ctx_t *pHddStaCtx;
6545 hdd_ap_ctx_t *pHddApCtx;
6546 hdd_hostapd_state_t * pHostapdState;
6547 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6548 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6549 const char *p2pMode = "DEV";
6550 const char *ccMode = "Standalone";
6551 int n;
6552
6553 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6554 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6555 {
6556 pAdapter = pAdapterNode->pAdapter;
6557 switch (pAdapter->device_mode) {
6558 case WLAN_HDD_INFRA_STATION:
6559 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6560 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6561 staChannel = pHddStaCtx->conn_info.operationChannel;
6562 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6563 }
6564 break;
6565 case WLAN_HDD_P2P_CLIENT:
6566 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6567 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6568 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6569 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6570 p2pMode = "CLI";
6571 }
6572 break;
6573 case WLAN_HDD_P2P_GO:
6574 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6575 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6576 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6577 p2pChannel = pHddApCtx->operatingChannel;
6578 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6579 }
6580 p2pMode = "GO";
6581 break;
6582 case WLAN_HDD_SOFTAP:
6583 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6584 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6585 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6586 apChannel = pHddApCtx->operatingChannel;
6587 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6588 }
6589 break;
6590 default:
6591 break;
6592 }
6593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6594 pAdapterNode = pNext;
6595 }
6596 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6597 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6598 }
6599 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6600 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6601 if (p2pChannel > 0) {
6602 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6603 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6604 }
6605 if (apChannel > 0) {
6606 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6607 apChannel, MAC_ADDR_ARRAY(apBssid));
6608 }
6609
6610 if (p2pChannel > 0 && apChannel > 0) {
6611 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6612 }
6613}
6614
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006615bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006616{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006617 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006618}
6619
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006620/* Once SSR is disabled then it cannot be set. */
6621void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006622{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006623 if (HDD_SSR_DISABLED == isSsrRequired)
6624 return;
6625
Jeff Johnson295189b2012-06-20 16:38:30 -07006626 isSsrRequired = value;
6627}
6628
6629VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6630 hdd_adapter_list_node_t** ppAdapterNode)
6631{
6632 VOS_STATUS status;
6633 spin_lock(&pHddCtx->hddAdapters.lock);
6634 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6635 (hdd_list_node_t**) ppAdapterNode );
6636 spin_unlock(&pHddCtx->hddAdapters.lock);
6637 return status;
6638}
6639
6640VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6641 hdd_adapter_list_node_t* pAdapterNode,
6642 hdd_adapter_list_node_t** pNextAdapterNode)
6643{
6644 VOS_STATUS status;
6645 spin_lock(&pHddCtx->hddAdapters.lock);
6646 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6647 (hdd_list_node_t*) pAdapterNode,
6648 (hdd_list_node_t**)pNextAdapterNode );
6649
6650 spin_unlock(&pHddCtx->hddAdapters.lock);
6651 return status;
6652}
6653
6654VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6655 hdd_adapter_list_node_t* pAdapterNode)
6656{
6657 VOS_STATUS status;
6658 spin_lock(&pHddCtx->hddAdapters.lock);
6659 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6660 &pAdapterNode->node );
6661 spin_unlock(&pHddCtx->hddAdapters.lock);
6662 return status;
6663}
6664
6665VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6666 hdd_adapter_list_node_t** ppAdapterNode)
6667{
6668 VOS_STATUS status;
6669 spin_lock(&pHddCtx->hddAdapters.lock);
6670 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6671 (hdd_list_node_t**) ppAdapterNode );
6672 spin_unlock(&pHddCtx->hddAdapters.lock);
6673 return status;
6674}
6675
6676VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6677 hdd_adapter_list_node_t* pAdapterNode)
6678{
6679 VOS_STATUS status;
6680 spin_lock(&pHddCtx->hddAdapters.lock);
6681 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6682 (hdd_list_node_t*) pAdapterNode );
6683 spin_unlock(&pHddCtx->hddAdapters.lock);
6684 return status;
6685}
6686
6687VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6688 hdd_adapter_list_node_t* pAdapterNode)
6689{
6690 VOS_STATUS status;
6691 spin_lock(&pHddCtx->hddAdapters.lock);
6692 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6693 (hdd_list_node_t*) pAdapterNode );
6694 spin_unlock(&pHddCtx->hddAdapters.lock);
6695 return status;
6696}
6697
6698hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6699 tSirMacAddr macAddr )
6700{
6701 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6702 hdd_adapter_t *pAdapter;
6703 VOS_STATUS status;
6704
6705 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6706
6707 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6708 {
6709 pAdapter = pAdapterNode->pAdapter;
6710
6711 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6712 macAddr, sizeof(tSirMacAddr) ) )
6713 {
6714 return pAdapter;
6715 }
6716 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6717 pAdapterNode = pNext;
6718 }
6719
6720 return NULL;
6721
6722}
6723
6724hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6725{
6726 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6727 hdd_adapter_t *pAdapter;
6728 VOS_STATUS status;
6729
6730 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6731
6732 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6733 {
6734 pAdapter = pAdapterNode->pAdapter;
6735
6736 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6737 IFNAMSIZ ) )
6738 {
6739 return pAdapter;
6740 }
6741 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6742 pAdapterNode = pNext;
6743 }
6744
6745 return NULL;
6746
6747}
6748
6749hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6750{
6751 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6752 hdd_adapter_t *pAdapter;
6753 VOS_STATUS status;
6754
6755 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6756
6757 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6758 {
6759 pAdapter = pAdapterNode->pAdapter;
6760
6761 if( pAdapter && (mode == pAdapter->device_mode) )
6762 {
6763 return pAdapter;
6764 }
6765 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6766 pAdapterNode = pNext;
6767 }
6768
6769 return NULL;
6770
6771}
6772
6773//Remove this function later
6774hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6775{
6776 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6777 hdd_adapter_t *pAdapter;
6778 VOS_STATUS status;
6779
6780 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6781
6782 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6783 {
6784 pAdapter = pAdapterNode->pAdapter;
6785
6786 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6787 {
6788 return pAdapter;
6789 }
6790
6791 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6792 pAdapterNode = pNext;
6793 }
6794
6795 return NULL;
6796
6797}
6798
Jeff Johnson295189b2012-06-20 16:38:30 -07006799/**---------------------------------------------------------------------------
6800
6801 \brief hdd_set_monitor_tx_adapter() -
6802
6803 This API initializes the adapter to be used while transmitting on monitor
6804 adapter.
6805
6806 \param - pHddCtx - Pointer to the HDD context.
6807 pAdapter - Adapter that will used for TX. This can be NULL.
6808 \return - None.
6809 --------------------------------------------------------------------------*/
6810void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6811{
6812 hdd_adapter_t *pMonAdapter;
6813
6814 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6815
6816 if( NULL != pMonAdapter )
6817 {
6818 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6819 }
6820}
Jeff Johnson295189b2012-06-20 16:38:30 -07006821/**---------------------------------------------------------------------------
6822
6823 \brief hdd_select_queue() -
6824
6825 This API returns the operating channel of the requested device mode
6826
6827 \param - pHddCtx - Pointer to the HDD context.
6828 - mode - Device mode for which operating channel is required
6829 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6830 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6831 \return - channel number. "0" id the requested device is not found OR it is not connected.
6832 --------------------------------------------------------------------------*/
6833v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6834{
6835 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6836 VOS_STATUS status;
6837 hdd_adapter_t *pAdapter;
6838 v_U8_t operatingChannel = 0;
6839
6840 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6841
6842 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6843 {
6844 pAdapter = pAdapterNode->pAdapter;
6845
6846 if( mode == pAdapter->device_mode )
6847 {
6848 switch(pAdapter->device_mode)
6849 {
6850 case WLAN_HDD_INFRA_STATION:
6851 case WLAN_HDD_P2P_CLIENT:
6852 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6853 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6854 break;
6855 case WLAN_HDD_SOFTAP:
6856 case WLAN_HDD_P2P_GO:
6857 /*softap connection info */
6858 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6859 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6860 break;
6861 default:
6862 break;
6863 }
6864
6865 break; //Found the device of interest. break the loop
6866 }
6867
6868 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6869 pAdapterNode = pNext;
6870 }
6871 return operatingChannel;
6872}
6873
6874#ifdef WLAN_FEATURE_PACKET_FILTERING
6875/**---------------------------------------------------------------------------
6876
6877 \brief hdd_set_multicast_list() -
6878
6879 This used to set the multicast address list.
6880
6881 \param - dev - Pointer to the WLAN device.
6882 - skb - Pointer to OS packet (sk_buff).
6883 \return - success/fail
6884
6885 --------------------------------------------------------------------------*/
6886static void hdd_set_multicast_list(struct net_device *dev)
6887{
6888 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006889 int mc_count;
6890 int i = 0;
6891 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306892
6893 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006894 {
6895 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306896 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006897 return;
6898 }
6899
6900 if (dev->flags & IFF_ALLMULTI)
6901 {
6902 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006903 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306904 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006905 }
6906 else
6907 {
6908 mc_count = netdev_mc_count(dev);
6909 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006910 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006911 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6912 {
6913 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006914 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306915 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006916 return;
6917 }
6918
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306919 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006920
6921 netdev_for_each_mc_addr(ha, dev) {
6922 if (i == mc_count)
6923 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306924 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6925 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306928 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006929 i++;
6930 }
6931 }
6932 return;
6933}
6934#endif
6935
6936/**---------------------------------------------------------------------------
6937
6938 \brief hdd_select_queue() -
6939
6940 This function is registered with the Linux OS for network
6941 core to decide which queue to use first.
6942
6943 \param - dev - Pointer to the WLAN device.
6944 - skb - Pointer to OS packet (sk_buff).
6945 \return - ac, Queue Index/access category corresponding to UP in IP header
6946
6947 --------------------------------------------------------------------------*/
6948v_U16_t hdd_select_queue(struct net_device *dev,
6949 struct sk_buff *skb)
6950{
6951 return hdd_wmm_select_queue(dev, skb);
6952}
6953
6954
6955/**---------------------------------------------------------------------------
6956
6957 \brief hdd_wlan_initial_scan() -
6958
6959 This function triggers the initial scan
6960
6961 \param - pAdapter - Pointer to the HDD adapter.
6962
6963 --------------------------------------------------------------------------*/
6964void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6965{
6966 tCsrScanRequest scanReq;
6967 tCsrChannelInfo channelInfo;
6968 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006969 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6971
6972 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6973 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6974 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6975
6976 if(sme_Is11dSupported(pHddCtx->hHal))
6977 {
6978 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6979 if ( HAL_STATUS_SUCCESS( halStatus ) )
6980 {
6981 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6982 if( !scanReq.ChannelInfo.ChannelList )
6983 {
6984 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6985 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006986 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 return;
6988 }
6989 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6990 channelInfo.numOfChannels);
6991 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6992 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006993 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006994 }
6995
6996 scanReq.scanType = eSIR_PASSIVE_SCAN;
6997 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6998 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6999 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7000 }
7001 else
7002 {
7003 scanReq.scanType = eSIR_ACTIVE_SCAN;
7004 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7005 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7006 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7007 }
7008
7009 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7010 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7011 {
7012 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7013 __func__, halStatus );
7014 }
7015
7016 if(sme_Is11dSupported(pHddCtx->hHal))
7017 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7018}
7019
Jeff Johnson295189b2012-06-20 16:38:30 -07007020/**---------------------------------------------------------------------------
7021
7022 \brief hdd_full_power_callback() - HDD full power callback function
7023
7024 This is the function invoked by SME to inform the result of a full power
7025 request issued by HDD
7026
7027 \param - callbackcontext - Pointer to cookie
7028 \param - status - result of request
7029
7030 \return - None
7031
7032 --------------------------------------------------------------------------*/
7033static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7034{
Jeff Johnson72a40512013-12-19 10:14:15 -08007035 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007036
7037 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307038 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007039
7040 if (NULL == callbackContext)
7041 {
7042 hddLog(VOS_TRACE_LEVEL_ERROR,
7043 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007044 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007045 return;
7046 }
7047
Jeff Johnson72a40512013-12-19 10:14:15 -08007048 /* there is a race condition that exists between this callback
7049 function and the caller since the caller could time out either
7050 before or while this code is executing. we use a spinlock to
7051 serialize these actions */
7052 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007053
7054 if (POWER_CONTEXT_MAGIC != pContext->magic)
7055 {
7056 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007057 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007058 hddLog(VOS_TRACE_LEVEL_WARN,
7059 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007060 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007061 return;
7062 }
7063
Jeff Johnson72a40512013-12-19 10:14:15 -08007064 /* context is valid so caller is still waiting */
7065
7066 /* paranoia: invalidate the magic */
7067 pContext->magic = 0;
7068
7069 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007070 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007071
7072 /* serialization is complete */
7073 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007074}
7075
7076/**---------------------------------------------------------------------------
7077
7078 \brief hdd_wlan_exit() - HDD WLAN exit function
7079
7080 This is the driver exit point (invoked during rmmod)
7081
7082 \param - pHddCtx - Pointer to the HDD Context
7083
7084 \return - None
7085
7086 --------------------------------------------------------------------------*/
7087void hdd_wlan_exit(hdd_context_t *pHddCtx)
7088{
7089 eHalStatus halStatus;
7090 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7091 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307092 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007093 hdd_adapter_t* pAdapter;
Jeff Johnson72a40512013-12-19 10:14:15 -08007094 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007095 long lrc;
7096
7097 ENTER();
7098
Jeff Johnson88ba7742013-02-27 14:36:02 -08007099 if (VOS_FTM_MODE != hdd_get_conparam())
7100 {
7101 // Unloading, restart logic is no more required.
7102 wlan_hdd_restart_deinit(pHddCtx);
7103 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007104
Jeff Johnson295189b2012-06-20 16:38:30 -07007105 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007106 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007107 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007108 {
7109 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7110 WLAN_HDD_INFRA_STATION);
7111 if (pAdapter == NULL)
7112 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7113
7114 if (pAdapter != NULL)
7115 {
7116 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7117 hdd_UnregisterWext(pAdapter->dev);
7118 }
7119 }
7120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007121
Jeff Johnson295189b2012-06-20 16:38:30 -07007122 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007123 {
7124 wlan_hdd_ftm_close(pHddCtx);
7125 goto free_hdd_ctx;
7126 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007127 //Stop the Interface TX queue.
7128 //netif_tx_disable(pWlanDev);
7129 //netif_carrier_off(pWlanDev);
7130
Jeff Johnson295189b2012-06-20 16:38:30 -07007131 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7132 {
7133 pAdapter = hdd_get_adapter(pHddCtx,
7134 WLAN_HDD_SOFTAP);
7135 }
7136 else
7137 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007139 {
7140 pAdapter = hdd_get_adapter(pHddCtx,
7141 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007142 if (pAdapter == NULL)
7143 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007144 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007146 /* DeRegister with platform driver as client for Suspend/Resume */
7147 vosStatus = hddDeregisterPmOps(pHddCtx);
7148 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7149 {
7150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7151 VOS_ASSERT(0);
7152 }
7153
7154 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7155 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7156 {
7157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7158 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007159
7160 // Cancel any outstanding scan requests. We are about to close all
7161 // of our adapters, but an adapter structure is what SME passes back
7162 // to our callback function. Hence if there are any outstanding scan
7163 // requests then there is a race condition between when the adapter
7164 // is closed and when the callback is invoked. We try to resolve that
7165 // race condition here by canceling any outstanding scans before we
7166 // close the adapters.
7167 // Note that the scans may be cancelled in an asynchronous manner, so
7168 // ideally there needs to be some kind of synchronization. Rather than
7169 // introduce a new synchronization here, we will utilize the fact that
7170 // we are about to Request Full Power, and since that is synchronized,
7171 // the expectation is that by the time Request Full Power has completed,
7172 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007173 if (NULL != pAdapter)
7174 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7175 else
7176 hddLog(VOS_TRACE_LEVEL_ERROR,
7177 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007178
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007179 //Stop the traffic monitor timer
7180 if ( VOS_TIMER_STATE_RUNNING ==
7181 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7182 {
7183 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7184 }
7185
7186 // Destroy the traffic monitor timer
7187 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7188 &pHddCtx->tx_rx_trafficTmr)))
7189 {
7190 hddLog(VOS_TRACE_LEVEL_ERROR,
7191 "%s: Cannot deallocate Traffic monitor timer", __func__);
7192 }
7193
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 //Disable IMPS/BMPS as we do not want the device to enter any power
7195 //save mode during shutdown
7196 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7197 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7198 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7199
7200 //Ensure that device is in full power as we will touch H/W during vos_Stop
7201 init_completion(&powerContext.completion);
7202 powerContext.magic = POWER_CONTEXT_MAGIC;
7203
7204 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7205 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7206
7207 if (eHAL_STATUS_SUCCESS != halStatus)
7208 {
7209 if (eHAL_STATUS_PMC_PENDING == halStatus)
7210 {
7211 /* request was sent -- wait for the response */
7212 lrc = wait_for_completion_interruptible_timeout(
7213 &powerContext.completion,
7214 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007215 if (lrc <= 0)
7216 {
7217 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007218 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007219 }
7220 }
7221 else
7222 {
7223 hddLog(VOS_TRACE_LEVEL_ERROR,
7224 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007225 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007226 /* continue -- need to clean up as much as possible */
7227 }
7228 }
7229
Jeff Johnson72a40512013-12-19 10:14:15 -08007230 /* either we never sent a request, we sent a request and received a
7231 response or we sent a request and timed out. if we never sent a
7232 request or if we sent a request and got a response, we want to
7233 clear the magic out of paranoia. if we timed out there is a
7234 race condition such that the callback function could be
7235 executing at the same time we are. of primary concern is if the
7236 callback function had already verified the "magic" but had not
7237 yet set the completion variable when a timeout occurred. we
7238 serialize these activities by invalidating the magic while
7239 holding a shared spinlock which will cause us to block if the
7240 callback is currently executing */
7241 spin_lock(&hdd_context_lock);
7242 powerContext.magic = 0;
7243 spin_unlock(&hdd_context_lock);
7244
Yue Ma0d4891e2013-08-06 17:01:45 -07007245 hdd_debugfs_exit(pHddCtx);
7246
Jeff Johnson295189b2012-06-20 16:38:30 -07007247 // Unregister the Net Device Notifier
7248 unregister_netdevice_notifier(&hdd_netdev_notifier);
7249
Jeff Johnson295189b2012-06-20 16:38:30 -07007250 hdd_stop_all_adapters( pHddCtx );
7251
Jeff Johnson295189b2012-06-20 16:38:30 -07007252#ifdef WLAN_BTAMP_FEATURE
7253 vosStatus = WLANBAP_Stop(pVosContext);
7254 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7255 {
7256 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7257 "%s: Failed to stop BAP",__func__);
7258 }
7259#endif //WLAN_BTAMP_FEATURE
7260
7261 //Stop all the modules
7262 vosStatus = vos_stop( pVosContext );
7263 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7264 {
7265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7266 "%s: Failed to stop VOSS",__func__);
7267 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7268 }
7269
Jeff Johnson295189b2012-06-20 16:38:30 -07007270 //Assert Deep sleep signal now to put Libra HW in lowest power state
7271 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7272 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7273
7274 //Vote off any PMIC voltage supplies
7275 vos_chipPowerDown(NULL, NULL, NULL);
7276
7277 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7278
Leo Chang59cdc7e2013-07-10 10:08:21 -07007279
Jeff Johnson295189b2012-06-20 16:38:30 -07007280 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007281 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007282
7283 //Close the scheduler before calling vos_close to make sure no thread is
7284 // scheduled after the each module close is called i.e after all the data
7285 // structures are freed.
7286 vosStatus = vos_sched_close( pVosContext );
7287 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7288 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7289 "%s: Failed to close VOSS Scheduler",__func__);
7290 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7291 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007292#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007293#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7294 /* Destroy the wake lock */
7295 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7296#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007297 /* Destroy the wake lock */
7298 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007299#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007300
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307301#ifdef CONFIG_ENABLE_LINUX_REG
7302 vosStatus = vos_nv_close();
7303 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7304 {
7305 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7306 "%s: Failed to close NV", __func__);
7307 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7308 }
7309#endif
7310
Jeff Johnson295189b2012-06-20 16:38:30 -07007311 //Close VOSS
7312 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7313 vos_close(pVosContext);
7314
Jeff Johnson295189b2012-06-20 16:38:30 -07007315 //Close Watchdog
7316 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7317 vos_watchdog_close(pVosContext);
7318
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307319 //Clean up HDD Nlink Service
7320 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007321#ifdef WLAN_KD_READY_NOTIFIER
7322 nl_srv_exit(pHddCtx->ptt_pid);
7323#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307324 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007325#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307326
Jeff Johnson295189b2012-06-20 16:38:30 -07007327 /* Cancel the vote for XO Core ON.
7328 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7329 * exited at this point
7330 */
7331 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007332 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007333 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7334 {
7335 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7336 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007337 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007338 }
7339
7340 hdd_close_all_adapters( pHddCtx );
7341
7342
7343 //Free up dynamically allocated members inside HDD Adapter
7344 kfree(pHddCtx->cfg_ini);
7345 pHddCtx->cfg_ini= NULL;
7346
7347 /* free the power on lock from platform driver */
7348 if (free_riva_power_on_lock("wlan"))
7349 {
7350 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7351 __func__);
7352 }
7353
Jeff Johnson88ba7742013-02-27 14:36:02 -08007354free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007355 /* FTM mode, WIPHY did not registered
7356 If un-register here, system crash will happen */
7357 if (VOS_FTM_MODE != hdd_get_conparam())
7358 {
7359 wiphy_unregister(wiphy) ;
7360 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007361 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007362 if (hdd_is_ssr_required())
7363 {
7364 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007365 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007366 msleep(5000);
7367 }
7368 hdd_set_ssr_required (VOS_FALSE);
7369}
7370
7371
7372/**---------------------------------------------------------------------------
7373
7374 \brief hdd_update_config_from_nv() - Function to update the contents of
7375 the running configuration with parameters taken from NV storage
7376
7377 \param - pHddCtx - Pointer to the HDD global context
7378
7379 \return - VOS_STATUS_SUCCESS if successful
7380
7381 --------------------------------------------------------------------------*/
7382static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7383{
Jeff Johnson295189b2012-06-20 16:38:30 -07007384 v_BOOL_t itemIsValid = VOS_FALSE;
7385 VOS_STATUS status;
7386 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7387 v_U8_t macLoop;
7388
7389 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7390 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7391 if(status != VOS_STATUS_SUCCESS)
7392 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007393 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007394 return VOS_STATUS_E_FAILURE;
7395 }
7396
7397 if (itemIsValid == VOS_TRUE)
7398 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007399 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007400 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7401 VOS_MAX_CONCURRENCY_PERSONA);
7402 if(status != VOS_STATUS_SUCCESS)
7403 {
7404 /* Get MAC from NV fail, not update CFG info
7405 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007406 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007407 return VOS_STATUS_E_FAILURE;
7408 }
7409
7410 /* If first MAC is not valid, treat all others are not valid
7411 * Then all MACs will be got from ini file */
7412 if(vos_is_macaddr_zero(&macFromNV[0]))
7413 {
7414 /* MAC address in NV file is not configured yet */
7415 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7416 return VOS_STATUS_E_INVAL;
7417 }
7418
7419 /* Get MAC address from NV, update CFG info */
7420 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7421 {
7422 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7423 {
7424 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7425 /* This MAC is not valid, skip it
7426 * This MAC will be got from ini file */
7427 }
7428 else
7429 {
7430 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7431 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7432 VOS_MAC_ADDR_SIZE);
7433 }
7434 }
7435 }
7436 else
7437 {
7438 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7439 return VOS_STATUS_E_FAILURE;
7440 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007441
Jeff Johnson295189b2012-06-20 16:38:30 -07007442
7443 return VOS_STATUS_SUCCESS;
7444}
7445
7446/**---------------------------------------------------------------------------
7447
7448 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7449
7450 \param - pAdapter - Pointer to the HDD
7451
7452 \return - None
7453
7454 --------------------------------------------------------------------------*/
7455VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7456{
7457 eHalStatus halStatus;
7458 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307459 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007460
Jeff Johnson295189b2012-06-20 16:38:30 -07007461
7462 // Send ready indication to the HDD. This will kick off the MAC
7463 // into a 'running' state and should kick off an initial scan.
7464 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7465 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7466 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307467 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007468 "code %08d [x%08x]",__func__, halStatus, halStatus );
7469 return VOS_STATUS_E_FAILURE;
7470 }
7471
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307472 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007473 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7474 // And RIVA will crash
7475 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7476 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307477 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7478 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7479
7480
Jeff Johnson295189b2012-06-20 16:38:30 -07007481 return VOS_STATUS_SUCCESS;
7482}
7483
Jeff Johnson295189b2012-06-20 16:38:30 -07007484/* wake lock APIs for HDD */
7485void hdd_prevent_suspend(void)
7486{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007487#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007488 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007489#else
7490 wcnss_prevent_suspend();
7491#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007492}
7493
7494void hdd_allow_suspend(void)
7495{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007496#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007497 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007498#else
7499 wcnss_allow_suspend();
7500#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007501}
7502
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007503void hdd_allow_suspend_timeout(v_U32_t timeout)
7504{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007505#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007506 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007507#else
7508 /* Do nothing as there is no API in wcnss for timeout*/
7509#endif
7510}
7511
Jeff Johnson295189b2012-06-20 16:38:30 -07007512/**---------------------------------------------------------------------------
7513
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007514 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7515 information between Host and Riva
7516
7517 This function gets reported version of FW
7518 It also finds the version of Riva headers used to compile the host
7519 It compares the above two and prints a warning if they are different
7520 It gets the SW and HW version string
7521 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7522 indicating the features they support through a bitmap
7523
7524 \param - pHddCtx - Pointer to HDD context
7525
7526 \return - void
7527
7528 --------------------------------------------------------------------------*/
7529
7530void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7531{
7532
7533 tSirVersionType versionCompiled;
7534 tSirVersionType versionReported;
7535 tSirVersionString versionString;
7536 tANI_U8 fwFeatCapsMsgSupported = 0;
7537 VOS_STATUS vstatus;
7538
7539 /* retrieve and display WCNSS version information */
7540 do {
7541
7542 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7543 &versionCompiled);
7544 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7545 {
7546 hddLog(VOS_TRACE_LEVEL_FATAL,
7547 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007548 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007549 break;
7550 }
7551
7552 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7553 &versionReported);
7554 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7555 {
7556 hddLog(VOS_TRACE_LEVEL_FATAL,
7557 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007558 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007559 break;
7560 }
7561
7562 if ((versionCompiled.major != versionReported.major) ||
7563 (versionCompiled.minor != versionReported.minor) ||
7564 (versionCompiled.version != versionReported.version) ||
7565 (versionCompiled.revision != versionReported.revision))
7566 {
7567 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7568 "Host expected %u.%u.%u.%u\n",
7569 WLAN_MODULE_NAME,
7570 (int)versionReported.major,
7571 (int)versionReported.minor,
7572 (int)versionReported.version,
7573 (int)versionReported.revision,
7574 (int)versionCompiled.major,
7575 (int)versionCompiled.minor,
7576 (int)versionCompiled.version,
7577 (int)versionCompiled.revision);
7578 }
7579 else
7580 {
7581 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7582 WLAN_MODULE_NAME,
7583 (int)versionReported.major,
7584 (int)versionReported.minor,
7585 (int)versionReported.version,
7586 (int)versionReported.revision);
7587 }
7588
7589 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7590 versionString,
7591 sizeof(versionString));
7592 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7593 {
7594 hddLog(VOS_TRACE_LEVEL_FATAL,
7595 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007596 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007597 break;
7598 }
7599
7600 pr_info("%s: WCNSS software version %s\n",
7601 WLAN_MODULE_NAME, versionString);
7602
7603 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7604 versionString,
7605 sizeof(versionString));
7606 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7607 {
7608 hddLog(VOS_TRACE_LEVEL_FATAL,
7609 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007610 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007611 break;
7612 }
7613
7614 pr_info("%s: WCNSS hardware version %s\n",
7615 WLAN_MODULE_NAME, versionString);
7616
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007617 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7618 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007619 send the message only if it the riva is 1.1
7620 minor numbers for different riva branches:
7621 0 -> (1.0)Mainline Build
7622 1 -> (1.1)Mainline Build
7623 2->(1.04) Stability Build
7624 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007625 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007626 ((versionReported.minor>=1) && (versionReported.version>=1)))
7627 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7628 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007629
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007630 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007631 {
7632#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7633 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7634 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7635#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007636 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7637 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7638 {
7639 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7640 }
7641
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007642 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007643 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007644
7645 } while (0);
7646
7647}
7648
7649/**---------------------------------------------------------------------------
7650
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307651 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7652
7653 \param - pHddCtx - Pointer to the hdd context
7654
7655 \return - true if hardware supports 5GHz
7656
7657 --------------------------------------------------------------------------*/
7658static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7659{
7660 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7661 * then hardware support 5Ghz.
7662 */
7663 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7664 {
7665 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7666 return true;
7667 }
7668 else
7669 {
7670 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7671 __func__);
7672 return false;
7673 }
7674}
7675
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307676/**---------------------------------------------------------------------------
7677
7678 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7679 generate function
7680
7681 This is generate the random mac address for WLAN interface
7682
7683 \param - pHddCtx - Pointer to HDD context
7684 idx - Start interface index to get auto
7685 generated mac addr.
7686 mac_addr - Mac address
7687
7688 \return - 0 for success, < 0 for failure
7689
7690 --------------------------------------------------------------------------*/
7691
7692static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7693 int idx, v_MACADDR_t mac_addr)
7694{
7695 int i;
7696 unsigned int serialno;
7697 serialno = wcnss_get_serial_number();
7698
7699 if (0 != serialno)
7700 {
7701 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7702 bytes of the serial number that can be used to generate
7703 the other 3 bytes of the MAC address. Mask off all but
7704 the lower 3 bytes (this will also make sure we don't
7705 overflow in the next step) */
7706 serialno &= 0x00FFFFFF;
7707
7708 /* we need a unique address for each session */
7709 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7710
7711 /* autogen other Mac addresses */
7712 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7713 {
7714 /* start with the entire default address */
7715 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7716 /* then replace the lower 3 bytes */
7717 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7718 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7719 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7720
7721 serialno++;
7722 hddLog(VOS_TRACE_LEVEL_ERROR,
7723 "%s: Derived Mac Addr: "
7724 MAC_ADDRESS_STR, __func__,
7725 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7726 }
7727
7728 }
7729 else
7730 {
7731 hddLog(LOGE, FL("Failed to Get Serial NO"));
7732 return -1;
7733 }
7734 return 0;
7735}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307736
7737/**---------------------------------------------------------------------------
7738
Jeff Johnson295189b2012-06-20 16:38:30 -07007739 \brief hdd_wlan_startup() - HDD init function
7740
7741 This is the driver startup code executed once a WLAN device has been detected
7742
7743 \param - dev - Pointer to the underlying device
7744
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007745 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007746
7747 --------------------------------------------------------------------------*/
7748
7749int hdd_wlan_startup(struct device *dev )
7750{
7751 VOS_STATUS status;
7752 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007753 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 hdd_context_t *pHddCtx = NULL;
7755 v_CONTEXT_t pVosContext= NULL;
7756#ifdef WLAN_BTAMP_FEATURE
7757 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7758 WLANBAP_ConfigType btAmpConfig;
7759 hdd_config_t *pConfig;
7760#endif
7761 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007762 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307763 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007764
7765 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007766 /*
7767 * cfg80211: wiphy allocation
7768 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307769 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007770
7771 if(wiphy == NULL)
7772 {
7773 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007774 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007775 }
7776
7777 pHddCtx = wiphy_priv(wiphy);
7778
Jeff Johnson295189b2012-06-20 16:38:30 -07007779 //Initialize the adapter context to zeros.
7780 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7781
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007783 hdd_prevent_suspend();
7784 pHddCtx->isLoadUnloadInProgress = TRUE;
7785
7786 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7787
7788 /*Get vos context here bcoz vos_open requires it*/
7789 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7790
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007791 if(pVosContext == NULL)
7792 {
7793 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7794 goto err_free_hdd_context;
7795 }
7796
Jeff Johnson295189b2012-06-20 16:38:30 -07007797 //Save the Global VOSS context in adapter context for future.
7798 pHddCtx->pvosContext = pVosContext;
7799
7800 //Save the adapter context in global context for future.
7801 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7802
Jeff Johnson295189b2012-06-20 16:38:30 -07007803 pHddCtx->parent_dev = dev;
7804
7805 init_completion(&pHddCtx->full_pwr_comp_var);
7806 init_completion(&pHddCtx->standby_comp_var);
7807 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007808 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007809 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307810 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007811
7812#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007813 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007814#else
7815 init_completion(&pHddCtx->driver_crda_req);
7816#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007817
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307818 spin_lock_init(&pHddCtx->schedScan_lock);
7819
Jeff Johnson295189b2012-06-20 16:38:30 -07007820 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7821
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307822#ifdef FEATURE_WLAN_TDLS
7823 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7824 * invoked by other instances also) to protect the concurrent
7825 * access for the Adapters by TDLS module.
7826 */
7827 mutex_init(&pHddCtx->tdls_lock);
7828#endif
7829
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307830 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007831 // Load all config first as TL config is needed during vos_open
7832 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7833 if(pHddCtx->cfg_ini == NULL)
7834 {
7835 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7836 goto err_free_hdd_context;
7837 }
7838
7839 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7840
7841 // Read and parse the qcom_cfg.ini file
7842 status = hdd_parse_config_ini( pHddCtx );
7843 if ( VOS_STATUS_SUCCESS != status )
7844 {
7845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7846 __func__, WLAN_INI_FILE);
7847 goto err_config;
7848 }
Arif Hussaind5218912013-12-05 01:10:55 -08007849#ifdef MEMORY_DEBUG
7850 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7851 vos_mem_init();
7852
7853 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7854 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7855#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007856
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307857 /* INI has been read, initialise the configuredMcastBcastFilter with
7858 * INI value as this will serve as the default value
7859 */
7860 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7861 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7862 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307863
7864 if (false == hdd_is_5g_supported(pHddCtx))
7865 {
7866 //5Ghz is not supported.
7867 if (1 != pHddCtx->cfg_ini->nBandCapability)
7868 {
7869 hddLog(VOS_TRACE_LEVEL_INFO,
7870 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7871 pHddCtx->cfg_ini->nBandCapability = 1;
7872 }
7873 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307874
7875 /* If SNR Monitoring is enabled, FW has to parse all beacons
7876 * for calcaluting and storing the average SNR, so set Nth beacon
7877 * filter to 1 to enable FW to parse all the beaocons
7878 */
7879 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7880 {
7881 /* The log level is deliberately set to WARN as overriding
7882 * nthBeaconFilter to 1 will increase power cosumption and this
7883 * might just prove helpful to detect the power issue.
7884 */
7885 hddLog(VOS_TRACE_LEVEL_WARN,
7886 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7887 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7888 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307890 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007891 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08007892 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007893 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08007894 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
7895 {
7896 hddLog(VOS_TRACE_LEVEL_FATAL,
7897 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7898 goto err_config;
7899 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007901
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007902 // Update VOS trace levels based upon the cfg.ini
7903 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7904 pHddCtx->cfg_ini->vosTraceEnableBAP);
7905 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7906 pHddCtx->cfg_ini->vosTraceEnableTL);
7907 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7908 pHddCtx->cfg_ini->vosTraceEnableWDI);
7909 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7910 pHddCtx->cfg_ini->vosTraceEnableHDD);
7911 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7912 pHddCtx->cfg_ini->vosTraceEnableSME);
7913 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7914 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307915 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7916 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007917 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7918 pHddCtx->cfg_ini->vosTraceEnableWDA);
7919 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7920 pHddCtx->cfg_ini->vosTraceEnableSYS);
7921 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7922 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007923 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7924 pHddCtx->cfg_ini->vosTraceEnableSAP);
7925 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7926 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007927
Jeff Johnson295189b2012-06-20 16:38:30 -07007928 // Update WDI trace levels based upon the cfg.ini
7929 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7930 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7931 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7932 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7933 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7934 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7935 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7936 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007937
Jeff Johnson88ba7742013-02-27 14:36:02 -08007938 if (VOS_FTM_MODE == hdd_get_conparam())
7939 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007940 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7941 {
7942 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7943 goto err_free_hdd_context;
7944 }
7945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7946 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007948
Jeff Johnson88ba7742013-02-27 14:36:02 -08007949 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007950 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7951 {
7952 status = vos_watchdog_open(pVosContext,
7953 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7954
7955 if(!VOS_IS_STATUS_SUCCESS( status ))
7956 {
7957 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307958 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007959 }
7960 }
7961
7962 pHddCtx->isLogpInProgress = FALSE;
7963 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7964
Jeff Johnson295189b2012-06-20 16:38:30 -07007965 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7966 if(!VOS_IS_STATUS_SUCCESS(status))
7967 {
7968 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007969 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007970 }
7971
Amar Singhala49cbc52013-10-08 18:37:44 -07007972#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007973 /* initialize the NV module. This is required so that
7974 we can initialize the channel information in wiphy
7975 from the NV.bin data. The channel information in
7976 wiphy needs to be initialized before wiphy registration */
7977
7978 status = vos_nv_open();
7979 if (!VOS_IS_STATUS_SUCCESS(status))
7980 {
7981 /* NV module cannot be initialized */
7982 hddLog( VOS_TRACE_LEVEL_FATAL,
7983 "%s: vos_nv_open failed", __func__);
7984 goto err_clkvote;
7985 }
7986
7987 status = vos_init_wiphy_from_nv_bin();
7988 if (!VOS_IS_STATUS_SUCCESS(status))
7989 {
7990 /* NV module cannot be initialized */
7991 hddLog( VOS_TRACE_LEVEL_FATAL,
7992 "%s: vos_init_wiphy failed", __func__);
7993 goto err_vos_nv_close;
7994 }
7995
Amar Singhala49cbc52013-10-08 18:37:44 -07007996 /* registration of wiphy dev with cfg80211 */
7997 if (0 > wlan_hdd_cfg80211_register(wiphy))
7998 {
7999 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07008000 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07008001 }
8002#endif
8003
Jeff Johnson295189b2012-06-20 16:38:30 -07008004 status = vos_open( &pVosContext, 0);
8005 if ( !VOS_IS_STATUS_SUCCESS( status ))
8006 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008007 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07008008 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008009 }
8010
Jeff Johnson295189b2012-06-20 16:38:30 -07008011 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8012
8013 if ( NULL == pHddCtx->hHal )
8014 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008015 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 goto err_vosclose;
8017 }
8018
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008019 status = vos_preStart( pHddCtx->pvosContext );
8020 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8021 {
8022 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
8023 goto err_vosclose;
8024 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008025
Arif Hussaineaf68602013-12-30 23:10:44 -08008026 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8027 {
8028 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8030 __func__, enable_dfs_chan_scan);
8031 }
8032 if (0 == enable_11d || 1 == enable_11d)
8033 {
8034 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8035 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8036 __func__, enable_11d);
8037 }
8038
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008039 /* Note that the vos_preStart() sequence triggers the cfg download.
8040 The cfg download must occur before we update the SME config
8041 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008042 status = hdd_set_sme_config( pHddCtx );
8043
8044 if ( VOS_STATUS_SUCCESS != status )
8045 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
8047 goto err_vosclose;
8048 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008049
8050 //Initialize the WMM module
8051 status = hdd_wmm_init(pHddCtx);
8052 if (!VOS_IS_STATUS_SUCCESS(status))
8053 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008054 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008055 goto err_vosclose;
8056 }
8057
Jeff Johnson295189b2012-06-20 16:38:30 -07008058 /* In the integrated architecture we update the configuration from
8059 the INI file and from NV before vOSS has been started so that
8060 the final contents are available to send down to the cCPU */
8061
8062 // Apply the cfg.ini to cfg.dat
8063 if (FALSE == hdd_update_config_dat(pHddCtx))
8064 {
8065 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
8066 goto err_vosclose;
8067 }
8068
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308069 // Get mac addr from platform driver
8070 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8071
8072 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008073 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308074 /* Store the mac addr for first interface */
8075 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8076
8077 hddLog(VOS_TRACE_LEVEL_ERROR,
8078 "%s: WLAN Mac Addr: "
8079 MAC_ADDRESS_STR, __func__,
8080 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8081
8082 /* Here, passing Arg2 as 1 because we do not want to change the
8083 last 3 bytes (means non OUI bytes) of first interface mac
8084 addr.
8085 */
8086 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8087 {
8088 hddLog(VOS_TRACE_LEVEL_ERROR,
8089 "%s: Failed to generate wlan interface mac addr "
8090 "using MAC from ini file ", __func__);
8091 }
8092 }
8093 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8094 {
8095 // Apply the NV to cfg.dat
8096 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008097#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8098 /* There was not a valid set of MAC Addresses in NV. See if the
8099 default addresses were modified by the cfg.ini settings. If so,
8100 we'll use them, but if not, we'll autogenerate a set of MAC
8101 addresses based upon the device serial number */
8102
8103 static const v_MACADDR_t default_address =
8104 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008105
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308106 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8107 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 {
8109 /* cfg.ini has the default address, invoke autogen logic */
8110
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308111 /* Here, passing Arg2 as 0 because we want to change the
8112 last 3 bytes (means non OUI bytes) of all the interfaces
8113 mac addr.
8114 */
8115 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8116 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308118 hddLog(VOS_TRACE_LEVEL_ERROR,
8119 "%s: Failed to generate wlan interface mac addr "
8120 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8121 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 }
8124 else
8125#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8126 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008127 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008128 "%s: Invalid MAC address in NV, using MAC from ini file "
8129 MAC_ADDRESS_STR, __func__,
8130 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8131 }
8132 }
8133 {
8134 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308135
8136 /* Set the MAC Address Currently this is used by HAL to
8137 * add self sta. Remove this once self sta is added as
8138 * part of session open.
8139 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008140 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8141 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8142 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308143
Jeff Johnson295189b2012-06-20 16:38:30 -07008144 if (!HAL_STATUS_SUCCESS( halStatus ))
8145 {
8146 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8147 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08008148 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 }
8150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008151
8152 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8153 Note: Firmware image will be read and downloaded inside vos_start API */
8154 status = vos_start( pHddCtx->pvosContext );
8155 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8156 {
8157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
8158 goto err_vosclose;
8159 }
8160
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008161 /* Exchange capability info between Host and FW and also get versioning info from FW */
8162 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008163
8164 status = hdd_post_voss_start_config( pHddCtx );
8165 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8166 {
8167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8168 __func__);
8169 goto err_vosstop;
8170 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008171
8172#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308173 wlan_hdd_cfg80211_update_reg_info( wiphy );
8174
8175 /* registration of wiphy dev with cfg80211 */
8176 if (0 > wlan_hdd_cfg80211_register(wiphy))
8177 {
8178 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8179 goto err_vosstop;
8180 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008182
Jeff Johnson295189b2012-06-20 16:38:30 -07008183 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8184 {
8185 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8186 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8187 }
8188 else
8189 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008190 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8191 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8192 if (pAdapter != NULL)
8193 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308194 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308196 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8197 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8198 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008199
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308200 /* Generate the P2P Device Address. This consists of the device's
8201 * primary MAC address with the locally administered bit set.
8202 */
8203 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008204 }
8205 else
8206 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308207 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8208 if (p2p_dev_addr != NULL)
8209 {
8210 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8211 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8212 }
8213 else
8214 {
8215 hddLog(VOS_TRACE_LEVEL_FATAL,
8216 "%s: Failed to allocate mac_address for p2p_device",
8217 __func__);
8218 goto err_close_adapter;
8219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008220 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008221
8222 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8223 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8224 if ( NULL == pP2pAdapter )
8225 {
8226 hddLog(VOS_TRACE_LEVEL_FATAL,
8227 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008228 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008229 goto err_close_adapter;
8230 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008231 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008232 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008233
8234 if( pAdapter == NULL )
8235 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008236 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8237 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008238 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008239
Arif Hussain66559122013-11-21 10:11:40 -08008240 if (country_code)
8241 {
8242 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008243 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008244 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8245#ifndef CONFIG_ENABLE_LINUX_REG
8246 hdd_checkandupdate_phymode(pAdapter, country_code);
8247#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008248 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8249 (void *)(tSmeChangeCountryCallback)
8250 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008251 country_code,
8252 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308253 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008254 if (eHAL_STATUS_SUCCESS == ret)
8255 {
Arif Hussaincb607082013-12-20 11:57:42 -08008256 ret = wait_for_completion_interruptible_timeout(
8257 &pAdapter->change_country_code,
8258 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8259
8260 if (0 >= ret)
8261 {
8262 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8263 "%s: SME while setting country code timed out", __func__);
8264 }
Arif Hussain66559122013-11-21 10:11:40 -08008265 }
8266 else
8267 {
Arif Hussaincb607082013-12-20 11:57:42 -08008268 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8269 "%s: SME Change Country code from module param fail ret=%d",
8270 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008271 }
8272 }
8273
Jeff Johnson295189b2012-06-20 16:38:30 -07008274#ifdef WLAN_BTAMP_FEATURE
8275 vStatus = WLANBAP_Open(pVosContext);
8276 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8277 {
8278 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8279 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008280 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008281 }
8282
8283 vStatus = BSL_Init(pVosContext);
8284 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8285 {
8286 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8287 "%s: Failed to Init BSL",__func__);
8288 goto err_bap_close;
8289 }
8290 vStatus = WLANBAP_Start(pVosContext);
8291 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8292 {
8293 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8294 "%s: Failed to start TL",__func__);
8295 goto err_bap_close;
8296 }
8297
8298 pConfig = pHddCtx->cfg_ini;
8299 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8300 status = WLANBAP_SetConfig(&btAmpConfig);
8301
8302#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008303
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008304#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8305 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8306 {
8307 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8308 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8309 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8310 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8311 }
8312#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008313#ifdef FEATURE_WLAN_SCAN_PNO
8314 /*SME must send channel update configuration to RIVA*/
8315 sme_UpdateChannelConfig(pHddCtx->hHal);
8316#endif
8317
Jeff Johnson295189b2012-06-20 16:38:30 -07008318 /* Register with platform driver as client for Suspend/Resume */
8319 status = hddRegisterPmOps(pHddCtx);
8320 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8321 {
8322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8323#ifdef WLAN_BTAMP_FEATURE
8324 goto err_bap_stop;
8325#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008326 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008327#endif //WLAN_BTAMP_FEATURE
8328 }
8329
Yue Ma0d4891e2013-08-06 17:01:45 -07008330 /* Open debugfs interface */
8331 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8332 {
8333 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8334 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008335 }
8336
Jeff Johnson295189b2012-06-20 16:38:30 -07008337 /* Register TM level change handler function to the platform */
8338 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8339 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8340 {
8341 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8342 goto err_unregister_pmops;
8343 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008344
8345 /* register for riva power on lock to platform driver */
8346 if (req_riva_power_on_lock("wlan"))
8347 {
8348 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8349 __func__);
8350 goto err_unregister_pmops;
8351 }
8352
Jeff Johnson295189b2012-06-20 16:38:30 -07008353 // register net device notifier for device change notification
8354 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8355
8356 if(ret < 0)
8357 {
8358 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8359 goto err_free_power_on_lock;
8360 }
8361
8362 //Initialize the nlink service
8363 if(nl_srv_init() != 0)
8364 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308365 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008366 goto err_reg_netdev;
8367 }
8368
Leo Chang4ce1cc52013-10-21 18:27:15 -07008369#ifdef WLAN_KD_READY_NOTIFIER
8370 pHddCtx->kd_nl_init = 1;
8371#endif /* WLAN_KD_READY_NOTIFIER */
8372
Jeff Johnson295189b2012-06-20 16:38:30 -07008373 //Initialize the BTC service
8374 if(btc_activate_service(pHddCtx) != 0)
8375 {
8376 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8377 goto err_nl_srv;
8378 }
8379
8380#ifdef PTT_SOCK_SVC_ENABLE
8381 //Initialize the PTT service
8382 if(ptt_sock_activate_svc(pHddCtx) != 0)
8383 {
8384 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8385 goto err_nl_srv;
8386 }
8387#endif
8388
Jeff Johnson295189b2012-06-20 16:38:30 -07008389 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008390 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008391 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008392 /* Action frame registered in one adapter which will
8393 * applicable to all interfaces
8394 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008395 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008397
8398 mutex_init(&pHddCtx->sap_lock);
8399
8400 pHddCtx->isLoadUnloadInProgress = FALSE;
8401
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008402#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008403#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8404 /* Initialize the wake lcok */
8405 wake_lock_init(&pHddCtx->rx_wake_lock,
8406 WAKE_LOCK_SUSPEND,
8407 "qcom_rx_wakelock");
8408#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008409 /* Initialize the wake lcok */
8410 wake_lock_init(&pHddCtx->sap_wake_lock,
8411 WAKE_LOCK_SUSPEND,
8412 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008413#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008414
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008415 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8416 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008417
8418 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8419 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308420#ifndef CONFIG_ENABLE_LINUX_REG
8421 /*updating wiphy so that regulatory user hints can be processed*/
8422 if (wiphy)
8423 {
8424 regulatory_hint(wiphy, "00");
8425 }
8426#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008427 // Initialize the restart logic
8428 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308429
Leo Chang0b0e45a2013-12-15 15:18:55 -08008430#ifdef FEATURE_WLAN_CH_AVOID
8431 /* Plug in avoid channel notification callback */
8432 sme_AddChAvoidCallback(pHddCtx->hHal,
8433 hdd_hostapd_ch_avoid_cb);
8434#endif /* FEATURE_WLAN_CH_AVOID */
8435
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008436 //Register the traffic monitor timer now
8437 if ( pHddCtx->cfg_ini->dynSplitscan)
8438 {
8439 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8440 VOS_TIMER_TYPE_SW,
8441 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8442 (void *)pHddCtx);
8443 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008444 goto success;
8445
8446err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008447#ifdef WLAN_KD_READY_NOTIFIER
8448 nl_srv_exit(pHddCtx->ptt_pid);
8449#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008450 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008451#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008452err_reg_netdev:
8453 unregister_netdevice_notifier(&hdd_netdev_notifier);
8454
8455err_free_power_on_lock:
8456 free_riva_power_on_lock("wlan");
8457
8458err_unregister_pmops:
8459 hddDevTmUnregisterNotifyCallback(pHddCtx);
8460 hddDeregisterPmOps(pHddCtx);
8461
Yue Ma0d4891e2013-08-06 17:01:45 -07008462 hdd_debugfs_exit(pHddCtx);
8463
Jeff Johnson295189b2012-06-20 16:38:30 -07008464#ifdef WLAN_BTAMP_FEATURE
8465err_bap_stop:
8466 WLANBAP_Stop(pVosContext);
8467#endif
8468
8469#ifdef WLAN_BTAMP_FEATURE
8470err_bap_close:
8471 WLANBAP_Close(pVosContext);
8472#endif
8473
Jeff Johnson295189b2012-06-20 16:38:30 -07008474err_close_adapter:
8475 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008476
8477#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308478 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008479#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008480
8481err_vosstop:
8482 vos_stop(pVosContext);
8483
Amar Singhala49cbc52013-10-08 18:37:44 -07008484err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008485 status = vos_sched_close( pVosContext );
8486 if (!VOS_IS_STATUS_SUCCESS(status)) {
8487 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8488 "%s: Failed to close VOSS Scheduler", __func__);
8489 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8490 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008491 vos_close(pVosContext );
8492
8493err_wiphy_unregister:
8494
8495#ifdef CONFIG_ENABLE_LINUX_REG
8496 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008497
Amar Singhal0a402232013-10-11 20:57:16 -07008498err_vos_nv_close:
8499
8500 vos_nv_close();
8501
Jeff Johnson295189b2012-06-20 16:38:30 -07008502err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008503#endif
8504
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008505 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008506
8507err_wdclose:
8508 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8509 vos_watchdog_close(pVosContext);
8510
Jeff Johnson295189b2012-06-20 16:38:30 -07008511err_config:
8512 kfree(pHddCtx->cfg_ini);
8513 pHddCtx->cfg_ini= NULL;
8514
8515err_free_hdd_context:
8516 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008517 wiphy_free(wiphy) ;
8518 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008519 VOS_BUG(1);
8520
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008521 if (hdd_is_ssr_required())
8522 {
8523 /* WDI timeout had happened during load, so SSR is needed here */
8524 subsystem_restart("wcnss");
8525 msleep(5000);
8526 }
8527 hdd_set_ssr_required (VOS_FALSE);
8528
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008529 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008530
8531success:
8532 EXIT();
8533 return 0;
8534}
8535
8536/**---------------------------------------------------------------------------
8537
Jeff Johnson32d95a32012-09-10 13:15:23 -07008538 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008539
Jeff Johnson32d95a32012-09-10 13:15:23 -07008540 This is the driver entry point - called in different timeline depending
8541 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008542
8543 \param - None
8544
8545 \return - 0 for success, non zero for failure
8546
8547 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008548static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008549{
8550 VOS_STATUS status;
8551 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008552 struct device *dev = NULL;
8553 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008554#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8555 int max_retries = 0;
8556#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008557
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308558#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8559 vos_wconn_trace_init();
8560#endif
8561
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 ENTER();
8563
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008564#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008565 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008566#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008567
8568 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8569 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8570
8571 //Power Up Libra WLAN card first if not already powered up
8572 status = vos_chipPowerUp(NULL,NULL,NULL);
8573 if (!VOS_IS_STATUS_SUCCESS(status))
8574 {
8575 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8576 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308577#ifdef WLAN_OPEN_SOURCE
8578 wake_lock_destroy(&wlan_wake_lock);
8579#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008580 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008581 }
8582
Jeff Johnson295189b2012-06-20 16:38:30 -07008583#ifdef ANI_BUS_TYPE_PCI
8584
8585 dev = wcnss_wlan_get_device();
8586
8587#endif // ANI_BUS_TYPE_PCI
8588
8589#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008590
8591#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8592 /* wait until WCNSS driver downloads NV */
8593 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8594 msleep(1000);
8595 }
8596 if (max_retries >= 5) {
8597 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308598#ifdef WLAN_OPEN_SOURCE
8599 wake_lock_destroy(&wlan_wake_lock);
8600#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008601 return -ENODEV;
8602 }
8603#endif
8604
Jeff Johnson295189b2012-06-20 16:38:30 -07008605 dev = wcnss_wlan_get_device();
8606#endif // ANI_BUS_TYPE_PLATFORM
8607
8608
8609 do {
8610 if (NULL == dev) {
8611 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8612 ret_status = -1;
8613 break;
8614 }
8615
Jeff Johnson295189b2012-06-20 16:38:30 -07008616#ifdef TIMER_MANAGER
8617 vos_timer_manager_init();
8618#endif
8619
8620 /* Preopen VOSS so that it is ready to start at least SAL */
8621 status = vos_preOpen(&pVosContext);
8622
8623 if (!VOS_IS_STATUS_SUCCESS(status))
8624 {
8625 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8626 ret_status = -1;
8627 break;
8628 }
8629
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008630#ifndef MODULE
8631 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8632 */
8633 hdd_set_conparam((v_UINT_t)con_mode);
8634#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008635
8636 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008637 if (hdd_wlan_startup(dev))
8638 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008639 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008640 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008641 vos_preClose( &pVosContext );
8642 ret_status = -1;
8643 break;
8644 }
8645
8646 /* Cancel the vote for XO Core ON
8647 * This is done here for safety purposes in case we re-initialize without turning
8648 * it OFF in any error scenario.
8649 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008650 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008651 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008652 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8654 {
8655 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008656 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008657 }
8658 } while (0);
8659
8660 if (0 != ret_status)
8661 {
8662 //Assert Deep sleep signal now to put Libra HW in lowest power state
8663 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8664 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8665
8666 //Vote off any PMIC voltage supplies
8667 vos_chipPowerDown(NULL, NULL, NULL);
8668#ifdef TIMER_MANAGER
8669 vos_timer_exit();
8670#endif
8671#ifdef MEMORY_DEBUG
8672 vos_mem_exit();
8673#endif
8674
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008675#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008676 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008678 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8679 }
8680 else
8681 {
8682 //Send WLAN UP indication to Nlink Service
8683 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8684
8685 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008686 }
8687
8688 EXIT();
8689
8690 return ret_status;
8691}
8692
Jeff Johnson32d95a32012-09-10 13:15:23 -07008693/**---------------------------------------------------------------------------
8694
8695 \brief hdd_module_init() - Init Function
8696
8697 This is the driver entry point (invoked when module is loaded using insmod)
8698
8699 \param - None
8700
8701 \return - 0 for success, non zero for failure
8702
8703 --------------------------------------------------------------------------*/
8704#ifdef MODULE
8705static int __init hdd_module_init ( void)
8706{
8707 return hdd_driver_init();
8708}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008709#else /* #ifdef MODULE */
8710static int __init hdd_module_init ( void)
8711{
8712 /* Driver initialization is delayed to fwpath_changed_handler */
8713 return 0;
8714}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008715#endif /* #ifdef MODULE */
8716
Jeff Johnson295189b2012-06-20 16:38:30 -07008717
8718/**---------------------------------------------------------------------------
8719
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008720 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008721
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008722 This is the driver exit point (invoked when module is unloaded using rmmod
8723 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008724
8725 \param - None
8726
8727 \return - None
8728
8729 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008730static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008731{
8732 hdd_context_t *pHddCtx = NULL;
8733 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008734 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008735
8736 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8737
8738 //Get the global vos context
8739 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8740
8741 if(!pVosContext)
8742 {
8743 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8744 goto done;
8745 }
8746
8747 //Get the HDD context.
8748 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8749
8750 if(!pHddCtx)
8751 {
8752 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8753 }
8754 else
8755 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008756 while(isWDresetInProgress()) {
8757 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8758 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008759 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008760
8761 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8763 "%s:SSR never completed, fatal error", __func__);
8764 VOS_BUG(0);
8765 }
8766 }
8767
Jeff Johnson295189b2012-06-20 16:38:30 -07008768
8769 pHddCtx->isLoadUnloadInProgress = TRUE;
8770 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8771
8772 //Do all the cleanup before deregistering the driver
8773 hdd_wlan_exit(pHddCtx);
8774 }
8775
Jeff Johnson295189b2012-06-20 16:38:30 -07008776 vos_preClose( &pVosContext );
8777
8778#ifdef TIMER_MANAGER
8779 vos_timer_exit();
8780#endif
8781#ifdef MEMORY_DEBUG
8782 vos_mem_exit();
8783#endif
8784
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308785#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8786 vos_wconn_trace_exit();
8787#endif
8788
Jeff Johnson295189b2012-06-20 16:38:30 -07008789done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008790#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008792#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8794}
8795
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008796/**---------------------------------------------------------------------------
8797
8798 \brief hdd_module_exit() - Exit function
8799
8800 This is the driver exit point (invoked when module is unloaded using rmmod)
8801
8802 \param - None
8803
8804 \return - None
8805
8806 --------------------------------------------------------------------------*/
8807static void __exit hdd_module_exit(void)
8808{
8809 hdd_driver_exit();
8810}
8811
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008812#ifdef MODULE
8813static int fwpath_changed_handler(const char *kmessage,
8814 struct kernel_param *kp)
8815{
Jeff Johnson76052702013-04-16 13:55:05 -07008816 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008817}
8818
8819static int con_mode_handler(const char *kmessage,
8820 struct kernel_param *kp)
8821{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008822 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008823}
8824#else /* #ifdef MODULE */
8825/**---------------------------------------------------------------------------
8826
Jeff Johnson76052702013-04-16 13:55:05 -07008827 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008828
Jeff Johnson76052702013-04-16 13:55:05 -07008829 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008830 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008831 - invoked when module parameter fwpath is modified from userspace to signal
8832 initializing the WLAN driver or when con_mode is modified from userspace
8833 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008834
8835 \return - 0 for success, non zero for failure
8836
8837 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008838static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008839{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008840 int ret_status;
8841
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008842 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008843 ret_status = hdd_driver_init();
8844 wlan_hdd_inited = ret_status ? 0 : 1;
8845 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008846 }
8847
8848 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008849
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008850 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008851
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008852 ret_status = hdd_driver_init();
8853 wlan_hdd_inited = ret_status ? 0 : 1;
8854 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008855}
8856
Jeff Johnson295189b2012-06-20 16:38:30 -07008857/**---------------------------------------------------------------------------
8858
Jeff Johnson76052702013-04-16 13:55:05 -07008859 \brief fwpath_changed_handler() - Handler Function
8860
8861 Handle changes to the fwpath parameter
8862
8863 \return - 0 for success, non zero for failure
8864
8865 --------------------------------------------------------------------------*/
8866static int fwpath_changed_handler(const char *kmessage,
8867 struct kernel_param *kp)
8868{
8869 int ret;
8870
8871 ret = param_set_copystring(kmessage, kp);
8872 if (0 == ret)
8873 ret = kickstart_driver();
8874 return ret;
8875}
8876
8877/**---------------------------------------------------------------------------
8878
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008879 \brief con_mode_handler() -
8880
8881 Handler function for module param con_mode when it is changed by userspace
8882 Dynamically linked - do nothing
8883 Statically linked - exit and init driver, as in rmmod and insmod
8884
Jeff Johnson76052702013-04-16 13:55:05 -07008885 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008886
Jeff Johnson76052702013-04-16 13:55:05 -07008887 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008888
8889 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008890static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008891{
Jeff Johnson76052702013-04-16 13:55:05 -07008892 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008893
Jeff Johnson76052702013-04-16 13:55:05 -07008894 ret = param_set_int(kmessage, kp);
8895 if (0 == ret)
8896 ret = kickstart_driver();
8897 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008898}
8899#endif /* #ifdef MODULE */
8900
8901/**---------------------------------------------------------------------------
8902
Jeff Johnson295189b2012-06-20 16:38:30 -07008903 \brief hdd_get_conparam() -
8904
8905 This is the driver exit point (invoked when module is unloaded using rmmod)
8906
8907 \param - None
8908
8909 \return - tVOS_CON_MODE
8910
8911 --------------------------------------------------------------------------*/
8912tVOS_CON_MODE hdd_get_conparam ( void )
8913{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008914#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008915 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008916#else
8917 return (tVOS_CON_MODE)curr_con_mode;
8918#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008919}
8920void hdd_set_conparam ( v_UINT_t newParam )
8921{
8922 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008923#ifndef MODULE
8924 curr_con_mode = con_mode;
8925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008926}
8927/**---------------------------------------------------------------------------
8928
8929 \brief hdd_softap_sta_deauth() - function
8930
8931 This to take counter measure to handle deauth req from HDD
8932
8933 \param - pAdapter - Pointer to the HDD
8934
8935 \param - enable - boolean value
8936
8937 \return - None
8938
8939 --------------------------------------------------------------------------*/
8940
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008941VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008942{
Jeff Johnson295189b2012-06-20 16:38:30 -07008943 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008944 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008945
8946 ENTER();
8947
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008948 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8949 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008950
8951 //Ignore request to deauth bcmc station
8952 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008953 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008954
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008955 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008956
8957 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008958 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008959}
8960
8961/**---------------------------------------------------------------------------
8962
8963 \brief hdd_softap_sta_disassoc() - function
8964
8965 This to take counter measure to handle deauth req from HDD
8966
8967 \param - pAdapter - Pointer to the HDD
8968
8969 \param - enable - boolean value
8970
8971 \return - None
8972
8973 --------------------------------------------------------------------------*/
8974
8975void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8976{
8977 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8978
8979 ENTER();
8980
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308981 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008982
8983 //Ignore request to disassoc bcmc station
8984 if( pDestMacAddress[0] & 0x1 )
8985 return;
8986
8987 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8988}
8989
8990void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8991{
8992 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8993
8994 ENTER();
8995
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308996 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008997
8998 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8999}
9000
Jeff Johnson295189b2012-06-20 16:38:30 -07009001/**---------------------------------------------------------------------------
9002 *
9003 * \brief hdd_get__concurrency_mode() -
9004 *
9005 *
9006 * \param - None
9007 *
9008 * \return - CONCURRENCY MODE
9009 *
9010 * --------------------------------------------------------------------------*/
9011tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9012{
9013 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9014 hdd_context_t *pHddCtx;
9015
9016 if (NULL != pVosContext)
9017 {
9018 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9019 if (NULL != pHddCtx)
9020 {
9021 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9022 }
9023 }
9024
9025 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009026 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009027 return VOS_STA;
9028}
9029
9030/* Decide whether to allow/not the apps power collapse.
9031 * Allow apps power collapse if we are in connected state.
9032 * if not, allow only if we are in IMPS */
9033v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9034{
9035 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009036 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009037 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9039 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9040 hdd_adapter_t *pAdapter = NULL;
9041 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009042 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009043
Jeff Johnson295189b2012-06-20 16:38:30 -07009044 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9045 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009046
Yathish9f22e662012-12-10 14:21:35 -08009047 concurrent_state = hdd_get_concurrency_mode();
9048
9049#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9050 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9051 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9052 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9053 return TRUE;
9054#endif
9055
Jeff Johnson295189b2012-06-20 16:38:30 -07009056 /*loop through all adapters. TBD fix for Concurrency */
9057 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9058 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9059 {
9060 pAdapter = pAdapterNode->pAdapter;
9061 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9062 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9063 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009064 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009065 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009066 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009067 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9068 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009069 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009070 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009071 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9072 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009073 return FALSE;
9074 }
9075 }
9076 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9077 pAdapterNode = pNext;
9078 }
9079 return TRUE;
9080}
9081
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009082/* Decides whether to send suspend notification to Riva
9083 * if any adapter is in BMPS; then it is required */
9084v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9085{
9086 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9087 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9088
9089 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9090 {
9091 return TRUE;
9092 }
9093 return FALSE;
9094}
9095
Jeff Johnson295189b2012-06-20 16:38:30 -07009096void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9097{
9098 switch(mode)
9099 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009100 case VOS_STA_MODE:
9101 case VOS_P2P_CLIENT_MODE:
9102 case VOS_P2P_GO_MODE:
9103 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009104 pHddCtx->concurrency_mode |= (1 << mode);
9105 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009106 break;
9107 default:
9108 break;
9109
9110 }
9111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9112 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9113}
9114
9115
9116void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9117{
9118 switch(mode)
9119 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009120 case VOS_STA_MODE:
9121 case VOS_P2P_CLIENT_MODE:
9122 case VOS_P2P_GO_MODE:
9123 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009124 pHddCtx->no_of_sessions[mode]--;
9125 if (!(pHddCtx->no_of_sessions[mode]))
9126 pHddCtx->concurrency_mode &= (~(1 << mode));
9127 break;
9128 default:
9129 break;
9130 }
9131 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9132 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9133}
9134
Jeff Johnsone7245742012-09-05 17:12:55 -07009135/**---------------------------------------------------------------------------
9136 *
9137 * \brief wlan_hdd_restart_init
9138 *
9139 * This function initalizes restart timer/flag. An internal function.
9140 *
9141 * \param - pHddCtx
9142 *
9143 * \return - None
9144 *
9145 * --------------------------------------------------------------------------*/
9146
9147static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9148{
9149 /* Initialize */
9150 pHddCtx->hdd_restart_retries = 0;
9151 atomic_set(&pHddCtx->isRestartInProgress, 0);
9152 vos_timer_init(&pHddCtx->hdd_restart_timer,
9153 VOS_TIMER_TYPE_SW,
9154 wlan_hdd_restart_timer_cb,
9155 pHddCtx);
9156}
9157/**---------------------------------------------------------------------------
9158 *
9159 * \brief wlan_hdd_restart_deinit
9160 *
9161 * This function cleans up the resources used. An internal function.
9162 *
9163 * \param - pHddCtx
9164 *
9165 * \return - None
9166 *
9167 * --------------------------------------------------------------------------*/
9168
9169static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9170{
9171
9172 VOS_STATUS vos_status;
9173 /* Block any further calls */
9174 atomic_set(&pHddCtx->isRestartInProgress, 1);
9175 /* Cleanup */
9176 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9177 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009178 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009179 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9180 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009181 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009182
9183}
9184
9185/**---------------------------------------------------------------------------
9186 *
9187 * \brief wlan_hdd_framework_restart
9188 *
9189 * This function uses a cfg80211 API to start a framework initiated WLAN
9190 * driver module unload/load.
9191 *
9192 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9193 *
9194 *
9195 * \param - pHddCtx
9196 *
9197 * \return - VOS_STATUS_SUCCESS: Success
9198 * VOS_STATUS_E_EMPTY: Adapter is Empty
9199 * VOS_STATUS_E_NOMEM: No memory
9200
9201 * --------------------------------------------------------------------------*/
9202
9203static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9204{
9205 VOS_STATUS status = VOS_STATUS_SUCCESS;
9206 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009207 int len = (sizeof (struct ieee80211_mgmt));
9208 struct ieee80211_mgmt *mgmt = NULL;
9209
9210 /* Prepare the DEAUTH managment frame with reason code */
9211 mgmt = kzalloc(len, GFP_KERNEL);
9212 if(mgmt == NULL)
9213 {
9214 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9215 "%s: memory allocation failed (%d bytes)", __func__, len);
9216 return VOS_STATUS_E_NOMEM;
9217 }
9218 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009219
9220 /* Iterate over all adapters/devices */
9221 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9222 do
9223 {
9224 if( (status == VOS_STATUS_SUCCESS) &&
9225 pAdapterNode &&
9226 pAdapterNode->pAdapter)
9227 {
9228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9229 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9230 pAdapterNode->pAdapter->dev->name,
9231 pAdapterNode->pAdapter->device_mode,
9232 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009233 /*
9234 * CFG80211 event to restart the driver
9235 *
9236 * 'cfg80211_send_unprot_deauth' sends a
9237 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9238 * of SME(Linux Kernel) state machine.
9239 *
9240 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9241 * the driver.
9242 *
9243 */
9244
9245 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009246 }
9247 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9248 pAdapterNode = pNext;
9249 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9250
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009251
9252 /* Free the allocated management frame */
9253 kfree(mgmt);
9254
Jeff Johnsone7245742012-09-05 17:12:55 -07009255 /* Retry until we unload or reach max count */
9256 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9257 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9258
9259 return status;
9260
9261}
9262/**---------------------------------------------------------------------------
9263 *
9264 * \brief wlan_hdd_restart_timer_cb
9265 *
9266 * Restart timer callback. An internal function.
9267 *
9268 * \param - User data:
9269 *
9270 * \return - None
9271 *
9272 * --------------------------------------------------------------------------*/
9273
9274void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9275{
9276 hdd_context_t *pHddCtx = usrDataForCallback;
9277 wlan_hdd_framework_restart(pHddCtx);
9278 return;
9279
9280}
9281
9282
9283/**---------------------------------------------------------------------------
9284 *
9285 * \brief wlan_hdd_restart_driver
9286 *
9287 * This function sends an event to supplicant to restart the WLAN driver.
9288 *
9289 * This function is called from vos_wlanRestart.
9290 *
9291 * \param - pHddCtx
9292 *
9293 * \return - VOS_STATUS_SUCCESS: Success
9294 * VOS_STATUS_E_EMPTY: Adapter is Empty
9295 * VOS_STATUS_E_ALREADY: Request already in progress
9296
9297 * --------------------------------------------------------------------------*/
9298VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9299{
9300 VOS_STATUS status = VOS_STATUS_SUCCESS;
9301
9302 /* A tight check to make sure reentrancy */
9303 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9304 {
9305 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9306 "%s: WLAN restart is already in progress", __func__);
9307
9308 return VOS_STATUS_E_ALREADY;
9309 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009310 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009311#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009312 wcnss_reset_intr();
9313#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009314
Jeff Johnsone7245742012-09-05 17:12:55 -07009315 return status;
9316}
9317
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009318/*
9319 * API to find if there is any STA or P2P-Client is connected
9320 */
9321VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9322{
9323 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9324}
Jeff Johnsone7245742012-09-05 17:12:55 -07009325
Jeff Johnson295189b2012-06-20 16:38:30 -07009326//Register the module init/exit functions
9327module_init(hdd_module_init);
9328module_exit(hdd_module_exit);
9329
9330MODULE_LICENSE("Dual BSD/GPL");
9331MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9332MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9333
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009334module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9335 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009336
Jeff Johnson76052702013-04-16 13:55:05 -07009337module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009338 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009339
9340module_param(enable_dfs_chan_scan, int,
9341 S_IRUSR | S_IRGRP | S_IROTH);
9342
9343module_param(enable_11d, int,
9344 S_IRUSR | S_IRGRP | S_IROTH);
9345
9346module_param(country_code, charp,
9347 S_IRUSR | S_IRGRP | S_IROTH);