blob: 45c0f5a40bde5be3cc97102a26f92104d50f30a5 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700112#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include <mach/subsystem_restart.h>
114#include <wlan_hdd_hostapd.h>
115#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "wlan_hdd_dev_pwr.h"
118#ifdef WLAN_BTAMP_FEATURE
119#include "bap_hdd_misc.h"
120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800123#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530124#ifdef FEATURE_WLAN_TDLS
125#include "wlan_hdd_tdls.h"
126#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700127#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700165
166/*
167 * Size of Driver command strings from upper layer
168 */
169#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
170#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
171
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700172#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
173#define TID_MIN_VALUE 0
174#define TID_MAX_VALUE 15
175static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
176 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800177static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
178 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700179#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
180
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700181/*
182 * Driver miracast parameters 0-Disabled
183 * 1-Source, 2-Sink
184 */
185#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
186#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
187
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800188#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700189static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700190#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700191/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700192static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700193
194//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700195static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
196static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
197static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
198void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800199void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700200
Jeff Johnson295189b2012-06-20 16:38:30 -0700201v_U16_t hdd_select_queue(struct net_device *dev,
202 struct sk_buff *skb);
203
204#ifdef WLAN_FEATURE_PACKET_FILTERING
205static void hdd_set_multicast_list(struct net_device *dev);
206#endif
207
208void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700209int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700210
211extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700212
Srinivas Girigowdade697412013-02-14 16:31:48 -0800213#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
214void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
215static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700216static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
217 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
218 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700219static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
220 tANI_U8 *pTargetApBssid,
221 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800222#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700223#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
224VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
225#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
226
Jeff Johnson295189b2012-06-20 16:38:30 -0700227static int hdd_netdev_notifier_call(struct notifier_block * nb,
228 unsigned long state,
229 void *ndev)
230{
231 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700232 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700233 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700234#ifdef WLAN_BTAMP_FEATURE
235 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700236#endif
237
238 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700239 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700240 (strncmp(dev->name, "p2p", 3)))
241 return NOTIFY_DONE;
242
243 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 return NOTIFY_DONE;
245
Jeff Johnson295189b2012-06-20 16:38:30 -0700246 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700247 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700248
Jeff Johnson27cee452013-03-27 11:10:24 -0700249 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 VOS_ASSERT(0);
253 return NOTIFY_DONE;
254 }
255
Jeff Johnson27cee452013-03-27 11:10:24 -0700256 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
257 if (NULL == pHddCtx)
258 {
259 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
260 VOS_ASSERT(0);
261 return NOTIFY_DONE;
262 }
263
264 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
265 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266
267 switch (state) {
268 case NETDEV_REGISTER:
269 break;
270
271 case NETDEV_UNREGISTER:
272 break;
273
274 case NETDEV_UP:
275 break;
276
277 case NETDEV_DOWN:
278 break;
279
280 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700281 if(TRUE == pAdapter->isLinkUpSvcNeeded)
282 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700283 break;
284
285 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700286 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 {
288 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800289 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530290 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800292 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
294 if(!result)
295 {
296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800297 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700298 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700299 }
300 }
301 else
302 {
303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700304 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 }
306#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 status = WLANBAP_StopAmp();
309 if(VOS_STATUS_SUCCESS != status )
310 {
311 pHddCtx->isAmpAllowed = VOS_TRUE;
312 hddLog(VOS_TRACE_LEVEL_FATAL,
313 "%s: Failed to stop AMP", __func__);
314 }
315 else
316 {
317 //a state m/c implementation in PAL is TBD to avoid this delay
318 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700319 if ( pHddCtx->isAmpAllowed )
320 {
321 WLANBAP_DeregisterFromHCI();
322 pHddCtx->isAmpAllowed = VOS_FALSE;
323 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 }
325#endif //WLAN_BTAMP_FEATURE
326 break;
327
328 default:
329 break;
330 }
331
332 return NOTIFY_DONE;
333}
334
335struct notifier_block hdd_netdev_notifier = {
336 .notifier_call = hdd_netdev_notifier_call,
337};
338
339/*---------------------------------------------------------------------------
340 * Function definitions
341 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700342void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
343void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700344//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700345static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700346#ifndef MODULE
347/* current con_mode - used only for statically linked driver
348 * con_mode is changed by userspace to indicate a mode change which will
349 * result in calling the module exit and init functions. The module
350 * exit function will clean up based on the value of con_mode prior to it
351 * being changed by userspace. So curr_con_mode records the current con_mode
352 * for exit when con_mode becomes the next mode for init
353 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700354static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700355#endif
356
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800357/**---------------------------------------------------------------------------
358
359 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
360
361 Called immediately after the cfg.ini is read in order to configure
362 the desired trace levels.
363
364 \param - moduleId - module whose trace level is being configured
365 \param - bitmask - bitmask of log levels to be enabled
366
367 \return - void
368
369 --------------------------------------------------------------------------*/
370static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
371{
372 wpt_tracelevel level;
373
374 /* if the bitmask is the default value, then a bitmask was not
375 specified in cfg.ini, so leave the logging level alone (it
376 will remain at the "compiled in" default value) */
377 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
378 {
379 return;
380 }
381
382 /* a mask was specified. start by disabling all logging */
383 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
384
385 /* now cycle through the bitmask until all "set" bits are serviced */
386 level = VOS_TRACE_LEVEL_FATAL;
387 while (0 != bitmask)
388 {
389 if (bitmask & 1)
390 {
391 vos_trace_setValue(moduleId, level, 1);
392 }
393 level++;
394 bitmask >>= 1;
395 }
396}
397
398
Jeff Johnson295189b2012-06-20 16:38:30 -0700399/**---------------------------------------------------------------------------
400
401 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
402
403 Called immediately after the cfg.ini is read in order to configure
404 the desired trace levels in the WDI.
405
406 \param - moduleId - module whose trace level is being configured
407 \param - bitmask - bitmask of log levels to be enabled
408
409 \return - void
410
411 --------------------------------------------------------------------------*/
412static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
413{
414 wpt_tracelevel level;
415
416 /* if the bitmask is the default value, then a bitmask was not
417 specified in cfg.ini, so leave the logging level alone (it
418 will remain at the "compiled in" default value) */
419 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
420 {
421 return;
422 }
423
424 /* a mask was specified. start by disabling all logging */
425 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
426
427 /* now cycle through the bitmask until all "set" bits are serviced */
428 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
429 while (0 != bitmask)
430 {
431 if (bitmask & 1)
432 {
433 wpalTraceSetLevel(moduleId, level, 1);
434 }
435 level++;
436 bitmask >>= 1;
437 }
438}
Jeff Johnson295189b2012-06-20 16:38:30 -0700439
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530440/*
441 * FUNCTION: wlan_hdd_validate_context
442 * This function is used to check the HDD context
443 */
444int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
445{
446 ENTER();
447
448 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
449 {
450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
451 "%s: HDD context is Null", __func__);
452 return -ENODEV;
453 }
454
455 if (pHddCtx->isLogpInProgress)
456 {
457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
458 "%s: LOGP in Progress. Ignore!!!", __func__);
459 return -EAGAIN;
460 }
461
462 if (pHddCtx->isLoadUnloadInProgress)
463 {
464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
465 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
466 return -EAGAIN;
467 }
468 return 0;
469}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700470#ifdef CONFIG_ENABLE_LINUX_REG
471void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
472{
473 hdd_adapter_t *pAdapter = NULL;
474 hdd_station_ctx_t *pHddStaCtx = NULL;
475 eCsrPhyMode phyMode;
476 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530477
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700478 if (NULL == pHddCtx)
479 {
480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
481 "HDD Context is null !!");
482 return ;
483 }
484
485 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
486 if (NULL == pAdapter)
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
489 "pAdapter is null !!");
490 return ;
491 }
492
493 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
494 if (NULL == pHddStaCtx)
495 {
496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
497 "pHddStaCtx is null !!");
498 return ;
499 }
500
501 cfg_param = pHddCtx->cfg_ini;
502 if (NULL == cfg_param)
503 {
504 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
505 "cfg_params not available !!");
506 return ;
507 }
508
509 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
510
511 if (!pHddCtx->isVHT80Allowed)
512 {
513 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
514 (eCSR_DOT11_MODE_11ac == phyMode) ||
515 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
518 "Setting phymode to 11n!!");
519 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
520 }
521 }
522 else
523 {
524 /*New country Supports 11ac as well resetting value back from .ini*/
525 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
526 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
527 return ;
528 }
529
530 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
531 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
532 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
533 {
534 VOS_STATUS vosStatus;
535
536 // need to issue a disconnect to CSR.
537 INIT_COMPLETION(pAdapter->disconnect_comp_var);
538 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
539 pAdapter->sessionId,
540 eCSR_DISCONNECT_REASON_UNSPECIFIED );
541
542 if (VOS_STATUS_SUCCESS == vosStatus)
543 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
544 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
545
546 }
547}
548#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530549void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
550{
551 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
552 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
553 hdd_config_t *cfg_param;
554 eCsrPhyMode phyMode;
555
556 if (NULL == pHddCtx)
557 {
558 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
559 "HDD Context is null !!");
560 return ;
561 }
562
563 cfg_param = pHddCtx->cfg_ini;
564
565 if (NULL == cfg_param)
566 {
567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
568 "cfg_params not available !!");
569 return ;
570 }
571
572 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
573
574 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
575 {
576 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
577 (eCSR_DOT11_MODE_11ac == phyMode) ||
578 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
579 {
580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
581 "Setting phymode to 11n!!");
582 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
583 }
584 }
585 else
586 {
587 /*New country Supports 11ac as well resetting value back from .ini*/
588 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
589 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
590 return ;
591 }
592
593 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
594 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
595 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
596 {
597 VOS_STATUS vosStatus;
598
599 // need to issue a disconnect to CSR.
600 INIT_COMPLETION(pAdapter->disconnect_comp_var);
601 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
602 pAdapter->sessionId,
603 eCSR_DISCONNECT_REASON_UNSPECIFIED );
604
605 if (VOS_STATUS_SUCCESS == vosStatus)
606 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
607 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
608
609 }
610}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700611#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530612
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700613void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
614{
615 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
616 hdd_config_t *cfg_param;
617
618 if (NULL == pHddCtx)
619 {
620 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
621 "HDD Context is null !!");
622 return ;
623 }
624
625 cfg_param = pHddCtx->cfg_ini;
626
627 if (NULL == cfg_param)
628 {
629 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
630 "cfg_params not available !!");
631 return ;
632 }
633
634 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
635 {
636 /*New country doesn't support DFS */
637 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
638 }
639 else
640 {
641 /*New country Supports DFS as well resetting value back from .ini*/
642 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
643 }
644
645}
646
Rajeev79dbe4c2013-10-05 11:03:42 +0530647#ifdef FEATURE_WLAN_BATCH_SCAN
648
649/**---------------------------------------------------------------------------
650
651 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
652 input string
653
654 This function extracts assigned integer from string in below format:
655 "STRING=10" : extracts integer 10 from this string
656
657 \param - pInPtr Pointer to input string
658 \param - base Base for string to int conversion(10 for decimal 16 for hex)
659 \param - pOutPtr Pointer to variable in which extracted integer needs to be
660 assigned
661 \param - pLastArg to tell whether it is last arguement in input string or
662 not
663
664 \return - NULL for failure cases
665 pointer to next arguement in input string for success cases
666 --------------------------------------------------------------------------*/
667static tANI_U8 *
668hdd_extract_assigned_int_from_str
669(
670 tANI_U8 *pInPtr,
671 tANI_U8 base,
672 tANI_U32 *pOutPtr,
673 tANI_U8 *pLastArg
674)
675{
676 int tempInt;
677 int v = 0;
678 char buf[32];
679 int val = 0;
680 *pLastArg = FALSE;
681
682 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
683 if (NULL == pInPtr)
684 {
685 return NULL;
686 }
687
688 pInPtr++;
689
690 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
691
692 val = sscanf(pInPtr, "%32s ", buf);
693 if (val < 0 && val > strlen(pInPtr))
694 {
695 return NULL;
696 }
697 pInPtr += val;
698 v = kstrtos32(buf, base, &tempInt);
699 if (v < 0)
700 {
701 return NULL;
702 }
703 *pOutPtr = tempInt;
704
705 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
706 if (NULL == pInPtr)
707 {
708 *pLastArg = TRUE;
709 return NULL;
710 }
711 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
712
713 return pInPtr;
714}
715
716/**---------------------------------------------------------------------------
717
718 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
719 input string
720
721 This function extracts assigned character from string in below format:
722 "STRING=A" : extracts char 'A' from this string
723
724 \param - pInPtr Pointer to input string
725 \param - pOutPtr Pointer to variable in which extracted char needs to be
726 assigned
727 \param - pLastArg to tell whether it is last arguement in input string or
728 not
729
730 \return - NULL for failure cases
731 pointer to next arguement in input string for success cases
732 --------------------------------------------------------------------------*/
733static tANI_U8 *
734hdd_extract_assigned_char_from_str
735(
736 tANI_U8 *pInPtr,
737 tANI_U8 *pOutPtr,
738 tANI_U8 *pLastArg
739)
740{
741 *pLastArg = FALSE;
742
743 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
744 if (NULL == pInPtr)
745 {
746 return NULL;
747 }
748
749 pInPtr++;
750
751 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
752
753 *pOutPtr = *pInPtr;
754
755 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
756 if (NULL == pInPtr)
757 {
758 *pLastArg = TRUE;
759 return NULL;
760 }
761 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
762
763 return pInPtr;
764}
765
766
767/**---------------------------------------------------------------------------
768
769 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
770
771 This function parses set batch scan command in below format:
772 WLS_BATCHING_SET <space> followed by below arguements
773 "SCANFREQ=XX" : Optional defaults to 30 sec
774 "MSCAN=XX" : Required number of scans to attempt to batch
775 "BESTN=XX" : Best Network (RSSI) defaults to 16
776 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
777 A. implies only 5 GHz , B. implies only 2.4GHz
778 "RTT=X" : optional defaults to 0
779 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
780 error
781
782 For example input commands:
783 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
784 translated into set batch scan with following parameters:
785 a) Frequence 60 seconds
786 b) Batch 10 scans together
787 c) Best RSSI to be 20
788 d) 5GHz band only
789 e) RTT is equal to 0
790
791 \param - pValue Pointer to input channel list
792 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
793
794 \return - 0 for success non-zero for failure
795
796 --------------------------------------------------------------------------*/
797static int
798hdd_parse_set_batchscan_command
799(
800 tANI_U8 *pValue,
801 tSirSetBatchScanReq *pHddSetBatchScanReq
802)
803{
804 tANI_U8 *inPtr = pValue;
805 tANI_U8 val = 0;
806 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800807 tANI_U32 nScanFreq;
808 tANI_U32 nMscan;
809 tANI_U32 nBestN;
810 tANI_U8 ucRfBand;
811 tANI_U32 nRtt;
Rajeev79dbe4c2013-10-05 11:03:42 +0530812
813 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800814 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
815 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
816 nRtt = 0;
817 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530818
819 /*go to space after WLS_BATCHING_SET command*/
820 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
821 /*no argument after the command*/
822 if (NULL == inPtr)
823 {
824 return -EINVAL;
825 }
826
827 /*no space after the command*/
828 else if (SPACE_ASCII_VALUE != *inPtr)
829 {
830 return -EINVAL;
831 }
832
833 /*removing empty spaces*/
834 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
835
836 /*no argument followed by spaces*/
837 if ('\0' == *inPtr)
838 {
839 return -EINVAL;
840 }
841
842 /*check and parse SCANFREQ*/
843 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
844 {
845 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800846 &nScanFreq, &lastArg);
847
848 if (0 == nScanFreq)
849 {
850 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
851 }
852
Rajeev79dbe4c2013-10-05 11:03:42 +0530853 if ( (NULL == inPtr) || (TRUE == lastArg))
854 {
855 return -EINVAL;
856 }
857 }
858
859 /*check and parse MSCAN*/
860 if ((strncmp(inPtr, "MSCAN", 5) == 0))
861 {
862 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800863 &nMscan, &lastArg);
864
865 if (0 == nMscan)
866 {
867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
868 "invalid MSCAN=%d", nMscan);
869 return -EINVAL;
870 }
871
Rajeev79dbe4c2013-10-05 11:03:42 +0530872 if (TRUE == lastArg)
873 {
874 goto done;
875 }
876 else if (NULL == inPtr)
877 {
878 return -EINVAL;
879 }
880 }
881 else
882 {
883 return -EINVAL;
884 }
885
886 /*check and parse BESTN*/
887 if ((strncmp(inPtr, "BESTN", 5) == 0))
888 {
889 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800890 &nBestN, &lastArg);
891
892 if (0 == nBestN)
893 {
894 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
895 }
896
Rajeev79dbe4c2013-10-05 11:03:42 +0530897 if (TRUE == lastArg)
898 {
899 goto done;
900 }
901 else if (NULL == inPtr)
902 {
903 return -EINVAL;
904 }
905 }
906
907 /*check and parse CHANNEL*/
908 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
909 {
910 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
911 if (TRUE == lastArg)
912 {
913 goto done;
914 }
915 else if (NULL == inPtr)
916 {
917 return -EINVAL;
918 }
919 if (('A' == val) || ('a' == val))
920 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800921 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530922 }
923 else if (('B' == val) || ('b' == val))
924 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800925 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530926 }
927 else
928 {
929 return -EINVAL;
930 }
931 }
932
933 /*check and parse RTT*/
934 if ((strncmp(inPtr, "RTT", 3) == 0))
935 {
936 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800937 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530938 if (TRUE == lastArg)
939 {
940 goto done;
941 }
942 if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946 }
947
948
949done:
950
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800951 pHddSetBatchScanReq->scanFrequency = nScanFreq;
952 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
953 pHddSetBatchScanReq->bestNetwork = nBestN;
954 pHddSetBatchScanReq->rfBand = ucRfBand;
955 pHddSetBatchScanReq->rtt = nRtt;
956
Rajeev79dbe4c2013-10-05 11:03:42 +0530957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
958 "Received WLS_BATCHING_SET with SCANFREQ=%d "
959 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
960 pHddSetBatchScanReq->scanFrequency,
961 pHddSetBatchScanReq->numberOfScansToBatch,
962 pHddSetBatchScanReq->bestNetwork,
963 pHddSetBatchScanReq->rfBand,
964 pHddSetBatchScanReq->rtt);
965
966 return 0;
967}/*End of hdd_parse_set_batchscan_command*/
968
969/**---------------------------------------------------------------------------
970
971 \brief hdd_set_batch_scan_req_callback () - This function is called after
972 receiving set batch scan response from FW and it saves set batch scan
973 response data FW to HDD context and sets the completion event on
974 which hdd_ioctl is waiting
975
976 \param - callbackContext Pointer to HDD adapter
977 \param - pRsp Pointer to set batch scan response data received from FW
978
979 \return - nothing
980
981 --------------------------------------------------------------------------*/
982static void hdd_set_batch_scan_req_callback
983(
984 void *callbackContext,
985 tSirSetBatchScanRsp *pRsp
986)
987{
988 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
989 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
990
991 /*sanity check*/
992 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
993 {
994 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
995 "%s: Invalid pAdapter magic", __func__);
996 VOS_ASSERT(0);
997 return;
998 }
999 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1000
1001 /*save set batch scan response*/
1002 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1003
1004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1005 "Received set batch scan rsp from FW with nScansToBatch=%d",
1006 pHddSetBatchScanRsp->nScansToBatch);
1007
1008 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1009 complete(&pAdapter->hdd_set_batch_scan_req_var);
1010
1011 return;
1012}/*End of hdd_set_batch_scan_req_callback*/
1013
1014
1015/**---------------------------------------------------------------------------
1016
1017 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1018 info in hdd batch scan response queue
1019
1020 \param - pAdapter Pointer to hdd adapter
1021 \param - pAPMetaInfo Pointer to access point meta info
1022 \param - scanId scan ID of batch scan response
1023 \param - isLastAp tells whether AP is last AP in batch scan response or not
1024
1025 \return - nothing
1026
1027 --------------------------------------------------------------------------*/
1028static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1029 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1030{
1031 tHddBatchScanRsp *pHead;
1032 tHddBatchScanRsp *pNode;
1033 tHddBatchScanRsp *pPrev;
1034 tHddBatchScanRsp *pTemp;
1035 tANI_U8 ssidLen;
1036
1037 /*head of hdd batch scan response queue*/
1038 pHead = pAdapter->pBatchScanRsp;
1039
1040 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1041 if (NULL == pNode)
1042 {
1043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1044 "%s: Could not allocate memory", __func__);
1045 VOS_ASSERT(0);
1046 return;
1047 }
1048
1049 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1050 sizeof(pNode->ApInfo.bssid));
1051 ssidLen = strlen(pApMetaInfo->ssid);
1052 if (SIR_MAX_SSID_SIZE < ssidLen)
1053 {
1054 /*invalid scan result*/
1055 vos_mem_free(pNode);
1056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1057 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1058 return;
1059 }
1060 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1061 /*null terminate ssid*/
1062 pNode->ApInfo.ssid[ssidLen] = '\0';
1063 pNode->ApInfo.ch = pApMetaInfo->ch;
1064 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1065 pNode->ApInfo.age = pApMetaInfo->timestamp;
1066 pNode->ApInfo.batchId = scanId;
1067 pNode->ApInfo.isLastAp = isLastAp;
1068
1069 pNode->pNext = NULL;
1070 if (NULL == pHead)
1071 {
1072 pAdapter->pBatchScanRsp = pNode;
1073 }
1074 else
1075 {
1076 pTemp = pHead;
1077 while (NULL != pTemp)
1078 {
1079 pPrev = pTemp;
1080 pTemp = pTemp->pNext;
1081 }
1082 pPrev->pNext = pNode;
1083 }
1084
1085 return;
1086}/*End of hdd_populate_batch_scan_rsp_queue*/
1087
1088/**---------------------------------------------------------------------------
1089
1090 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1091 receiving batch scan response indication from FW. It saves get batch scan
1092 response data in HDD batch scan response queue. This callback sets the
1093 completion event on which hdd_ioctl is waiting only after getting complete
1094 batch scan response data from FW
1095
1096 \param - callbackContext Pointer to HDD adapter
1097 \param - pRsp Pointer to get batch scan response data received from FW
1098
1099 \return - nothing
1100
1101 --------------------------------------------------------------------------*/
1102static void hdd_batch_scan_result_ind_callback
1103(
1104 void *callbackContext,
1105 void *pRsp
1106)
1107{
1108 v_BOOL_t isLastAp;
1109 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001110 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301111 tANI_U32 numberScanList;
1112 tANI_U32 nextScanListOffset;
1113 tANI_U32 nextApMetaInfoOffset;
1114 hdd_adapter_t* pAdapter;
1115 tpSirBatchScanList pScanList;
1116 tpSirBatchScanNetworkInfo pApMetaInfo;
1117 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1118 tSirSetBatchScanReq *pReq;
1119
1120 pAdapter = (hdd_adapter_t *)callbackContext;
1121 /*sanity check*/
1122 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1123 {
1124 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1125 "%s: Invalid pAdapter magic", __func__);
1126 VOS_ASSERT(0);
1127 return;
1128 }
1129
1130 /*initialize locals*/
1131 pReq = &pAdapter->hddSetBatchScanReq;
1132 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1133 isLastAp = FALSE;
1134 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001135 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301136 numberScanList = 0;
1137 nextScanListOffset = 0;
1138 nextApMetaInfoOffset = 0;
1139 pScanList = NULL;
1140 pApMetaInfo = NULL;
1141
1142 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1143 {
1144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1145 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1146 isLastAp = TRUE;
1147 goto done;
1148 }
1149
1150 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1152 "Batch scan rsp: numberScalList %d", numberScanList);
1153
1154 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1155 {
1156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1157 "%s: numberScanList %d", __func__, numberScanList);
1158 isLastAp = TRUE;
1159 goto done;
1160 }
1161
1162 while (numberScanList)
1163 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001164 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301165 nextScanListOffset);
1166 if (NULL == pScanList)
1167 {
1168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "%s: pScanList is %p", __func__, pScanList);
1170 isLastAp = TRUE;
1171 goto done;
1172 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001173 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001175 "Batch scan rsp: numApMetaInfo %d scanId %d",
1176 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301177
1178 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1179 {
1180 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1181 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1182 isLastAp = TRUE;
1183 goto done;
1184 }
1185
Rajeev Kumarce651e42013-10-21 18:57:15 -07001186 /*Initialize next AP meta info offset for next scan list*/
1187 nextApMetaInfoOffset = 0;
1188
Rajeev79dbe4c2013-10-05 11:03:42 +05301189 while (numApMetaInfo)
1190 {
1191 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1192 nextApMetaInfoOffset);
1193 if (NULL == pApMetaInfo)
1194 {
1195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1197 isLastAp = TRUE;
1198 goto done;
1199 }
1200 /*calculate AP age*/
1201 pApMetaInfo->timestamp =
1202 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1203
1204 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1205 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1206 "ch %d rssi %d timestamp %d", __func__,
1207 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1208 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1209 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1210 pApMetaInfo->ch, pApMetaInfo->rssi,
1211 pApMetaInfo->timestamp);
1212
1213 /*mark last AP in batch scan response*/
1214 if ((TRUE == pBatchScanRsp->isLastResult) &&
1215 (1 == numberScanList) && (1 == numApMetaInfo))
1216 {
1217 isLastAp = TRUE;
1218 }
1219
1220 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1221 /*store batch scan repsonse in hdd queue*/
1222 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1223 pScanList->scanId, isLastAp);
1224 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1225
1226 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1227 numApMetaInfo--;
1228 }
1229
Rajeev Kumarce651e42013-10-21 18:57:15 -07001230 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1231 + (sizeof(tSirBatchScanNetworkInfo)
1232 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301233 numberScanList--;
1234 }
1235
1236done:
1237
1238 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1239 requested from hdd_ioctl*/
1240 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1241 (TRUE == isLastAp))
1242 {
1243 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1244 complete(&pAdapter->hdd_get_batch_scan_req_var);
1245 }
1246
1247 return;
1248}/*End of hdd_batch_scan_result_ind_callback*/
1249
1250/**---------------------------------------------------------------------------
1251
1252 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1253 response as per batch scan FR request format by putting proper markers
1254
1255 \param - pDest pointer to destination buffer
1256 \param - cur_len current length
1257 \param - tot_len total remaining size which can be written to user space
1258 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1259 \param - pAdapter Pointer to HDD adapter
1260
1261 \return - ret no of characters written
1262
1263 --------------------------------------------------------------------------*/
1264static tANI_U32
1265hdd_format_batch_scan_rsp
1266(
1267 tANI_U8 *pDest,
1268 tANI_U32 cur_len,
1269 tANI_U32 tot_len,
1270 tHddBatchScanRsp *pApMetaInfo,
1271 hdd_adapter_t* pAdapter
1272)
1273{
1274 tANI_U32 ret = 0;
1275 tANI_U32 rem_len = 0;
1276 tANI_U8 temp_len = 0;
1277 tANI_U8 temp_total_len = 0;
1278 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1279 tANI_U8 *pTemp = temp;
1280
1281 /*Batch scan reponse needs to be returned to user space in
1282 following format:
1283 "scancount=X\n" where X is the number of scans in current batch
1284 batch
1285 "trunc\n" optional present if current scan truncated
1286 "bssid=XX:XX:XX:XX:XX:XX\n"
1287 "ssid=XXXX\n"
1288 "freq=X\n" frequency in Mhz
1289 "level=XX\n"
1290 "age=X\n" ms
1291 "dist=X\n" cm (-1 if not available)
1292 "errror=X\n" (-1if not available)
1293 "====\n" (end of ap marker)
1294 "####\n" (end of scan marker)
1295 "----\n" (end of results)*/
1296 /*send scan result in above format to user space based on
1297 available length*/
1298 /*The GET response may have more data than the driver can return in its
1299 buffer. In that case the buffer should be filled to the nearest complete
1300 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1301 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1302 The final buffer should end with "----\n"*/
1303
1304 /*sanity*/
1305 if (cur_len > tot_len)
1306 {
1307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1308 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1309 return 0;
1310 }
1311 else
1312 {
1313 rem_len = (tot_len - cur_len);
1314 }
1315
1316 /*end scan marker*/
1317 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1318 {
1319 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1320 pTemp += temp_len;
1321 temp_total_len += temp_len;
1322 }
1323
1324 /*bssid*/
1325 temp_len = snprintf(pTemp, sizeof(temp),
1326 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1327 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1328 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1329 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1330 pTemp += temp_len;
1331 temp_total_len += temp_len;
1332
1333 /*ssid*/
1334 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1335 pApMetaInfo->ApInfo.ssid);
1336 pTemp += temp_len;
1337 temp_total_len += temp_len;
1338
1339 /*freq*/
1340 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001341 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301342 pTemp += temp_len;
1343 temp_total_len += temp_len;
1344
1345 /*level*/
1346 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1347 pApMetaInfo->ApInfo.rssi);
1348 pTemp += temp_len;
1349 temp_total_len += temp_len;
1350
1351 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001352 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301353 pApMetaInfo->ApInfo.age);
1354 pTemp += temp_len;
1355 temp_total_len += temp_len;
1356
1357 /*dist*/
1358 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1359 pTemp += temp_len;
1360 temp_total_len += temp_len;
1361
1362 /*error*/
1363 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1364 pTemp += temp_len;
1365 temp_total_len += temp_len;
1366
1367 /*end AP marker*/
1368 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1369 pTemp += temp_len;
1370 temp_total_len += temp_len;
1371
1372 /*last AP in batch scan response*/
1373 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1374 {
1375 /*end scan marker*/
1376 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1377 pTemp += temp_len;
1378 temp_total_len += temp_len;
1379
1380 /*end batch scan result marker*/
1381 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1382 pTemp += temp_len;
1383 temp_total_len += temp_len;
1384 }
1385
1386 if (temp_total_len < rem_len)
1387 {
1388 ret = temp_total_len + 1;
1389 strlcpy(pDest, temp, ret);
1390 pAdapter->isTruncated = FALSE;
1391 }
1392 else
1393 {
1394 pAdapter->isTruncated = TRUE;
1395 if (rem_len >= strlen("%%%%"))
1396 {
1397 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1398 }
1399 {
1400 ret = 0;
1401 }
1402 }
1403
1404 return ret;
1405
1406}/*End of hdd_format_batch_scan_rsp*/
1407
1408/**---------------------------------------------------------------------------
1409
1410 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1411 buffer starting with head of hdd batch scan response queue
1412
1413 \param - pAdapter Pointer to HDD adapter
1414 \param - pDest Pointer to user data buffer
1415 \param - cur_len current offset in user buffer
1416 \param - rem_len remaining no of bytes in user buffer
1417
1418 \return - number of bytes written in user buffer
1419
1420 --------------------------------------------------------------------------*/
1421
1422tANI_U32 hdd_populate_user_batch_scan_rsp
1423(
1424 hdd_adapter_t* pAdapter,
1425 tANI_U8 *pDest,
1426 tANI_U32 cur_len,
1427 tANI_U32 rem_len
1428)
1429{
1430 tHddBatchScanRsp *pHead;
1431 tHddBatchScanRsp *pPrev;
1432 tANI_U32 len;
1433
1434 pAdapter->prev_batch_id = 0;
1435 pAdapter->isTruncated = FALSE;
1436
1437 /*head of hdd batch scan response queue*/
1438 pHead = pAdapter->pBatchScanRsp;
1439 while (pHead)
1440 {
1441 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1442 pAdapter);
1443 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001444 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301445 cur_len += len;
1446 if(TRUE == pAdapter->isTruncated)
1447 {
1448 /*result is truncated return rest of scan rsp in next req*/
1449 cur_len = rem_len;
1450 break;
1451 }
1452 pPrev = pHead;
1453 pHead = pHead->pNext;
1454 pAdapter->pBatchScanRsp = pHead;
1455 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1456 vos_mem_free(pPrev);
1457 }
1458
1459 return cur_len;
1460}/*End of hdd_populate_user_batch_scan_rsp*/
1461
1462/**---------------------------------------------------------------------------
1463
1464 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1465 scan response data from HDD queue to user space
1466 It does following in detail:
1467 a) if HDD has enough data in its queue then it 1st copies data to user
1468 space and then send get batch scan indication message to FW. In this
1469 case it does not wait on any event and batch scan response data will
1470 be populated in HDD response queue in MC thread context after receiving
1471 indication from FW
1472 b) else send get batch scan indication message to FW and wait on an event
1473 which will be set once HDD receives complete batch scan response from
1474 FW and then this function returns batch scan response to user space
1475
1476 \param - pAdapter Pointer to HDD adapter
1477 \param - pPrivData Pointer to priv_data
1478
1479 \return - 0 for success -EFAULT for failure
1480
1481 --------------------------------------------------------------------------*/
1482
1483int hdd_return_batch_scan_rsp_to_user
1484(
1485 hdd_adapter_t* pAdapter,
1486 hdd_priv_data_t *pPrivData,
1487 tANI_U8 *command
1488)
1489{
1490 tANI_U8 *pDest;
1491 tANI_U32 count = 0;
1492 tANI_U32 len = 0;
1493 tANI_U32 cur_len = 0;
1494 tANI_U32 rem_len = 0;
1495 eHalStatus halStatus;
1496 unsigned long rc;
1497 tSirTriggerBatchScanResultInd *pReq;
1498
1499 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1500 pReq->param = 0;/*batch scan client*/
1501 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1502 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1503
1504 cur_len = pPrivData->used_len;
1505 if (pPrivData->total_len > pPrivData->used_len)
1506 {
1507 rem_len = pPrivData->total_len - pPrivData->used_len;
1508 }
1509 else
1510 {
1511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1512 "%s: Invalid user data buffer total_len %d used_len %d",
1513 __func__, pPrivData->total_len, pPrivData->used_len);
1514 return -EFAULT;
1515 }
1516
1517 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1518 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1519 cur_len, rem_len);
1520 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1521
1522 /*enough scan result available in cache to return to user space or
1523 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001524 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301525 {
1526 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1527 halStatus = sme_TriggerBatchScanResultInd(
1528 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1529 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1530 pAdapter);
1531 if ( eHAL_STATUS_SUCCESS == halStatus )
1532 {
1533 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1534 {
1535 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1536 rc = wait_for_completion_timeout(
1537 &pAdapter->hdd_get_batch_scan_req_var,
1538 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1539 if (0 == rc)
1540 {
1541 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1542 "%s: Timeout waiting to fetch batch scan rsp from fw",
1543 __func__);
1544 return -EFAULT;
1545 }
1546 }
1547
1548 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001549 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301550 pDest += len;
1551 cur_len += len;
1552
1553 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1554 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1555 cur_len, rem_len);
1556 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1557
1558 count = 0;
1559 len = (len - pPrivData->used_len);
1560 pDest = (command + pPrivData->used_len);
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001562 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301563 while(count < len)
1564 {
1565 printk("%c", *(pDest + count));
1566 count++;
1567 }
1568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1569 "%s: copy %d data to user buffer", __func__, len);
1570 if (copy_to_user(pPrivData->buf, pDest, len))
1571 {
1572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1573 "%s: failed to copy data to user buffer", __func__);
1574 return -EFAULT;
1575 }
1576 }
1577 else
1578 {
1579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1580 "sme_GetBatchScanScan returned failure halStatus %d",
1581 halStatus);
1582 return -EINVAL;
1583 }
1584 }
1585 else
1586 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301587 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 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301592 while(count < len)
1593 {
1594 printk("%c", *(pDest + count));
1595 count++;
1596 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301599 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 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301605 }
1606
1607 return 0;
1608} /*End of hdd_return_batch_scan_rsp_to_user*/
1609
1610#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1611
Jeff Johnson295189b2012-06-20 16:38:30 -07001612int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1613{
1614 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1615 hdd_priv_data_t priv_data;
1616 tANI_U8 *command = NULL;
1617 int ret = 0;
1618
1619 if (NULL == pAdapter)
1620 {
1621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001622 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001623 ret = -ENODEV;
1624 goto exit;
1625 }
1626
Jeff Johnsone7245742012-09-05 17:12:55 -07001627 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001628 {
1629 ret = -EINVAL;
1630 goto exit;
1631 }
1632
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001633 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1634 {
1635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1636 "%s:LOGP in Progress. Ignore!!!", __func__);
1637 ret = -EBUSY;
1638 goto exit;
1639 }
1640
Jeff Johnson295189b2012-06-20 16:38:30 -07001641 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1642 {
1643 ret = -EFAULT;
1644 goto exit;
1645 }
1646
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001647 if (priv_data.total_len <= 0)
1648 {
1649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1650 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1651 priv_data.total_len);
1652 ret = -EINVAL;
1653 goto exit;
1654 }
1655
1656 /* Allocate +1 for '\0' */
1657 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001658 if (!command)
1659 {
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001661 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001662 ret = -ENOMEM;
1663 goto exit;
1664 }
1665
1666 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1667 {
1668 ret = -EFAULT;
1669 goto exit;
1670 }
1671
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001672 /* Making sure the command is NUL-terminated */
1673 command[priv_data.total_len] = '\0';
1674
Jeff Johnson295189b2012-06-20 16:38:30 -07001675 if ((SIOCDEVPRIVATE + 1) == cmd)
1676 {
1677 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1678
1679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001680 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001681
1682 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1683 {
1684 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1685 sizeof(tSirMacAddr)))
1686 {
1687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001688 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001689 ret = -EFAULT;
1690 }
1691 }
Amar Singhal0974e402013-02-12 14:27:46 -08001692 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 {
Amar Singhal0974e402013-02-12 14:27:46 -08001694 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001695 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001696
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001698
1699 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001700 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001701 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001702 "%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 -07001703 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001704 ret = hdd_setBand_helper(dev, ptr);
1705 }
Kiet Lamf040f472013-11-20 21:15:23 +05301706 else if(strncmp(command, "SETWMMPS", 8) == 0)
1707 {
1708 tANI_U8 *ptr = command;
1709 ret = hdd_wmmps_helper(pAdapter, ptr);
1710 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001711 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1712 {
1713 char *country_code;
1714
1715 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001716
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001717 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001718 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001719#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301720 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001721#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001722 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1723 (void *)(tSmeChangeCountryCallback)
1724 wlan_hdd_change_country_code_callback,
1725 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1726 if (eHAL_STATUS_SUCCESS == ret)
1727 {
1728 ret = wait_for_completion_interruptible_timeout(
1729 &pAdapter->change_country_code,
1730 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1731 if (0 >= ret)
1732 {
1733 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1734 __func__);
1735 }
1736 }
1737 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001738 {
1739 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001740 "%s: SME Change Country code fail ret=%d", __func__, ret);
1741 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001742 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001743
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001744 }
1745 /*
1746 command should be a string having format
1747 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1748 */
Amar Singhal0974e402013-02-12 14:27:46 -08001749 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001750 {
Amar Singhal0974e402013-02-12 14:27:46 -08001751 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001752
1753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001754 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001755
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001756 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001757 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001758 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1759 {
1760 int suspend = 0;
1761 tANI_U8 *ptr = (tANI_U8*)command + 15;
1762
1763 suspend = *ptr - '0';
1764 hdd_set_wlan_suspend_mode(suspend);
1765 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001766#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1767 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1768 {
1769 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001770 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001771 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1772 eHalStatus status = eHAL_STATUS_SUCCESS;
1773
1774 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1775 value = value + 15;
1776
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001777 /* Convert the value from ascii to integer */
1778 ret = kstrtos8(value, 10, &rssi);
1779 if (ret < 0)
1780 {
1781 /* If the input value is greater than max value of datatype, then also
1782 kstrtou8 fails */
1783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1784 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001785 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001786 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1787 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1788 ret = -EINVAL;
1789 goto exit;
1790 }
1791
Srinivas Girigowdade697412013-02-14 16:31:48 -08001792 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001793
Srinivas Girigowdade697412013-02-14 16:31:48 -08001794 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1795 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1796 {
1797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1798 "Neighbor lookup threshold value %d is out of range"
1799 " (Min: %d Max: %d)", lookUpThreshold,
1800 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1801 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1802 ret = -EINVAL;
1803 goto exit;
1804 }
1805
1806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1807 "%s: Received Command to Set Roam trigger"
1808 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1809
1810 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1811 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1812 if (eHAL_STATUS_SUCCESS != status)
1813 {
1814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1815 "%s: Failed to set roam trigger, try again", __func__);
1816 ret = -EPERM;
1817 goto exit;
1818 }
1819
1820 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1821 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1822 }
1823 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1824 {
1825 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1826 int rssi = (-1) * lookUpThreshold;
1827 char extra[32];
1828 tANI_U8 len = 0;
1829
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001830 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001831 if (copy_to_user(priv_data.buf, &extra, len + 1))
1832 {
1833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1834 "%s: failed to copy data to user buffer", __func__);
1835 ret = -EFAULT;
1836 goto exit;
1837 }
1838 }
1839 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1840 {
1841 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001842 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001843 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001844
Srinivas Girigowdade697412013-02-14 16:31:48 -08001845 /* input refresh period is in terms of seconds */
1846 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1847 value = value + 18;
1848 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001849 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001850 if (ret < 0)
1851 {
1852 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001853 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001855 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001856 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001857 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1858 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001859 ret = -EINVAL;
1860 goto exit;
1861 }
1862
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001863 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1864 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001865 {
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001867 "Roam scan period value %d is out of range"
1868 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001869 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1870 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001871 ret = -EINVAL;
1872 goto exit;
1873 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001874 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001875
1876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1877 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001878 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001879
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001880 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1881 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001882 }
1883 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1884 {
1885 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1886 char extra[32];
1887 tANI_U8 len = 0;
1888
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001889 len = scnprintf(extra, sizeof(extra), "%s %d",
1890 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001891 /* Returned value is in units of seconds */
1892 if (copy_to_user(priv_data.buf, &extra, len + 1))
1893 {
1894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1895 "%s: failed to copy data to user buffer", __func__);
1896 ret = -EFAULT;
1897 goto exit;
1898 }
1899 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001900 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1901 {
1902 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001903 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001904 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001905
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001906 /* input refresh period is in terms of seconds */
1907 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1908 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001909
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001910 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001911 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001912 if (ret < 0)
1913 {
1914 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001915 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001917 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001918 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1920 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1921 ret = -EINVAL;
1922 goto exit;
1923 }
1924
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001925 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1926 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1927 {
1928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "Neighbor scan results refresh period value %d is out of range"
1930 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1931 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1932 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1933 ret = -EINVAL;
1934 goto exit;
1935 }
1936 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1937
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1939 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001940 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001941
1942 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1943 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1944 }
1945 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1946 {
1947 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1948 char extra[32];
1949 tANI_U8 len = 0;
1950
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001951 len = scnprintf(extra, sizeof(extra), "%s %d",
1952 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001953 /* Returned value is in units of seconds */
1954 if (copy_to_user(priv_data.buf, &extra, len + 1))
1955 {
1956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1957 "%s: failed to copy data to user buffer", __func__);
1958 ret = -EFAULT;
1959 goto exit;
1960 }
1961 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001962#ifdef FEATURE_WLAN_LFR
1963 /* SETROAMMODE */
1964 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1965 {
1966 tANI_U8 *value = command;
1967 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1968
1969 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1970 value = value + SIZE_OF_SETROAMMODE + 1;
1971
1972 /* Convert the value from ascii to integer */
1973 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1974 if (ret < 0)
1975 {
1976 /* If the input value is greater than max value of datatype, then also
1977 kstrtou8 fails */
1978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1979 "%s: kstrtou8 failed range [%d - %d]", __func__,
1980 CFG_LFR_FEATURE_ENABLED_MIN,
1981 CFG_LFR_FEATURE_ENABLED_MAX);
1982 ret = -EINVAL;
1983 goto exit;
1984 }
1985 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1986 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1987 {
1988 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1989 "Roam Mode value %d is out of range"
1990 " (Min: %d Max: %d)", roamMode,
1991 CFG_LFR_FEATURE_ENABLED_MIN,
1992 CFG_LFR_FEATURE_ENABLED_MAX);
1993 ret = -EINVAL;
1994 goto exit;
1995 }
1996
1997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1998 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1999 /*
2000 * Note that
2001 * SETROAMMODE 0 is to enable LFR while
2002 * SETROAMMODE 1 is to disable LFR, but
2003 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2004 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2005 */
2006 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2007 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2008 else
2009 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2010
2011 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2012 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2013 }
2014 /* GETROAMMODE */
2015 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2016 {
2017 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2018 char extra[32];
2019 tANI_U8 len = 0;
2020
2021 /*
2022 * roamMode value shall be inverted because the sementics is different.
2023 */
2024 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2025 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2026 else
2027 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2028
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002029 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002030 if (copy_to_user(priv_data.buf, &extra, len + 1))
2031 {
2032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2033 "%s: failed to copy data to user buffer", __func__);
2034 ret = -EFAULT;
2035 goto exit;
2036 }
2037 }
2038#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002039#endif
2040#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2041 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2042 {
2043 tANI_U8 *value = command;
2044 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2045
2046 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2047 value = value + 13;
2048 /* Convert the value from ascii to integer */
2049 ret = kstrtou8(value, 10, &roamRssiDiff);
2050 if (ret < 0)
2051 {
2052 /* If the input value is greater than max value of datatype, then also
2053 kstrtou8 fails */
2054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2055 "%s: kstrtou8 failed range [%d - %d]", __func__,
2056 CFG_ROAM_RSSI_DIFF_MIN,
2057 CFG_ROAM_RSSI_DIFF_MAX);
2058 ret = -EINVAL;
2059 goto exit;
2060 }
2061
2062 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2063 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2064 {
2065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2066 "Roam rssi diff value %d is out of range"
2067 " (Min: %d Max: %d)", roamRssiDiff,
2068 CFG_ROAM_RSSI_DIFF_MIN,
2069 CFG_ROAM_RSSI_DIFF_MAX);
2070 ret = -EINVAL;
2071 goto exit;
2072 }
2073
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2075 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2076
2077 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2078 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2079 }
2080 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2081 {
2082 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2083 char extra[32];
2084 tANI_U8 len = 0;
2085
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002086 len = scnprintf(extra, sizeof(extra), "%s %d",
2087 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002088 if (copy_to_user(priv_data.buf, &extra, len + 1))
2089 {
2090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2091 "%s: failed to copy data to user buffer", __func__);
2092 ret = -EFAULT;
2093 goto exit;
2094 }
2095 }
2096#endif
2097#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2098 else if (strncmp(command, "GETBAND", 7) == 0)
2099 {
2100 int band = -1;
2101 char extra[32];
2102 tANI_U8 len = 0;
2103 hdd_getBand_helper(pHddCtx, &band);
2104
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002105 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002106 if (copy_to_user(priv_data.buf, &extra, len + 1))
2107 {
2108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2109 "%s: failed to copy data to user buffer", __func__);
2110 ret = -EFAULT;
2111 goto exit;
2112 }
2113 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002114 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2115 {
2116 tANI_U8 *value = command;
2117 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2118 tANI_U8 numChannels = 0;
2119 eHalStatus status = eHAL_STATUS_SUCCESS;
2120
2121 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2122 if (eHAL_STATUS_SUCCESS != status)
2123 {
2124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2125 "%s: Failed to parse channel list information", __func__);
2126 ret = -EINVAL;
2127 goto exit;
2128 }
2129
2130 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2131 {
2132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2133 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2134 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2135 ret = -EINVAL;
2136 goto exit;
2137 }
2138 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2139 numChannels);
2140 if (eHAL_STATUS_SUCCESS != status)
2141 {
2142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2143 "%s: Failed to update channel list information", __func__);
2144 ret = -EINVAL;
2145 goto exit;
2146 }
2147 }
2148 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2149 {
2150 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2151 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002152 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002153 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002154 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002155
2156 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2157 ChannelList, &numChannels ))
2158 {
2159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2160 "%s: failed to get roam scan channel list", __func__);
2161 ret = -EFAULT;
2162 goto exit;
2163 }
2164 /* output channel list is of the format
2165 [Number of roam scan channels][Channel1][Channel2]... */
2166 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002167 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002168 for (j = 0; (j < numChannels); j++)
2169 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002170 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2171 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002172 }
2173
2174 if (copy_to_user(priv_data.buf, &extra, len + 1))
2175 {
2176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2177 "%s: failed to copy data to user buffer", __func__);
2178 ret = -EFAULT;
2179 goto exit;
2180 }
2181 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002182 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2183 {
2184 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2185 char extra[32];
2186 tANI_U8 len = 0;
2187
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002188 /* Check if the features OKC/CCX/11R are supported simultaneously,
2189 then this operation is not permitted (return FAILURE) */
2190 if (ccxMode &&
2191 hdd_is_okc_mode_enabled(pHddCtx) &&
2192 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2193 {
2194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2195 "%s: OKC/CCX/11R are supported simultaneously"
2196 " hence this operation is not permitted!", __func__);
2197 ret = -EPERM;
2198 goto exit;
2199 }
2200
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002201 len = scnprintf(extra, sizeof(extra), "%s %d",
2202 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002203 if (copy_to_user(priv_data.buf, &extra, len + 1))
2204 {
2205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2206 "%s: failed to copy data to user buffer", __func__);
2207 ret = -EFAULT;
2208 goto exit;
2209 }
2210 }
2211 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2212 {
2213 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2214 char extra[32];
2215 tANI_U8 len = 0;
2216
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002217 /* Check if the features OKC/CCX/11R are supported simultaneously,
2218 then this operation is not permitted (return FAILURE) */
2219 if (okcMode &&
2220 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2221 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2222 {
2223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2224 "%s: OKC/CCX/11R are supported simultaneously"
2225 " hence this operation is not permitted!", __func__);
2226 ret = -EPERM;
2227 goto exit;
2228 }
2229
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002230 len = scnprintf(extra, sizeof(extra), "%s %d",
2231 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002232 if (copy_to_user(priv_data.buf, &extra, len + 1))
2233 {
2234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2235 "%s: failed to copy data to user buffer", __func__);
2236 ret = -EFAULT;
2237 goto exit;
2238 }
2239 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002240 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002241 {
2242 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2243 char extra[32];
2244 tANI_U8 len = 0;
2245
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002246 len = scnprintf(extra, sizeof(extra), "%s %d",
2247 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002248 if (copy_to_user(priv_data.buf, &extra, len + 1))
2249 {
2250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2251 "%s: failed to copy data to user buffer", __func__);
2252 ret = -EFAULT;
2253 goto exit;
2254 }
2255 }
2256 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2257 {
2258 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2259 char extra[32];
2260 tANI_U8 len = 0;
2261
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002262 len = scnprintf(extra, sizeof(extra), "%s %d",
2263 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002264 if (copy_to_user(priv_data.buf, &extra, len + 1))
2265 {
2266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2267 "%s: failed to copy data to user buffer", __func__);
2268 ret = -EFAULT;
2269 goto exit;
2270 }
2271 }
2272 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2273 {
2274 tANI_U8 *value = command;
2275 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2276
2277 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2278 value = value + 26;
2279 /* Convert the value from ascii to integer */
2280 ret = kstrtou8(value, 10, &minTime);
2281 if (ret < 0)
2282 {
2283 /* If the input value is greater than max value of datatype, then also
2284 kstrtou8 fails */
2285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2286 "%s: kstrtou8 failed range [%d - %d]", __func__,
2287 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2288 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2289 ret = -EINVAL;
2290 goto exit;
2291 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002292 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2293 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2294 {
2295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2296 "scan min channel time value %d is out of range"
2297 " (Min: %d Max: %d)", minTime,
2298 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2299 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2300 ret = -EINVAL;
2301 goto exit;
2302 }
2303
2304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2305 "%s: Received Command to change channel min time = %d", __func__, minTime);
2306
2307 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2308 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2309 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002310 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2311 {
2312 tANI_U8 *value = command;
2313 tANI_U8 channel = 0;
2314 tANI_U8 dwellTime = 0;
2315 tANI_U8 bufLen = 0;
2316 tANI_U8 *buf = NULL;
2317 tSirMacAddr targetApBssid;
2318 eHalStatus status = eHAL_STATUS_SUCCESS;
2319 struct ieee80211_channel chan;
2320 tANI_U8 finalLen = 0;
2321 tANI_U8 *finalBuf = NULL;
2322 tANI_U8 temp = 0;
2323 u64 cookie;
2324 hdd_station_ctx_t *pHddStaCtx = NULL;
2325 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2326
2327 /* if not associated, no need to send action frame */
2328 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2329 {
2330 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2331 ret = -EINVAL;
2332 goto exit;
2333 }
2334
2335 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2336 &dwellTime, &buf, &bufLen);
2337 if (eHAL_STATUS_SUCCESS != status)
2338 {
2339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2340 "%s: Failed to parse send action frame data", __func__);
2341 ret = -EINVAL;
2342 goto exit;
2343 }
2344
2345 /* if the target bssid is different from currently associated AP,
2346 then no need to send action frame */
2347 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2348 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2349 {
2350 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2351 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002352 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002353 goto exit;
2354 }
2355
2356 /* if the channel number is different from operating channel then
2357 no need to send action frame */
2358 if (channel != pHddStaCtx->conn_info.operationChannel)
2359 {
2360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2361 "%s: channel(%d) is different from operating channel(%d)",
2362 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2363 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002364 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002365 goto exit;
2366 }
2367 chan.center_freq = sme_ChnToFreq(channel);
2368
2369 finalLen = bufLen + 24;
2370 finalBuf = vos_mem_malloc(finalLen);
2371 if (NULL == finalBuf)
2372 {
2373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2374 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002375 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002376 goto exit;
2377 }
2378 vos_mem_zero(finalBuf, finalLen);
2379
2380 /* Fill subtype */
2381 temp = SIR_MAC_MGMT_ACTION << 4;
2382 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2383
2384 /* Fill type */
2385 temp = SIR_MAC_MGMT_FRAME;
2386 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2387
2388 /* Fill destination address (bssid of the AP) */
2389 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2390
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002391 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002392 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2393
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002394 /* Fill BSSID (AP mac address) */
2395 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002396
2397 /* Fill received buffer from 24th address */
2398 vos_mem_copy(finalBuf + 24, buf, bufLen);
2399
Jeff Johnson11c33152013-04-16 17:52:40 -07002400 /* done with the parsed buffer */
2401 vos_mem_free(buf);
2402
Yue Maf49ba872013-08-19 12:04:25 -07002403 wlan_hdd_action( NULL,
2404#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2405 &(pAdapter->wdev),
2406#else
2407 dev,
2408#endif
2409 &chan, 0,
2410#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2411 NL80211_CHAN_HT20, 1,
2412#endif
2413 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002414 1, &cookie );
2415 vos_mem_free(finalBuf);
2416 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002417 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2418 {
2419 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2420 char extra[32];
2421 tANI_U8 len = 0;
2422
2423 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002424 len = scnprintf(extra, sizeof(extra), "%s %d",
2425 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002426 if (copy_to_user(priv_data.buf, &extra, len + 1))
2427 {
2428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2429 "%s: failed to copy data to user buffer", __func__);
2430 ret = -EFAULT;
2431 goto exit;
2432 }
2433 }
2434 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2435 {
2436 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002437 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002438 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002439
2440 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2441 value = value + 19;
2442 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002443 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002444 if (ret < 0)
2445 {
2446 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002447 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002449 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002450 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2451 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2452 ret = -EINVAL;
2453 goto exit;
2454 }
2455
2456 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2457 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2458 {
2459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2460 "lfr mode value %d is out of range"
2461 " (Min: %d Max: %d)", maxTime,
2462 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2463 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2464 ret = -EINVAL;
2465 goto exit;
2466 }
2467
2468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2469 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2470
2471 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002472
2473 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2474 * where RFS is the RF Switching time. It is twice RFS to consider the
2475 * time to go off channel and return to the home channel. */
2476 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2477 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2478 {
2479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002480 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002481 " Hence enforcing home away time to disable (0)",
2482 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2483 homeAwayTime = 0;
2484 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2485 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2486 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002487 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2488 }
2489 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2490 {
2491 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2492 char extra[32];
2493 tANI_U8 len = 0;
2494
2495 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002496 len = scnprintf(extra, sizeof(extra), "%s %d",
2497 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002498 if (copy_to_user(priv_data.buf, &extra, len + 1))
2499 {
2500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2501 "%s: failed to copy data to user buffer", __func__);
2502 ret = -EFAULT;
2503 goto exit;
2504 }
2505 }
2506 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2507 {
2508 tANI_U8 *value = command;
2509 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2510
2511 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2512 value = value + 16;
2513 /* Convert the value from ascii to integer */
2514 ret = kstrtou16(value, 10, &val);
2515 if (ret < 0)
2516 {
2517 /* If the input value is greater than max value of datatype, then also
2518 kstrtou16 fails */
2519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2520 "%s: kstrtou16 failed range [%d - %d]", __func__,
2521 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2522 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2523 ret = -EINVAL;
2524 goto exit;
2525 }
2526
2527 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2528 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2531 "scan home time value %d is out of range"
2532 " (Min: %d Max: %d)", val,
2533 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2534 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2535 ret = -EINVAL;
2536 goto exit;
2537 }
2538
2539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2540 "%s: Received Command to change scan home time = %d", __func__, val);
2541
2542 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2543 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2544 }
2545 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2546 {
2547 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2548 char extra[32];
2549 tANI_U8 len = 0;
2550
2551 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002552 len = scnprintf(extra, sizeof(extra), "%s %d",
2553 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002554 if (copy_to_user(priv_data.buf, &extra, len + 1))
2555 {
2556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2557 "%s: failed to copy data to user buffer", __func__);
2558 ret = -EFAULT;
2559 goto exit;
2560 }
2561 }
2562 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2563 {
2564 tANI_U8 *value = command;
2565 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2566
2567 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2568 value = value + 17;
2569 /* Convert the value from ascii to integer */
2570 ret = kstrtou8(value, 10, &val);
2571 if (ret < 0)
2572 {
2573 /* If the input value is greater than max value of datatype, then also
2574 kstrtou8 fails */
2575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2576 "%s: kstrtou8 failed range [%d - %d]", __func__,
2577 CFG_ROAM_INTRA_BAND_MIN,
2578 CFG_ROAM_INTRA_BAND_MAX);
2579 ret = -EINVAL;
2580 goto exit;
2581 }
2582
2583 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2584 (val > CFG_ROAM_INTRA_BAND_MAX))
2585 {
2586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2587 "intra band mode value %d is out of range"
2588 " (Min: %d Max: %d)", val,
2589 CFG_ROAM_INTRA_BAND_MIN,
2590 CFG_ROAM_INTRA_BAND_MAX);
2591 ret = -EINVAL;
2592 goto exit;
2593 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2595 "%s: Received Command to change intra band = %d", __func__, val);
2596
2597 pHddCtx->cfg_ini->nRoamIntraBand = val;
2598 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2599 }
2600 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2601 {
2602 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2603 char extra[32];
2604 tANI_U8 len = 0;
2605
2606 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002607 len = scnprintf(extra, sizeof(extra), "%s %d",
2608 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002609 if (copy_to_user(priv_data.buf, &extra, len + 1))
2610 {
2611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2612 "%s: failed to copy data to user buffer", __func__);
2613 ret = -EFAULT;
2614 goto exit;
2615 }
2616 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002617 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2618 {
2619 tANI_U8 *value = command;
2620 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2621
2622 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2623 value = value + 15;
2624 /* Convert the value from ascii to integer */
2625 ret = kstrtou8(value, 10, &nProbes);
2626 if (ret < 0)
2627 {
2628 /* If the input value is greater than max value of datatype, then also
2629 kstrtou8 fails */
2630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2631 "%s: kstrtou8 failed range [%d - %d]", __func__,
2632 CFG_ROAM_SCAN_N_PROBES_MIN,
2633 CFG_ROAM_SCAN_N_PROBES_MAX);
2634 ret = -EINVAL;
2635 goto exit;
2636 }
2637
2638 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2639 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2640 {
2641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2642 "NProbes value %d is out of range"
2643 " (Min: %d Max: %d)", nProbes,
2644 CFG_ROAM_SCAN_N_PROBES_MIN,
2645 CFG_ROAM_SCAN_N_PROBES_MAX);
2646 ret = -EINVAL;
2647 goto exit;
2648 }
2649
2650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2651 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2652
2653 pHddCtx->cfg_ini->nProbes = nProbes;
2654 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2655 }
2656 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2657 {
2658 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2659 char extra[32];
2660 tANI_U8 len = 0;
2661
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002662 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002663 if (copy_to_user(priv_data.buf, &extra, len + 1))
2664 {
2665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2666 "%s: failed to copy data to user buffer", __func__);
2667 ret = -EFAULT;
2668 goto exit;
2669 }
2670 }
2671 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2672 {
2673 tANI_U8 *value = command;
2674 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002675 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002676
2677 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2678 /* input value is in units of msec */
2679 value = value + 20;
2680 /* Convert the value from ascii to integer */
2681 ret = kstrtou16(value, 10, &homeAwayTime);
2682 if (ret < 0)
2683 {
2684 /* If the input value is greater than max value of datatype, then also
2685 kstrtou8 fails */
2686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2687 "%s: kstrtou8 failed range [%d - %d]", __func__,
2688 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2689 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2690 ret = -EINVAL;
2691 goto exit;
2692 }
2693
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002694 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2695 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2696 {
2697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2698 "homeAwayTime value %d is out of range"
2699 " (Min: %d Max: %d)", homeAwayTime,
2700 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2701 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2702 ret = -EINVAL;
2703 goto exit;
2704 }
2705
2706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2707 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2708
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002709 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2710 * where RFS is the RF Switching time. It is twice RFS to consider the
2711 * time to go off channel and return to the home channel. */
2712 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2713 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2714 {
2715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002716 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002717 " Hence enforcing home away time to disable (0)",
2718 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2719 homeAwayTime = 0;
2720 }
2721
2722 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2723 {
2724 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2725 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2726 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002727 }
2728 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2729 {
2730 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2731 char extra[32];
2732 tANI_U8 len = 0;
2733
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002734 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002735 if (copy_to_user(priv_data.buf, &extra, len + 1))
2736 {
2737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2738 "%s: failed to copy data to user buffer", __func__);
2739 ret = -EFAULT;
2740 goto exit;
2741 }
2742 }
2743 else if (strncmp(command, "REASSOC", 7) == 0)
2744 {
2745 tANI_U8 *value = command;
2746 tANI_U8 channel = 0;
2747 tSirMacAddr targetApBssid;
2748 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002749#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2750 tCsrHandoffRequest handoffInfo;
2751#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002752 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002753 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2754
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002755 /* if not associated, no need to proceed with reassoc */
2756 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2757 {
2758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2759 ret = -EINVAL;
2760 goto exit;
2761 }
2762
2763 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2764 if (eHAL_STATUS_SUCCESS != status)
2765 {
2766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2767 "%s: Failed to parse reassoc command data", __func__);
2768 ret = -EINVAL;
2769 goto exit;
2770 }
2771
2772 /* if the target bssid is same as currently associated AP,
2773 then no need to proceed with reassoc */
2774 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2775 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2776 {
2777 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2778 ret = -EINVAL;
2779 goto exit;
2780 }
2781
2782 /* Check channel number is a valid channel number */
2783 if(VOS_STATUS_SUCCESS !=
2784 wlan_hdd_validate_operation_channel(pAdapter, channel))
2785 {
2786 hddLog(VOS_TRACE_LEVEL_ERROR,
2787 "%s: Invalid Channel [%d] \n", __func__, channel);
2788 return -EINVAL;
2789 }
2790
2791 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002792#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2793 handoffInfo.channel = channel;
2794 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2795 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2796#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002797 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002798 else if (strncmp(command, "SETWESMODE", 10) == 0)
2799 {
2800 tANI_U8 *value = command;
2801 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2802
2803 /* Move pointer to ahead of SETWESMODE<delimiter> */
2804 value = value + 11;
2805 /* Convert the value from ascii to integer */
2806 ret = kstrtou8(value, 10, &wesMode);
2807 if (ret < 0)
2808 {
2809 /* If the input value is greater than max value of datatype, then also
2810 kstrtou8 fails */
2811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2812 "%s: kstrtou8 failed range [%d - %d]", __func__,
2813 CFG_ENABLE_WES_MODE_NAME_MIN,
2814 CFG_ENABLE_WES_MODE_NAME_MAX);
2815 ret = -EINVAL;
2816 goto exit;
2817 }
2818
2819 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2820 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2821 {
2822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2823 "WES Mode value %d is out of range"
2824 " (Min: %d Max: %d)", wesMode,
2825 CFG_ENABLE_WES_MODE_NAME_MIN,
2826 CFG_ENABLE_WES_MODE_NAME_MAX);
2827 ret = -EINVAL;
2828 goto exit;
2829 }
2830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2831 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2832
2833 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2834 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2835 }
2836 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2837 {
2838 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2839 char extra[32];
2840 tANI_U8 len = 0;
2841
Arif Hussain826d9412013-11-12 16:44:54 -08002842 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002843 if (copy_to_user(priv_data.buf, &extra, len + 1))
2844 {
2845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2846 "%s: failed to copy data to user buffer", __func__);
2847 ret = -EFAULT;
2848 goto exit;
2849 }
2850 }
2851#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002852#ifdef FEATURE_WLAN_LFR
2853 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2854 {
2855 tANI_U8 *value = command;
2856 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2857
2858 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2859 value = value + 12;
2860 /* Convert the value from ascii to integer */
2861 ret = kstrtou8(value, 10, &lfrMode);
2862 if (ret < 0)
2863 {
2864 /* If the input value is greater than max value of datatype, then also
2865 kstrtou8 fails */
2866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2867 "%s: kstrtou8 failed range [%d - %d]", __func__,
2868 CFG_LFR_FEATURE_ENABLED_MIN,
2869 CFG_LFR_FEATURE_ENABLED_MAX);
2870 ret = -EINVAL;
2871 goto exit;
2872 }
2873
2874 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2875 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2876 {
2877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2878 "lfr mode value %d is out of range"
2879 " (Min: %d Max: %d)", lfrMode,
2880 CFG_LFR_FEATURE_ENABLED_MIN,
2881 CFG_LFR_FEATURE_ENABLED_MAX);
2882 ret = -EINVAL;
2883 goto exit;
2884 }
2885
2886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2887 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2888
2889 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2890 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2891 }
2892#endif
2893#ifdef WLAN_FEATURE_VOWIFI_11R
2894 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2895 {
2896 tANI_U8 *value = command;
2897 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2898
2899 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2900 value = value + 18;
2901 /* Convert the value from ascii to integer */
2902 ret = kstrtou8(value, 10, &ft);
2903 if (ret < 0)
2904 {
2905 /* If the input value is greater than max value of datatype, then also
2906 kstrtou8 fails */
2907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2908 "%s: kstrtou8 failed range [%d - %d]", __func__,
2909 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2910 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
2914
2915 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2916 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2917 {
2918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2919 "ft mode value %d is out of range"
2920 " (Min: %d Max: %d)", ft,
2921 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2922 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2923 ret = -EINVAL;
2924 goto exit;
2925 }
2926
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2928 "%s: Received Command to change ft mode = %d", __func__, ft);
2929
2930 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2931 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2932 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302933
2934 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2935 {
2936 tANI_U8 *value = command;
2937 tSirMacAddr targetApBssid;
2938 tANI_U8 trigger = 0;
2939 eHalStatus status = eHAL_STATUS_SUCCESS;
2940 hdd_station_ctx_t *pHddStaCtx = NULL;
2941 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2942
2943 /* if not associated, no need to proceed with reassoc */
2944 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2945 {
2946 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2947 ret = -EINVAL;
2948 goto exit;
2949 }
2950
2951 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2952 if (eHAL_STATUS_SUCCESS != status)
2953 {
2954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2955 "%s: Failed to parse reassoc command data", __func__);
2956 ret = -EINVAL;
2957 goto exit;
2958 }
2959
2960 /* if the target bssid is same as currently associated AP,
2961 then no need to proceed with reassoc */
2962 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2963 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2964 {
2965 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2966 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2967 __func__);
2968 ret = -EINVAL;
2969 goto exit;
2970 }
2971
2972 /* Proceed with scan/roam */
2973 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2974 &targetApBssid[0],
2975 (tSmeFastRoamTrigger)(trigger));
2976 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002977#endif
2978#ifdef FEATURE_WLAN_CCX
2979 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2980 {
2981 tANI_U8 *value = command;
2982 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2983
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002984 /* Check if the features OKC/CCX/11R are supported simultaneously,
2985 then this operation is not permitted (return FAILURE) */
2986 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2987 hdd_is_okc_mode_enabled(pHddCtx) &&
2988 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2989 {
2990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2991 "%s: OKC/CCX/11R are supported simultaneously"
2992 " hence this operation is not permitted!", __func__);
2993 ret = -EPERM;
2994 goto exit;
2995 }
2996
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002997 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2998 value = value + 11;
2999 /* Convert the value from ascii to integer */
3000 ret = kstrtou8(value, 10, &ccxMode);
3001 if (ret < 0)
3002 {
3003 /* If the input value is greater than max value of datatype, then also
3004 kstrtou8 fails */
3005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3006 "%s: kstrtou8 failed range [%d - %d]", __func__,
3007 CFG_CCX_FEATURE_ENABLED_MIN,
3008 CFG_CCX_FEATURE_ENABLED_MAX);
3009 ret = -EINVAL;
3010 goto exit;
3011 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003012 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3013 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3014 {
3015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3016 "Ccx mode value %d is out of range"
3017 " (Min: %d Max: %d)", ccxMode,
3018 CFG_CCX_FEATURE_ENABLED_MIN,
3019 CFG_CCX_FEATURE_ENABLED_MAX);
3020 ret = -EINVAL;
3021 goto exit;
3022 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3024 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3025
3026 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3027 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3028 }
3029#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003030 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3031 {
3032 tANI_U8 *value = command;
3033 tANI_BOOLEAN roamScanControl = 0;
3034
3035 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3036 value = value + 19;
3037 /* Convert the value from ascii to integer */
3038 ret = kstrtou8(value, 10, &roamScanControl);
3039 if (ret < 0)
3040 {
3041 /* If the input value is greater than max value of datatype, then also
3042 kstrtou8 fails */
3043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3044 "%s: kstrtou8 failed ", __func__);
3045 ret = -EINVAL;
3046 goto exit;
3047 }
3048
3049 if (0 != roamScanControl)
3050 {
3051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3052 "roam scan control invalid value = %d",
3053 roamScanControl);
3054 ret = -EINVAL;
3055 goto exit;
3056 }
3057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3058 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3059
3060 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3061 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003062#ifdef FEATURE_WLAN_OKC
3063 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3064 {
3065 tANI_U8 *value = command;
3066 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3067
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003068 /* Check if the features OKC/CCX/11R are supported simultaneously,
3069 then this operation is not permitted (return FAILURE) */
3070 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3071 hdd_is_okc_mode_enabled(pHddCtx) &&
3072 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3073 {
3074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3075 "%s: OKC/CCX/11R are supported simultaneously"
3076 " hence this operation is not permitted!", __func__);
3077 ret = -EPERM;
3078 goto exit;
3079 }
3080
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003081 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3082 value = value + 11;
3083 /* Convert the value from ascii to integer */
3084 ret = kstrtou8(value, 10, &okcMode);
3085 if (ret < 0)
3086 {
3087 /* If the input value is greater than max value of datatype, then also
3088 kstrtou8 fails */
3089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3090 "%s: kstrtou8 failed range [%d - %d]", __func__,
3091 CFG_OKC_FEATURE_ENABLED_MIN,
3092 CFG_OKC_FEATURE_ENABLED_MAX);
3093 ret = -EINVAL;
3094 goto exit;
3095 }
3096
3097 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3098 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3099 {
3100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3101 "Okc mode value %d is out of range"
3102 " (Min: %d Max: %d)", okcMode,
3103 CFG_OKC_FEATURE_ENABLED_MIN,
3104 CFG_OKC_FEATURE_ENABLED_MAX);
3105 ret = -EINVAL;
3106 goto exit;
3107 }
3108
3109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3110 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3111
3112 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3113 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003114#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003115 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3116 {
3117 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3118 char extra[32];
3119 tANI_U8 len = 0;
3120
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003121 len = scnprintf(extra, sizeof(extra), "%s %d",
3122 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003123 if (copy_to_user(priv_data.buf, &extra, len + 1))
3124 {
3125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3126 "%s: failed to copy data to user buffer", __func__);
3127 ret = -EFAULT;
3128 goto exit;
3129 }
3130 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303131#ifdef WLAN_FEATURE_PACKET_FILTERING
3132 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3133 {
3134 tANI_U8 filterType = 0;
3135 tANI_U8 *value = command;
3136
3137 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3138 value = value + 22;
3139
3140 /* Convert the value from ascii to integer */
3141 ret = kstrtou8(value, 10, &filterType);
3142 if (ret < 0)
3143 {
3144 /* If the input value is greater than max value of datatype,
3145 * then also kstrtou8 fails
3146 */
3147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3148 "%s: kstrtou8 failed range ", __func__);
3149 ret = -EINVAL;
3150 goto exit;
3151 }
3152
3153 if (filterType != 0 && filterType != 1)
3154 {
3155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3156 "%s: Accepted Values are 0 and 1 ", __func__);
3157 ret = -EINVAL;
3158 goto exit;
3159 }
3160 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3161 pAdapter->sessionId);
3162 }
3163#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303164 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3165 {
3166 char *dhcpPhase;
3167 dhcpPhase = command + 12;
3168 if ('1' == *dhcpPhase)
3169 {
3170 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3171 pAdapter->macAddressCurrent.bytes);
3172 }
3173 else if ('2' == *dhcpPhase)
3174 {
3175 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3176 pAdapter->macAddressCurrent.bytes);
3177 }
3178 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003179 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3180 {
3181 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3182 }
3183 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3184 {
3185 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3186 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303187 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3188 {
3189 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3190 char extra[32];
3191 tANI_U8 len = 0;
3192
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003193 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303194 (int)pCfg->nActiveMaxChnTime);
3195 if (copy_to_user(priv_data.buf, &extra, len + 1))
3196 {
3197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3198 "%s: failed to copy data to user buffer", __func__);
3199 ret = -EFAULT;
3200 goto exit;
3201 }
3202 ret = len;
3203 }
3204 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3205 {
3206 tANI_U8 *value = command;
3207 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3208 int val = 0, temp;
3209
3210 value = value + 13;
3211 temp = kstrtou32(value, 10, &val);
3212 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3213 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3214 {
3215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3217 ret = -EFAULT;
3218 goto exit;
3219 }
3220 pCfg->nActiveMaxChnTime = val;
3221 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003222 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3223 {
3224 tANI_U8 filterType = 0;
3225 tANI_U8 *value;
3226 value = command + 9;
3227
3228 /* Convert the value from ascii to integer */
3229 ret = kstrtou8(value, 10, &filterType);
3230 if (ret < 0)
3231 {
3232 /* If the input value is greater than max value of datatype,
3233 * then also kstrtou8 fails
3234 */
3235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3236 "%s: kstrtou8 failed range ", __func__);
3237 ret = -EINVAL;
3238 goto exit;
3239 }
3240 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3241 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3242 {
3243 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3244 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3245 " 2-Sink ", __func__);
3246 ret = -EINVAL;
3247 goto exit;
3248 }
3249 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3250 pHddCtx->drvr_miracast = filterType;
3251 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3252 }
Leo Chang614d2072013-08-22 14:59:44 -07003253 else if (strncmp(command, "SETMCRATE", 9) == 0)
3254 {
Leo Chang614d2072013-08-22 14:59:44 -07003255 tANI_U8 *value = command;
3256 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003257 tSirRateUpdateInd *rateUpdate;
3258 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003259
3260 /* Only valid for SAP mode */
3261 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3262 {
3263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3264 "%s: SAP mode is not running", __func__);
3265 ret = -EFAULT;
3266 goto exit;
3267 }
3268
3269 /* Move pointer to ahead of SETMCRATE<delimiter> */
3270 /* input value is in units of hundred kbps */
3271 value = value + 10;
3272 /* Convert the value from ascii to integer, decimal base */
3273 ret = kstrtouint(value, 10, &targetRate);
3274
Leo Chang1f98cbd2013-10-17 15:03:52 -07003275 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3276 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003277 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003278 hddLog(VOS_TRACE_LEVEL_ERROR,
3279 "%s: SETMCRATE indication alloc fail", __func__);
3280 ret = -EFAULT;
3281 goto exit;
3282 }
3283 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3284
3285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3286 "MC Target rate %d", targetRate);
3287 /* Ignore unicast */
3288 rateUpdate->ucastDataRate = -1;
3289 rateUpdate->mcastDataRate24GHz = targetRate;
3290 rateUpdate->mcastDataRate5GHz = targetRate;
3291 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3292 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3293 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3294 if (eHAL_STATUS_SUCCESS != status)
3295 {
3296 hddLog(VOS_TRACE_LEVEL_ERROR,
3297 "%s: SET_MC_RATE failed", __func__);
3298 vos_mem_free(rateUpdate);
3299 ret = -EFAULT;
3300 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003301 }
3302 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303303#ifdef FEATURE_WLAN_BATCH_SCAN
3304 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3305 {
3306 char extra[32];
3307 tANI_U8 len = 0;
3308 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3309
3310 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3311 {
3312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3313 "%s: Batch scan feature is not supported by FW", __func__);
3314 ret = -EINVAL;
3315 goto exit;
3316 }
3317
3318 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3319 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3320 {
3321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3322 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3323 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3324 " mode",
3325 pAdapter->device_mode);
3326 ret = -EINVAL;
3327 goto exit;
3328 }
3329
Arif Hussain826d9412013-11-12 16:44:54 -08003330 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303331 version);
3332 if (copy_to_user(priv_data.buf, &extra, len + 1))
3333 {
3334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3335 "%s: failed to copy data to user buffer", __func__);
3336 ret = -EFAULT;
3337 goto exit;
3338 }
3339 ret = HDD_BATCH_SCAN_VERSION;
3340 }
3341 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3342 {
3343 int status;
3344 tANI_U8 *value = (command + 16);
3345 eHalStatus halStatus;
3346 unsigned long rc;
3347 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3348 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3349
3350 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3351 {
3352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3353 "%s: Batch scan feature is not supported by FW", __func__);
3354 ret = -EINVAL;
3355 goto exit;
3356 }
3357
Rajeev Kumar20140c12013-10-21 19:39:02 -07003358
Rajeev79dbe4c2013-10-05 11:03:42 +05303359 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3360 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3361 {
3362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003363 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303364 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3365 pAdapter->device_mode);
3366 ret = -EINVAL;
3367 goto exit;
3368 }
3369
Rajeev Kumar20140c12013-10-21 19:39:02 -07003370
Rajeev79dbe4c2013-10-05 11:03:42 +05303371 status = hdd_parse_set_batchscan_command(value, pReq);
3372 if (status)
3373 {
3374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003375 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303376 ret = -EINVAL;
3377 goto exit;
3378 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003379
3380
Rajeev79dbe4c2013-10-05 11:03:42 +05303381 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3382 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3383 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3384 pAdapter);
3385
3386 if ( eHAL_STATUS_SUCCESS == halStatus )
3387 {
3388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3389 "sme_SetBatchScanReq returned success halStatus %d",
3390 halStatus);
3391 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3392 {
3393 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3394 rc = wait_for_completion_timeout(
3395 &pAdapter->hdd_set_batch_scan_req_var,
3396 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3397 if (0 == rc)
3398 {
3399 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3400 "%s: Timeout waiting for set batch scan to complete",
3401 __func__);
3402 ret = -EINVAL;
3403 goto exit;
3404 }
3405 }
3406 if ( !pRsp->nScansToBatch )
3407 {
3408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3409 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003410 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303411 ret = -EINVAL;
3412 goto exit;
3413 }
3414 /*As per the Batch Scan Framework API we should return the MIN of
3415 either MSCAN or the max # of scans firmware can cache*/
3416 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3417
Rajeev Kumar20140c12013-10-21 19:39:02 -07003418 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3419
Rajeev79dbe4c2013-10-05 11:03:42 +05303420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3421 "%s: request MSCAN %d response MSCAN %d ret %d",
3422 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3423 }
3424 else
3425 {
3426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3427 "sme_SetBatchScanReq returned failure halStatus %d",
3428 halStatus);
3429 ret = -EINVAL;
3430 goto exit;
3431 }
3432 }
3433 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3434 {
3435 eHalStatus halStatus;
3436 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3437 pInd->param = 0;
3438
3439 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3440 {
3441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3442 "%s: Batch scan feature is not supported by FW", __func__);
3443 ret = -EINVAL;
3444 goto exit;
3445 }
3446
Rajeev Kumar20140c12013-10-21 19:39:02 -07003447 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303448 {
3449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003450 "Batch scan is not yet enabled batch scan state %d",
3451 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303452 ret = -EINVAL;
3453 goto exit;
3454 }
3455
Rajeev Kumar20140c12013-10-21 19:39:02 -07003456 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3457
Rajeev79dbe4c2013-10-05 11:03:42 +05303458 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3459 pAdapter->sessionId);
3460 if ( eHAL_STATUS_SUCCESS == halStatus )
3461 {
3462 ret = 0;
3463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3464 "sme_StopBatchScanInd returned success halStatus %d",
3465 halStatus);
3466 }
3467 else
3468 {
3469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3470 "sme_StopBatchScanInd returned failure halStatus %d",
3471 halStatus);
3472 ret = -EINVAL;
3473 goto exit;
3474 }
3475 }
3476 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3477 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003478 tANI_U32 remain_len;
3479
Rajeev79dbe4c2013-10-05 11:03:42 +05303480 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3481 {
3482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3483 "%s: Batch scan feature is not supported by FW", __func__);
3484 ret = -EINVAL;
3485 goto exit;
3486 }
3487
Rajeev Kumar20140c12013-10-21 19:39:02 -07003488 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303489 {
3490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003491 "Batch scan is not yet enabled could not return results"
3492 "Batch Scan state %d",
3493 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303494 ret = -EINVAL;
3495 goto exit;
3496 }
3497
3498 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003499 remain_len = priv_data.total_len - priv_data.used_len;
3500 if (remain_len < priv_data.total_len)
3501 {
3502 /*Clear previous batch scan response data if any*/
3503 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3504 }
3505 else
3506 {
3507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3508 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003509 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003510 priv_data.total_len, priv_data.used_len, remain_len);
3511 ret = -EINVAL;
3512 goto exit;
3513 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303514 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3515 }
3516#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003517#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3518 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3519 {
3520 tANI_U8 *value = command;
3521 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3522 tANI_U8 numChannels = 0;
3523 eHalStatus status = eHAL_STATUS_SUCCESS;
3524
3525 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3526 if (eHAL_STATUS_SUCCESS != status)
3527 {
3528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3529 "%s: Failed to parse channel list information", __func__);
3530 ret = -EINVAL;
3531 goto exit;
3532 }
3533
3534 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3535 {
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3537 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3538 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3539 ret = -EINVAL;
3540 goto exit;
3541 }
3542 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3543 ChannelList,
3544 numChannels);
3545 if (eHAL_STATUS_SUCCESS != status)
3546 {
3547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3548 "%s: Failed to update channel list information", __func__);
3549 ret = -EINVAL;
3550 goto exit;
3551 }
3552 }
3553 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3554 {
3555 tANI_U8 *value = command;
3556 char extra[128] = {0};
3557 int len = 0;
3558 tANI_U8 tid = 0;
3559 hdd_station_ctx_t *pHddStaCtx = NULL;
3560 tAniTrafStrmMetrics tsmMetrics;
3561 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3562
3563 /* if not associated, return error */
3564 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3565 {
3566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3567 ret = -EINVAL;
3568 goto exit;
3569 }
3570
3571 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3572 value = value + 12;
3573 /* Convert the value from ascii to integer */
3574 ret = kstrtou8(value, 10, &tid);
3575 if (ret < 0)
3576 {
3577 /* If the input value is greater than max value of datatype, then also
3578 kstrtou8 fails */
3579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3580 "%s: kstrtou8 failed range [%d - %d]", __func__,
3581 TID_MIN_VALUE,
3582 TID_MAX_VALUE);
3583 ret = -EINVAL;
3584 goto exit;
3585 }
3586
3587 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3588 {
3589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3590 "tid value %d is out of range"
3591 " (Min: %d Max: %d)", tid,
3592 TID_MIN_VALUE,
3593 TID_MAX_VALUE);
3594 ret = -EINVAL;
3595 goto exit;
3596 }
3597
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3599 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3600
3601 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3602 {
3603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3604 "%s: failed to get tsm stats", __func__);
3605 ret = -EFAULT;
3606 goto exit;
3607 }
3608
3609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3610 "UplinkPktQueueDly(%d)\n"
3611 "UplinkPktQueueDlyHist[0](%d)\n"
3612 "UplinkPktQueueDlyHist[1](%d)\n"
3613 "UplinkPktQueueDlyHist[2](%d)\n"
3614 "UplinkPktQueueDlyHist[3](%d)\n"
3615 "UplinkPktTxDly(%lu)\n"
3616 "UplinkPktLoss(%d)\n"
3617 "UplinkPktCount(%d)\n"
3618 "RoamingCount(%d)\n"
3619 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3620 tsmMetrics.UplinkPktQueueDlyHist[0],
3621 tsmMetrics.UplinkPktQueueDlyHist[1],
3622 tsmMetrics.UplinkPktQueueDlyHist[2],
3623 tsmMetrics.UplinkPktQueueDlyHist[3],
3624 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3625 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3626
3627 /* Output TSM stats is of the format
3628 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3629 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003630 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003631 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3632 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3633 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3634 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3635 tsmMetrics.RoamingDly);
3636
3637 if (copy_to_user(priv_data.buf, &extra, len + 1))
3638 {
3639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3640 "%s: failed to copy data to user buffer", __func__);
3641 ret = -EFAULT;
3642 goto exit;
3643 }
3644 }
3645 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3646 {
3647 tANI_U8 *value = command;
3648 tANI_U8 *cckmIe = NULL;
3649 tANI_U8 cckmIeLen = 0;
3650 eHalStatus status = eHAL_STATUS_SUCCESS;
3651
3652 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3653 if (eHAL_STATUS_SUCCESS != status)
3654 {
3655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3656 "%s: Failed to parse cckm ie data", __func__);
3657 ret = -EINVAL;
3658 goto exit;
3659 }
3660
3661 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3662 {
3663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3664 "%s: CCKM Ie input length is more than max[%d]", __func__,
3665 DOT11F_IE_RSN_MAX_LEN);
3666 if (NULL != cckmIe)
3667 {
3668 vos_mem_free(cckmIe);
3669 }
3670 ret = -EINVAL;
3671 goto exit;
3672 }
3673 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3674 if (NULL != cckmIe)
3675 {
3676 vos_mem_free(cckmIe);
3677 }
3678 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003679 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3680 {
3681 tANI_U8 *value = command;
3682 tCsrCcxBeaconReq ccxBcnReq;
3683 eHalStatus status = eHAL_STATUS_SUCCESS;
3684 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3685 if (eHAL_STATUS_SUCCESS != status)
3686 {
3687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3688 "%s: Failed to parse ccx beacon req", __func__);
3689 ret = -EINVAL;
3690 goto exit;
3691 }
3692
3693 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3694 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003695#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003696 else {
3697 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3698 __func__, command);
3699 }
3700
Jeff Johnson295189b2012-06-20 16:38:30 -07003701 }
3702exit:
3703 if (command)
3704 {
3705 kfree(command);
3706 }
3707 return ret;
3708}
3709
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003710
3711
3712#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003713/**---------------------------------------------------------------------------
3714
3715 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3716
3717 This function parses the ccx beacon request passed in the format
3718 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3719 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3720 <space>Scan Mode N<space>Meas Duration N
3721 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3722 then take N.
3723 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3724 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3725 This function does not take care of removing duplicate channels from the list
3726
3727 \param - pValue Pointer to data
3728 \param - pCcxBcnReq output pointer to store parsed ie information
3729
3730 \return - 0 for success non-zero for failure
3731
3732 --------------------------------------------------------------------------*/
3733static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3734 tCsrCcxBeaconReq *pCcxBcnReq)
3735{
3736 tANI_U8 *inPtr = pValue;
3737 int tempInt = 0;
3738 int j = 0, i = 0, v = 0;
3739 char buf[32];
3740
3741 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3742 /*no argument after the command*/
3743 if (NULL == inPtr)
3744 {
3745 return -EINVAL;
3746 }
3747 /*no space after the command*/
3748 else if (SPACE_ASCII_VALUE != *inPtr)
3749 {
3750 return -EINVAL;
3751 }
3752
3753 /*removing empty spaces*/
3754 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3755
3756 /*no argument followed by spaces*/
3757 if ('\0' == *inPtr) return -EINVAL;
3758
3759 /*getting the first argument ie measurement token*/
3760 v = sscanf(inPtr, "%32s ", buf);
3761 if (1 != v) return -EINVAL;
3762
3763 v = kstrtos32(buf, 10, &tempInt);
3764 if ( v < 0) return -EINVAL;
3765
3766 pCcxBcnReq->numBcnReqIe = tempInt;
3767
3768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3769 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3770
3771 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3772 {
3773 for (i = 0; i < 4; i++)
3774 {
3775 /*inPtr pointing to the beginning of first space after number of ie fields*/
3776 inPtr = strpbrk( inPtr, " " );
3777 /*no ie data after the number of ie fields argument*/
3778 if (NULL == inPtr) return -EINVAL;
3779
3780 /*removing empty space*/
3781 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3782
3783 /*no ie data after the number of ie fields argument and spaces*/
3784 if ( '\0' == *inPtr ) return -EINVAL;
3785
3786 v = sscanf(inPtr, "%32s ", buf);
3787 if (1 != v) return -EINVAL;
3788
3789 v = kstrtos32(buf, 10, &tempInt);
3790 if (v < 0) return -EINVAL;
3791
3792 switch (i)
3793 {
3794 case 0: /* Measurement token */
3795 if (tempInt <= 0)
3796 {
3797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3798 "Invalid Measurement Token(%d)", tempInt);
3799 return -EINVAL;
3800 }
3801 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3802 break;
3803
3804 case 1: /* Channel number */
3805 if ((tempInt <= 0) ||
3806 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3807 {
3808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3809 "Invalid Channel Number(%d)", tempInt);
3810 return -EINVAL;
3811 }
3812 pCcxBcnReq->bcnReq[j].channel = tempInt;
3813 break;
3814
3815 case 2: /* Scan mode */
3816 if ((tempInt < 0) || (tempInt > 2))
3817 {
3818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3819 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3820 return -EINVAL;
3821 }
3822 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3823 break;
3824
3825 case 3: /* Measurement duration */
3826 if (tempInt <= 0)
3827 {
3828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3829 "Invalid Measurement Duration(%d)", tempInt);
3830 return -EINVAL;
3831 }
3832 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3833 break;
3834 }
3835 }
3836 }
3837
3838 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3839 {
3840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3841 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3842 j,
3843 pCcxBcnReq->bcnReq[j].measurementToken,
3844 pCcxBcnReq->bcnReq[j].channel,
3845 pCcxBcnReq->bcnReq[j].scanMode,
3846 pCcxBcnReq->bcnReq[j].measurementDuration);
3847 }
3848
3849 return VOS_STATUS_SUCCESS;
3850}
3851
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003852static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3853{
3854 struct statsContext *pStatsContext = NULL;
3855 hdd_adapter_t *pAdapter = NULL;
3856
3857 if (NULL == pContext)
3858 {
3859 hddLog(VOS_TRACE_LEVEL_ERROR,
3860 "%s: Bad param, pContext [%p]",
3861 __func__, pContext);
3862 return;
3863 }
3864
3865 /* there is a race condition that exists between this callback function
3866 and the caller since the caller could time out either before or
3867 while this code is executing. we'll assume the timeout hasn't
3868 occurred, but we'll verify that right before we save our work */
3869
3870 pStatsContext = pContext;
3871 pAdapter = pStatsContext->pAdapter;
3872 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3873 {
3874 /* the caller presumably timed out so there is nothing we can do */
3875 hddLog(VOS_TRACE_LEVEL_WARN,
3876 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3877 __func__, pAdapter, pStatsContext->magic);
3878 return;
3879 }
3880
3881 /* the race is on. caller could have timed out immediately after
3882 we verified the magic, but if so, caller will wait a short time
3883 for us to copy over the tsm stats */
3884 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3885 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3886 tsmMetrics.UplinkPktQueueDlyHist,
3887 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3888 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3889 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3890 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3891 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3892 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3893 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3894
3895 /* and notify the caller */
3896 complete(&pStatsContext->completion);
3897}
3898
3899
3900
3901static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3902 tAniTrafStrmMetrics* pTsmMetrics)
3903{
3904 hdd_station_ctx_t *pHddStaCtx = NULL;
3905 eHalStatus hstatus;
3906 long lrc;
3907 struct statsContext context;
3908 hdd_context_t *pHddCtx = NULL;
3909
3910 if (NULL == pAdapter)
3911 {
3912 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3913 return VOS_STATUS_E_FAULT;
3914 }
3915
3916 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3917 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3918
3919 /* we are connected prepare our callback context */
3920 init_completion(&context.completion);
3921 context.pAdapter = pAdapter;
3922 context.magic = STATS_CONTEXT_MAGIC;
3923
3924 /* query tsm stats */
3925 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3926 pHddStaCtx->conn_info.staId[ 0 ],
3927 pHddStaCtx->conn_info.bssId,
3928 &context, pHddCtx->pvosContext, tid);
3929
3930 if (eHAL_STATUS_SUCCESS != hstatus)
3931 {
3932 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3933 return hstatus;
3934 }
3935 else
3936 {
3937 /* request was sent -- wait for the response */
3938 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3939 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3940 /* either we have a response or we timed out
3941 either way, first invalidate our magic */
3942 context.magic = 0;
3943 if (lrc <= 0)
3944 {
3945 hddLog(VOS_TRACE_LEVEL_ERROR,
3946 "%s: SME %s while retrieving statistics",
3947 __func__, (0 == lrc) ? "timeout" : "interrupt");
3948 /* there is a race condition such that the callback
3949 function could be executing at the same time we are. of
3950 primary concern is if the callback function had already
3951 verified the "magic" but hasn't yet set the completion
3952 variable. Since the completion variable is on our
3953 stack, we'll delay just a bit to make sure the data is
3954 still valid if that is the case */
3955 msleep(50);
3956 return (VOS_STATUS_E_TIMEOUT);
3957 }
3958 }
3959 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3960 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3961 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3962 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3963 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3964 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3965 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3966 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3967 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3968 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3969
3970 return VOS_STATUS_SUCCESS;
3971}
3972#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3973
Srinivas Girigowdade697412013-02-14 16:31:48 -08003974#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3975void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3976{
3977 eCsrBand band = -1;
3978 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3979 switch (band)
3980 {
3981 case eCSR_BAND_ALL:
3982 *pBand = WLAN_HDD_UI_BAND_AUTO;
3983 break;
3984
3985 case eCSR_BAND_24:
3986 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3987 break;
3988
3989 case eCSR_BAND_5G:
3990 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3991 break;
3992
3993 default:
3994 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3995 *pBand = -1;
3996 break;
3997 }
3998}
3999
4000/**---------------------------------------------------------------------------
4001
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004002 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4003
4004 This function parses the send action frame data passed in the format
4005 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4006
Srinivas Girigowda56076852013-08-20 14:00:50 -07004007 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004008 \param - pTargetApBssid Pointer to target Ap bssid
4009 \param - pChannel Pointer to the Target AP channel
4010 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4011 \param - pBuf Pointer to data
4012 \param - pBufLen Pointer to data length
4013
4014 \return - 0 for success non-zero for failure
4015
4016 --------------------------------------------------------------------------*/
4017VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4018 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4019{
4020 tANI_U8 *inPtr = pValue;
4021 tANI_U8 *dataEnd;
4022 int tempInt;
4023 int j = 0;
4024 int i = 0;
4025 int v = 0;
4026 tANI_U8 tempBuf[32];
4027 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004028 /* 12 hexa decimal digits and 5 ':' */
4029 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004030
4031 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4032 /*no argument after the command*/
4033 if (NULL == inPtr)
4034 {
4035 return -EINVAL;
4036 }
4037
4038 /*no space after the command*/
4039 else if (SPACE_ASCII_VALUE != *inPtr)
4040 {
4041 return -EINVAL;
4042 }
4043
4044 /*removing empty spaces*/
4045 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4046
4047 /*no argument followed by spaces*/
4048 if ('\0' == *inPtr)
4049 {
4050 return -EINVAL;
4051 }
4052
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004053 v = sscanf(inPtr, "%17s", macAddress);
4054 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004055 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4057 "Invalid MAC address or All hex inputs are not read (%d)", v);
4058 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004059 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004060
4061 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4062 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4063 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4064 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4065 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4066 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004067
4068 /* point to the next argument */
4069 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4070 /*no argument after the command*/
4071 if (NULL == inPtr) return -EINVAL;
4072
4073 /*removing empty spaces*/
4074 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4075
4076 /*no argument followed by spaces*/
4077 if ('\0' == *inPtr)
4078 {
4079 return -EINVAL;
4080 }
4081
4082 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004083 v = sscanf(inPtr, "%32s ", tempBuf);
4084 if (1 != v) return -EINVAL;
4085
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004086 v = kstrtos32(tempBuf, 10, &tempInt);
4087 if ( v < 0) return -EINVAL;
4088
4089 *pChannel = tempInt;
4090
4091 /* point to the next argument */
4092 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4093 /*no argument after the command*/
4094 if (NULL == inPtr) return -EINVAL;
4095 /*removing empty spaces*/
4096 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4097
4098 /*no argument followed by spaces*/
4099 if ('\0' == *inPtr)
4100 {
4101 return -EINVAL;
4102 }
4103
4104 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004105 v = sscanf(inPtr, "%32s ", tempBuf);
4106 if (1 != v) return -EINVAL;
4107
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004108 v = kstrtos32(tempBuf, 10, &tempInt);
4109 if ( v < 0) return -EINVAL;
4110
4111 *pDwellTime = tempInt;
4112
4113 /* point to the next argument */
4114 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4115 /*no argument after the command*/
4116 if (NULL == inPtr) return -EINVAL;
4117 /*removing empty spaces*/
4118 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4119
4120 /*no argument followed by spaces*/
4121 if ('\0' == *inPtr)
4122 {
4123 return -EINVAL;
4124 }
4125
4126 /* find the length of data */
4127 dataEnd = inPtr;
4128 while(('\0' != *dataEnd) )
4129 {
4130 dataEnd++;
4131 ++(*pBufLen);
4132 }
4133 if ( *pBufLen <= 0) return -EINVAL;
4134
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004135 /* Allocate the number of bytes based on the number of input characters
4136 whether it is even or odd.
4137 if the number of input characters are even, then we need N/2 byte.
4138 if the number of input characters are odd, then we need do (N+1)/2 to
4139 compensate rounding off.
4140 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4141 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4142 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004143 if (NULL == *pBuf)
4144 {
4145 hddLog(VOS_TRACE_LEVEL_FATAL,
4146 "%s: vos_mem_alloc failed ", __func__);
4147 return -EINVAL;
4148 }
4149
4150 /* the buffer received from the upper layer is character buffer,
4151 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4152 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4153 and f0 in 3rd location */
4154 for (i = 0, j = 0; j < *pBufLen; j += 2)
4155 {
4156 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4157 (*pBuf)[i++] = tempByte;
4158 }
4159 *pBufLen = i;
4160 return VOS_STATUS_SUCCESS;
4161}
4162
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004163/**---------------------------------------------------------------------------
4164
Srinivas Girigowdade697412013-02-14 16:31:48 -08004165 \brief hdd_parse_channellist() - HDD Parse channel list
4166
4167 This function parses the channel list passed in the format
4168 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004169 if the Number of channels (N) does not match with the actual number of channels passed
4170 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4171 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4172 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4173 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004174
4175 \param - pValue Pointer to input channel list
4176 \param - ChannelList Pointer to local output array to record channel list
4177 \param - pNumChannels Pointer to number of roam scan channels
4178
4179 \return - 0 for success non-zero for failure
4180
4181 --------------------------------------------------------------------------*/
4182VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4183{
4184 tANI_U8 *inPtr = pValue;
4185 int tempInt;
4186 int j = 0;
4187 int v = 0;
4188 char buf[32];
4189
4190 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4191 /*no argument after the command*/
4192 if (NULL == inPtr)
4193 {
4194 return -EINVAL;
4195 }
4196
4197 /*no space after the command*/
4198 else if (SPACE_ASCII_VALUE != *inPtr)
4199 {
4200 return -EINVAL;
4201 }
4202
4203 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004204 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004205
4206 /*no argument followed by spaces*/
4207 if ('\0' == *inPtr)
4208 {
4209 return -EINVAL;
4210 }
4211
4212 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004213 v = sscanf(inPtr, "%32s ", buf);
4214 if (1 != v) return -EINVAL;
4215
Srinivas Girigowdade697412013-02-14 16:31:48 -08004216 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004217 if ((v < 0) ||
4218 (tempInt <= 0) ||
4219 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4220 {
4221 return -EINVAL;
4222 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004223
4224 *pNumChannels = tempInt;
4225
4226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4227 "Number of channels are: %d", *pNumChannels);
4228
4229 for (j = 0; j < (*pNumChannels); j++)
4230 {
4231 /*inPtr pointing to the beginning of first space after number of channels*/
4232 inPtr = strpbrk( inPtr, " " );
4233 /*no channel list after the number of channels argument*/
4234 if (NULL == inPtr)
4235 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004236 if (0 != j)
4237 {
4238 *pNumChannels = j;
4239 return VOS_STATUS_SUCCESS;
4240 }
4241 else
4242 {
4243 return -EINVAL;
4244 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004245 }
4246
4247 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004248 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004249
4250 /*no channel list after the number of channels argument and spaces*/
4251 if ( '\0' == *inPtr )
4252 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004253 if (0 != j)
4254 {
4255 *pNumChannels = j;
4256 return VOS_STATUS_SUCCESS;
4257 }
4258 else
4259 {
4260 return -EINVAL;
4261 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004262 }
4263
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004264 v = sscanf(inPtr, "%32s ", buf);
4265 if (1 != v) return -EINVAL;
4266
Srinivas Girigowdade697412013-02-14 16:31:48 -08004267 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004268 if ((v < 0) ||
4269 (tempInt <= 0) ||
4270 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4271 {
4272 return -EINVAL;
4273 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004274 pChannelList[j] = tempInt;
4275
4276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4277 "Channel %d added to preferred channel list",
4278 pChannelList[j] );
4279 }
4280
Srinivas Girigowdade697412013-02-14 16:31:48 -08004281 return VOS_STATUS_SUCCESS;
4282}
4283
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004284
4285/**---------------------------------------------------------------------------
4286
4287 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4288
4289 This function parses the reasoc command data passed in the format
4290 REASSOC<space><bssid><space><channel>
4291
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004292 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004293 \param - pTargetApBssid Pointer to target Ap bssid
4294 \param - pChannel Pointer to the Target AP channel
4295
4296 \return - 0 for success non-zero for failure
4297
4298 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004299VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4300 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004301{
4302 tANI_U8 *inPtr = pValue;
4303 int tempInt;
4304 int v = 0;
4305 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004306 /* 12 hexa decimal digits and 5 ':' */
4307 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004308
4309 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4310 /*no argument after the command*/
4311 if (NULL == inPtr)
4312 {
4313 return -EINVAL;
4314 }
4315
4316 /*no space after the command*/
4317 else if (SPACE_ASCII_VALUE != *inPtr)
4318 {
4319 return -EINVAL;
4320 }
4321
4322 /*removing empty spaces*/
4323 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4324
4325 /*no argument followed by spaces*/
4326 if ('\0' == *inPtr)
4327 {
4328 return -EINVAL;
4329 }
4330
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004331 v = sscanf(inPtr, "%17s", macAddress);
4332 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004333 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4335 "Invalid MAC address or All hex inputs are not read (%d)", v);
4336 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004337 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004338
4339 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4340 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4341 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4342 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4343 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4344 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004345
4346 /* point to the next argument */
4347 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4348 /*no argument after the command*/
4349 if (NULL == inPtr) return -EINVAL;
4350
4351 /*removing empty spaces*/
4352 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4353
4354 /*no argument followed by spaces*/
4355 if ('\0' == *inPtr)
4356 {
4357 return -EINVAL;
4358 }
4359
4360 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004361 v = sscanf(inPtr, "%32s ", tempBuf);
4362 if (1 != v) return -EINVAL;
4363
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004364 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004365 if ((v < 0) ||
4366 (tempInt <= 0) ||
4367 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4368 {
4369 return -EINVAL;
4370 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004371
4372 *pChannel = tempInt;
4373 return VOS_STATUS_SUCCESS;
4374}
4375
4376#endif
4377
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004378#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4379/**---------------------------------------------------------------------------
4380
4381 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4382
4383 This function parses the SETCCKM IE command
4384 SETCCKMIE<space><ie data>
4385
4386 \param - pValue Pointer to input data
4387 \param - pCckmIe Pointer to output cckm Ie
4388 \param - pCckmIeLen Pointer to output cckm ie length
4389
4390 \return - 0 for success non-zero for failure
4391
4392 --------------------------------------------------------------------------*/
4393VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4394 tANI_U8 *pCckmIeLen)
4395{
4396 tANI_U8 *inPtr = pValue;
4397 tANI_U8 *dataEnd;
4398 int j = 0;
4399 int i = 0;
4400 tANI_U8 tempByte = 0;
4401
4402 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4403 /*no argument after the command*/
4404 if (NULL == inPtr)
4405 {
4406 return -EINVAL;
4407 }
4408
4409 /*no space after the command*/
4410 else if (SPACE_ASCII_VALUE != *inPtr)
4411 {
4412 return -EINVAL;
4413 }
4414
4415 /*removing empty spaces*/
4416 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4417
4418 /*no argument followed by spaces*/
4419 if ('\0' == *inPtr)
4420 {
4421 return -EINVAL;
4422 }
4423
4424 /* find the length of data */
4425 dataEnd = inPtr;
4426 while(('\0' != *dataEnd) )
4427 {
4428 dataEnd++;
4429 ++(*pCckmIeLen);
4430 }
4431 if ( *pCckmIeLen <= 0) return -EINVAL;
4432
4433 /* Allocate the number of bytes based on the number of input characters
4434 whether it is even or odd.
4435 if the number of input characters are even, then we need N/2 byte.
4436 if the number of input characters are odd, then we need do (N+1)/2 to
4437 compensate rounding off.
4438 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4439 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4440 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4441 if (NULL == *pCckmIe)
4442 {
4443 hddLog(VOS_TRACE_LEVEL_FATAL,
4444 "%s: vos_mem_alloc failed ", __func__);
4445 return -EINVAL;
4446 }
4447 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4448 /* the buffer received from the upper layer is character buffer,
4449 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4450 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4451 and f0 in 3rd location */
4452 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4453 {
4454 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4455 (*pCckmIe)[i++] = tempByte;
4456 }
4457 *pCckmIeLen = i;
4458
4459 return VOS_STATUS_SUCCESS;
4460}
4461#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4462
Jeff Johnson295189b2012-06-20 16:38:30 -07004463/**---------------------------------------------------------------------------
4464
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004465 \brief hdd_is_valid_mac_address() - Validate MAC address
4466
4467 This function validates whether the given MAC address is valid or not
4468 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4469 where X is the hexa decimal digit character and separated by ':'
4470 This algorithm works even if MAC address is not separated by ':'
4471
4472 This code checks given input string mac contains exactly 12 hexadecimal digits.
4473 and a separator colon : appears in the input string only after
4474 an even number of hex digits.
4475
4476 \param - pMacAddr pointer to the input MAC address
4477 \return - 1 for valid and 0 for invalid
4478
4479 --------------------------------------------------------------------------*/
4480
4481v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4482{
4483 int xdigit = 0;
4484 int separator = 0;
4485 while (*pMacAddr)
4486 {
4487 if (isxdigit(*pMacAddr))
4488 {
4489 xdigit++;
4490 }
4491 else if (':' == *pMacAddr)
4492 {
4493 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4494 break;
4495
4496 ++separator;
4497 }
4498 else
4499 {
4500 separator = -1;
4501 /* Invalid MAC found */
4502 return 0;
4503 }
4504 ++pMacAddr;
4505 }
4506 return (xdigit == 12 && (separator == 5 || separator == 0));
4507}
4508
4509/**---------------------------------------------------------------------------
4510
Jeff Johnson295189b2012-06-20 16:38:30 -07004511 \brief hdd_open() - HDD Open function
4512
4513 This is called in response to ifconfig up
4514
4515 \param - dev Pointer to net_device structure
4516
4517 \return - 0 for success non-zero for failure
4518
4519 --------------------------------------------------------------------------*/
4520int hdd_open (struct net_device *dev)
4521{
4522 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4523 hdd_context_t *pHddCtx;
4524 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4525 VOS_STATUS status;
4526 v_BOOL_t in_standby = TRUE;
4527
4528 if (NULL == pAdapter)
4529 {
4530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004531 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004532 return -ENODEV;
4533 }
4534
4535 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4536 if (NULL == pHddCtx)
4537 {
4538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004539 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 return -ENODEV;
4541 }
4542
4543 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4544 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4545 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004546 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4547 {
4548 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304549 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004550 in_standby = FALSE;
4551 break;
4552 }
4553 else
4554 {
4555 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4556 pAdapterNode = pNext;
4557 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004558 }
4559
4560 if (TRUE == in_standby)
4561 {
4562 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4563 {
4564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4565 "wlan out of power save", __func__);
4566 return -EINVAL;
4567 }
4568 }
4569
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004570 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004571 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4572 {
4573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004574 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004575 /* Enable TX queues only when we are connected */
4576 netif_tx_start_all_queues(dev);
4577 }
4578
4579 return 0;
4580}
4581
4582int hdd_mon_open (struct net_device *dev)
4583{
4584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4585
4586 if(pAdapter == NULL) {
4587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004588 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004589 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004590 }
4591
4592 netif_start_queue(dev);
4593
4594 return 0;
4595}
4596/**---------------------------------------------------------------------------
4597
4598 \brief hdd_stop() - HDD stop function
4599
4600 This is called in response to ifconfig down
4601
4602 \param - dev Pointer to net_device structure
4603
4604 \return - 0 for success non-zero for failure
4605
4606 --------------------------------------------------------------------------*/
4607
4608int hdd_stop (struct net_device *dev)
4609{
4610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4611 hdd_context_t *pHddCtx;
4612 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4613 VOS_STATUS status;
4614 v_BOOL_t enter_standby = TRUE;
4615
4616 ENTER();
4617
4618 if (NULL == pAdapter)
4619 {
4620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004621 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004622 return -ENODEV;
4623 }
4624
4625 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4626 if (NULL == pHddCtx)
4627 {
4628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004629 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 return -ENODEV;
4631 }
4632
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004633 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4635 netif_tx_disable(pAdapter->dev);
4636 netif_carrier_off(pAdapter->dev);
4637
4638
4639 /* SoftAP ifaces should never go in power save mode
4640 making sure same here. */
4641 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4642 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 )
4645 {
4646 /* SoftAP mode, so return from here */
4647 EXIT();
4648 return 0;
4649 }
4650
4651 /* Find if any iface is up then
4652 if any iface is up then can't put device to sleep/ power save mode. */
4653 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4654 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4655 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004656 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4657 {
4658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304659 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004660 enter_standby = FALSE;
4661 break;
4662 }
4663 else
4664 {
4665 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4666 pAdapterNode = pNext;
4667 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 }
4669
4670 if (TRUE == enter_standby)
4671 {
4672 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4673 "entering standby", __func__);
4674 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4675 {
4676 /*log and return success*/
4677 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4678 "wlan in power save", __func__);
4679 }
4680 }
4681
4682 EXIT();
4683 return 0;
4684}
4685
4686/**---------------------------------------------------------------------------
4687
4688 \brief hdd_uninit() - HDD uninit function
4689
4690 This is called during the netdev unregister to uninitialize all data
4691associated with the device
4692
4693 \param - dev Pointer to net_device structure
4694
4695 \return - void
4696
4697 --------------------------------------------------------------------------*/
4698static void hdd_uninit (struct net_device *dev)
4699{
4700 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4701
4702 ENTER();
4703
4704 do
4705 {
4706 if (NULL == pAdapter)
4707 {
4708 hddLog(VOS_TRACE_LEVEL_FATAL,
4709 "%s: NULL pAdapter", __func__);
4710 break;
4711 }
4712
4713 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4714 {
4715 hddLog(VOS_TRACE_LEVEL_FATAL,
4716 "%s: Invalid magic", __func__);
4717 break;
4718 }
4719
4720 if (NULL == pAdapter->pHddCtx)
4721 {
4722 hddLog(VOS_TRACE_LEVEL_FATAL,
4723 "%s: NULL pHddCtx", __func__);
4724 break;
4725 }
4726
4727 if (dev != pAdapter->dev)
4728 {
4729 hddLog(VOS_TRACE_LEVEL_FATAL,
4730 "%s: Invalid device reference", __func__);
4731 /* we haven't validated all cases so let this go for now */
4732 }
4733
4734 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4735
4736 /* after uninit our adapter structure will no longer be valid */
4737 pAdapter->dev = NULL;
4738 pAdapter->magic = 0;
4739 } while (0);
4740
4741 EXIT();
4742}
4743
4744/**---------------------------------------------------------------------------
4745
4746 \brief hdd_release_firmware() -
4747
4748 This function calls the release firmware API to free the firmware buffer.
4749
4750 \param - pFileName Pointer to the File Name.
4751 pCtx - Pointer to the adapter .
4752
4753
4754 \return - 0 for success, non zero for failure
4755
4756 --------------------------------------------------------------------------*/
4757
4758VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4759{
4760 VOS_STATUS status = VOS_STATUS_SUCCESS;
4761 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4762 ENTER();
4763
4764
4765 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4766
4767 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4768
4769 if(pHddCtx->fw) {
4770 release_firmware(pHddCtx->fw);
4771 pHddCtx->fw = NULL;
4772 }
4773 else
4774 status = VOS_STATUS_E_FAILURE;
4775 }
4776 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4777 if(pHddCtx->nv) {
4778 release_firmware(pHddCtx->nv);
4779 pHddCtx->nv = NULL;
4780 }
4781 else
4782 status = VOS_STATUS_E_FAILURE;
4783
4784 }
4785
4786 EXIT();
4787 return status;
4788}
4789
4790/**---------------------------------------------------------------------------
4791
4792 \brief hdd_request_firmware() -
4793
4794 This function reads the firmware file using the request firmware
4795 API and returns the the firmware data and the firmware file size.
4796
4797 \param - pfileName - Pointer to the file name.
4798 - pCtx - Pointer to the adapter .
4799 - ppfw_data - Pointer to the pointer of the firmware data.
4800 - pSize - Pointer to the file size.
4801
4802 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4803
4804 --------------------------------------------------------------------------*/
4805
4806
4807VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4808{
4809 int status;
4810 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4811 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4812 ENTER();
4813
4814 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4815
4816 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4817
4818 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4819 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4820 __func__, pfileName);
4821 retval = VOS_STATUS_E_FAILURE;
4822 }
4823
4824 else {
4825 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4826 *pSize = pHddCtx->fw->size;
4827 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4828 __func__, *pSize);
4829 }
4830 }
4831 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4832
4833 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4834
4835 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4837 __func__, pfileName);
4838 retval = VOS_STATUS_E_FAILURE;
4839 }
4840
4841 else {
4842 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4843 *pSize = pHddCtx->nv->size;
4844 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4845 __func__, *pSize);
4846 }
4847 }
4848
4849 EXIT();
4850 return retval;
4851}
4852/**---------------------------------------------------------------------------
4853 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4854
4855 This is the function invoked by SME to inform the result of a full power
4856 request issued by HDD
4857
4858 \param - callbackcontext - Pointer to cookie
4859 status - result of request
4860
4861 \return - None
4862
4863--------------------------------------------------------------------------*/
4864void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4865{
4866 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4867
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004868 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 if(&pHddCtx->full_pwr_comp_var)
4870 {
4871 complete(&pHddCtx->full_pwr_comp_var);
4872 }
4873}
4874
4875/**---------------------------------------------------------------------------
4876
4877 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4878
4879 This is the function invoked by SME to inform the result of BMPS
4880 request issued by HDD
4881
4882 \param - callbackcontext - Pointer to cookie
4883 status - result of request
4884
4885 \return - None
4886
4887--------------------------------------------------------------------------*/
4888void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4889{
4890
4891 struct completion *completion_var = (struct completion*) callbackContext;
4892
4893 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4894 if(completion_var != NULL)
4895 {
4896 complete(completion_var);
4897 }
4898}
4899
4900/**---------------------------------------------------------------------------
4901
4902 \brief hdd_get_cfg_file_size() -
4903
4904 This function reads the configuration file using the request firmware
4905 API and returns the configuration file size.
4906
4907 \param - pCtx - Pointer to the adapter .
4908 - pFileName - Pointer to the file name.
4909 - pBufSize - Pointer to the buffer size.
4910
4911 \return - 0 for success, non zero for failure
4912
4913 --------------------------------------------------------------------------*/
4914
4915VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4916{
4917 int status;
4918 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4919
4920 ENTER();
4921
4922 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4923
4924 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4926 status = VOS_STATUS_E_FAILURE;
4927 }
4928 else {
4929 *pBufSize = pHddCtx->fw->size;
4930 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4931 release_firmware(pHddCtx->fw);
4932 pHddCtx->fw = NULL;
4933 }
4934
4935 EXIT();
4936 return VOS_STATUS_SUCCESS;
4937}
4938
4939/**---------------------------------------------------------------------------
4940
4941 \brief hdd_read_cfg_file() -
4942
4943 This function reads the configuration file using the request firmware
4944 API and returns the cfg data and the buffer size of the configuration file.
4945
4946 \param - pCtx - Pointer to the adapter .
4947 - pFileName - Pointer to the file name.
4948 - pBuffer - Pointer to the data buffer.
4949 - pBufSize - Pointer to the buffer size.
4950
4951 \return - 0 for success, non zero for failure
4952
4953 --------------------------------------------------------------------------*/
4954
4955VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4956 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4957{
4958 int status;
4959 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4960
4961 ENTER();
4962
4963 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4964
4965 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4967 return VOS_STATUS_E_FAILURE;
4968 }
4969 else {
4970 if(*pBufSize != pHddCtx->fw->size) {
4971 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4972 "file size", __func__);
4973 release_firmware(pHddCtx->fw);
4974 pHddCtx->fw = NULL;
4975 return VOS_STATUS_E_FAILURE;
4976 }
4977 else {
4978 if(pBuffer) {
4979 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4980 }
4981 release_firmware(pHddCtx->fw);
4982 pHddCtx->fw = NULL;
4983 }
4984 }
4985
4986 EXIT();
4987
4988 return VOS_STATUS_SUCCESS;
4989}
4990
4991/**---------------------------------------------------------------------------
4992
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 \brief hdd_set_mac_address() -
4994
4995 This function sets the user specified mac address using
4996 the command ifconfig wlanX hw ether <mac adress>.
4997
4998 \param - dev - Pointer to the net device.
4999 - addr - Pointer to the sockaddr.
5000 \return - 0 for success, non zero for failure
5001
5002 --------------------------------------------------------------------------*/
5003
5004static int hdd_set_mac_address(struct net_device *dev, void *addr)
5005{
5006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5007 struct sockaddr *psta_mac_addr = addr;
5008 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5009
5010 ENTER();
5011
5012 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5013
5014#ifdef HDD_SESSIONIZE
5015 // set the MAC address though the STA ID CFG.
5016 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5017 (v_U8_t *)&pAdapter->macAddressCurrent,
5018 sizeof( pAdapter->macAddressCurrent ),
5019 hdd_set_mac_addr_cb, VOS_FALSE );
5020#endif
5021
5022 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5023
5024 EXIT();
5025 return halStatus;
5026}
5027
5028tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5029{
5030 int i;
5031 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5032 {
5033 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5034 break;
5035 }
5036
5037 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5038 return NULL;
5039
5040 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5041 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5042}
5043
5044void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5045{
5046 int i;
5047 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5048 {
5049 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5050 {
5051 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5052 break;
5053 }
5054 }
5055 return;
5056}
5057
5058#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5059 static struct net_device_ops wlan_drv_ops = {
5060 .ndo_open = hdd_open,
5061 .ndo_stop = hdd_stop,
5062 .ndo_uninit = hdd_uninit,
5063 .ndo_start_xmit = hdd_hard_start_xmit,
5064 .ndo_tx_timeout = hdd_tx_timeout,
5065 .ndo_get_stats = hdd_stats,
5066 .ndo_do_ioctl = hdd_ioctl,
5067 .ndo_set_mac_address = hdd_set_mac_address,
5068 .ndo_select_queue = hdd_select_queue,
5069#ifdef WLAN_FEATURE_PACKET_FILTERING
5070#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5071 .ndo_set_rx_mode = hdd_set_multicast_list,
5072#else
5073 .ndo_set_multicast_list = hdd_set_multicast_list,
5074#endif //LINUX_VERSION_CODE
5075#endif
5076 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 static struct net_device_ops wlan_mon_drv_ops = {
5078 .ndo_open = hdd_mon_open,
5079 .ndo_stop = hdd_stop,
5080 .ndo_uninit = hdd_uninit,
5081 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5082 .ndo_tx_timeout = hdd_tx_timeout,
5083 .ndo_get_stats = hdd_stats,
5084 .ndo_do_ioctl = hdd_ioctl,
5085 .ndo_set_mac_address = hdd_set_mac_address,
5086 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005087
5088#endif
5089
5090void hdd_set_station_ops( struct net_device *pWlanDev )
5091{
5092#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005093 pWlanDev->netdev_ops = &wlan_drv_ops;
5094#else
5095 pWlanDev->open = hdd_open;
5096 pWlanDev->stop = hdd_stop;
5097 pWlanDev->uninit = hdd_uninit;
5098 pWlanDev->hard_start_xmit = NULL;
5099 pWlanDev->tx_timeout = hdd_tx_timeout;
5100 pWlanDev->get_stats = hdd_stats;
5101 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 pWlanDev->set_mac_address = hdd_set_mac_address;
5103#endif
5104}
5105
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005106static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005107{
5108 struct net_device *pWlanDev = NULL;
5109 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 /*
5111 * cfg80211 initialization and registration....
5112 */
5113 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5114
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 if(pWlanDev != NULL)
5116 {
5117
5118 //Save the pointer to the net_device in the HDD adapter
5119 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5120
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5122
5123 pAdapter->dev = pWlanDev;
5124 pAdapter->pHddCtx = pHddCtx;
5125 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5126
5127 init_completion(&pAdapter->session_open_comp_var);
5128 init_completion(&pAdapter->session_close_comp_var);
5129 init_completion(&pAdapter->disconnect_comp_var);
5130 init_completion(&pAdapter->linkup_event_var);
5131 init_completion(&pAdapter->cancel_rem_on_chan_var);
5132 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005133#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5134 init_completion(&pAdapter->offchannel_tx_event);
5135#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005137#ifdef FEATURE_WLAN_TDLS
5138 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005139 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005140 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305141 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005142#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 init_completion(&pHddCtx->mc_sus_event_var);
5144 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305145 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005146 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005147 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005148
Rajeev79dbe4c2013-10-05 11:03:42 +05305149#ifdef FEATURE_WLAN_BATCH_SCAN
5150 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5151 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5152 pAdapter->pBatchScanRsp = NULL;
5153 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005154 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05305155 mutex_init(&pAdapter->hdd_batch_scan_lock);
5156#endif
5157
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 pAdapter->isLinkUpSvcNeeded = FALSE;
5159 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5160 //Init the net_device structure
5161 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5162
5163 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5164 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5165 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5166 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5167
5168 hdd_set_station_ops( pAdapter->dev );
5169
5170 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5172 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5173 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005174 /* set pWlanDev's parent to underlying device */
5175 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5176 }
5177
5178 return pAdapter;
5179}
5180
5181VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5182{
5183 struct net_device *pWlanDev = pAdapter->dev;
5184 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5185 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5186 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5187
5188 if( rtnl_lock_held )
5189 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005190 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5192 {
5193 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5194 return VOS_STATUS_E_FAILURE;
5195 }
5196 }
5197 if (register_netdevice(pWlanDev))
5198 {
5199 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5200 return VOS_STATUS_E_FAILURE;
5201 }
5202 }
5203 else
5204 {
5205 if(register_netdev(pWlanDev))
5206 {
5207 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5208 return VOS_STATUS_E_FAILURE;
5209 }
5210 }
5211 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5212
5213 return VOS_STATUS_SUCCESS;
5214}
5215
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005216static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005217{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005218 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005219
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005220 if (NULL == pAdapter)
5221 {
5222 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5223 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005224 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005225
5226 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5227 {
5228 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5229 return eHAL_STATUS_NOT_INITIALIZED;
5230 }
5231
5232 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5233
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005234#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005235 /* need to make sure all of our scheduled work has completed.
5236 * This callback is called from MC thread context, so it is safe to
5237 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005238 *
5239 * Even though this is called from MC thread context, if there is a faulty
5240 * work item in the system, that can hang this call forever. So flushing
5241 * this global work queue is not safe; and now we make sure that
5242 * individual work queues are stopped correctly. But the cancel work queue
5243 * is a GPL only API, so the proprietary version of the driver would still
5244 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005245 */
5246 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005247#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005248
5249 /* We can be blocked while waiting for scheduled work to be
5250 * flushed, and the adapter structure can potentially be freed, in
5251 * which case the magic will have been reset. So make sure the
5252 * magic is still good, and hence the adapter structure is still
5253 * valid, before signaling completion */
5254 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5255 {
5256 complete(&pAdapter->session_close_comp_var);
5257 }
5258
Jeff Johnson295189b2012-06-20 16:38:30 -07005259 return eHAL_STATUS_SUCCESS;
5260}
5261
5262VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5263{
5264 struct net_device *pWlanDev = pAdapter->dev;
5265 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5266 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5267 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5268 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5269 int rc = 0;
5270
5271 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005272 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 //Open a SME session for future operation
5274 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005275 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005276 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5277 {
5278 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005279 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005280 halStatus, halStatus );
5281 status = VOS_STATUS_E_FAILURE;
5282 goto error_sme_open;
5283 }
5284
5285 //Block on a completion variable. Can't wait forever though.
5286 rc = wait_for_completion_interruptible_timeout(
5287 &pAdapter->session_open_comp_var,
5288 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5289 if (!rc)
5290 {
5291 hddLog(VOS_TRACE_LEVEL_FATAL,
5292 "Session is not opened within timeout period code %08d", rc );
5293 status = VOS_STATUS_E_FAILURE;
5294 goto error_sme_open;
5295 }
5296
5297 // Register wireless extensions
5298 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005301 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005302 halStatus, halStatus );
5303 status = VOS_STATUS_E_FAILURE;
5304 goto error_register_wext;
5305 }
5306 //Safe to register the hard_start_xmit function again
5307#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5308 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5309#else
5310 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5311#endif
5312
5313 //Set the Connection State to Not Connected
5314 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5315
5316 //Set the default operation channel
5317 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5318
5319 /* Make the default Auth Type as OPEN*/
5320 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5321
5322 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5323 {
5324 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005325 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005326 status, status );
5327 goto error_init_txrx;
5328 }
5329
5330 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5331
5332 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5333 {
5334 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005335 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005336 status, status );
5337 goto error_wmm_init;
5338 }
5339
5340 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5341
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005342#ifdef FEATURE_WLAN_TDLS
5343 if(0 != wlan_hdd_tdls_init(pAdapter))
5344 {
5345 status = VOS_STATUS_E_FAILURE;
5346 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5347 goto error_tdls_init;
5348 }
5349 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5350#endif
5351
Jeff Johnson295189b2012-06-20 16:38:30 -07005352 return VOS_STATUS_SUCCESS;
5353
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005354#ifdef FEATURE_WLAN_TDLS
5355error_tdls_init:
5356 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5357 hdd_wmm_adapter_close(pAdapter);
5358#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005359error_wmm_init:
5360 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5361 hdd_deinit_tx_rx(pAdapter);
5362error_init_txrx:
5363 hdd_UnregisterWext(pWlanDev);
5364error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005365 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005366 {
5367 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005368 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005369 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005370 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005371 {
5372 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005373 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005375 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 }
5377}
5378error_sme_open:
5379 return status;
5380}
5381
Jeff Johnson295189b2012-06-20 16:38:30 -07005382void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5383{
5384 hdd_cfg80211_state_t *cfgState;
5385
5386 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5387
5388 if( NULL != cfgState->buf )
5389 {
5390 int rc;
5391 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5392 rc = wait_for_completion_interruptible_timeout(
5393 &pAdapter->tx_action_cnf_event,
5394 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5395 if(!rc)
5396 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005398 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5399 }
5400 }
5401 return;
5402}
Jeff Johnson295189b2012-06-20 16:38:30 -07005403
5404void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5405{
5406 ENTER();
5407 switch ( pAdapter->device_mode )
5408 {
5409 case WLAN_HDD_INFRA_STATION:
5410 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005411 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 {
5413 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5414 {
5415 hdd_deinit_tx_rx( pAdapter );
5416 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5417 }
5418
5419 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5420 {
5421 hdd_wmm_adapter_close( pAdapter );
5422 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5423 }
5424
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005426#ifdef FEATURE_WLAN_TDLS
5427 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5428 {
5429 wlan_hdd_tdls_exit(pAdapter);
5430 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5431 }
5432#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005433
5434 break;
5435 }
5436
5437 case WLAN_HDD_SOFTAP:
5438 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305440
5441 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5442 {
5443 hdd_wmm_adapter_close( pAdapter );
5444 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5445 }
5446
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005448
5449 hdd_unregister_hostapd(pAdapter);
5450 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 break;
5453 }
5454
5455 case WLAN_HDD_MONITOR:
5456 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5459 {
5460 hdd_deinit_tx_rx( pAdapter );
5461 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5462 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 if(NULL != pAdapterforTx)
5464 {
5465 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005467 break;
5468 }
5469
5470
5471 default:
5472 break;
5473 }
5474
5475 EXIT();
5476}
5477
5478void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5479{
5480 struct net_device *pWlanDev = pAdapter->dev;
5481
Rajeev79dbe4c2013-10-05 11:03:42 +05305482#ifdef FEATURE_WLAN_BATCH_SCAN
5483 tHddBatchScanRsp *pNode;
5484 tHddBatchScanRsp *pPrev;
5485 if (pAdapter)
5486 {
5487 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5488 pNode = pAdapter->pBatchScanRsp;
5489 while (pNode)
5490 {
5491 pPrev = pNode;
5492 pNode = pNode->pNext;
5493 vos_mem_free((v_VOID_t * )pPrev);
5494 }
5495 pAdapter->pBatchScanRsp = NULL;
5496 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5497 }
5498#endif
5499
Jeff Johnson295189b2012-06-20 16:38:30 -07005500 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5501 if( rtnl_held )
5502 {
5503 unregister_netdevice(pWlanDev);
5504 }
5505 else
5506 {
5507 unregister_netdev(pWlanDev);
5508 }
5509 // note that the pAdapter is no longer valid at this point
5510 // since the memory has been reclaimed
5511 }
5512
5513}
5514
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005515void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5516{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305517 VOS_STATUS status;
5518 hdd_adapter_t *pAdapter = NULL;
5519 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005520
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305521 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005522
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305523 /*loop through all adapters.*/
5524 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005525 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305526 pAdapter = pAdapterNode->pAdapter;
5527 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5528 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005529
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305530 { // we skip this registration for modes other than STA and P2P client modes.
5531 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5532 pAdapterNode = pNext;
5533 continue;
5534 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005535
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305536 //Apply Dynamic DTIM For P2P
5537 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5538 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5539 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5540 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5541 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5542 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5543 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5544 (eConnectionState_Associated ==
5545 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5546 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5547 {
5548 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005549
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305550 powerRequest.uIgnoreDTIM = 1;
5551 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5552
5553 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5554 {
5555 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5556 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5557 }
5558 else
5559 {
5560 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5561 }
5562
5563 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5564 * specified during Enter/Exit BMPS when LCD off*/
5565 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5566 NULL, eANI_BOOLEAN_FALSE);
5567 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5568 NULL, eANI_BOOLEAN_FALSE);
5569
5570 /* switch to the DTIM specified in cfg.ini */
5571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5572 "Switch to DTIM %d", powerRequest.uListenInterval);
5573 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5574 break;
5575
5576 }
5577
5578 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5579 pAdapterNode = pNext;
5580 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005581}
5582
5583void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5584{
5585 /*Switch back to DTIM 1*/
5586 tSirSetPowerParamsReq powerRequest = { 0 };
5587
5588 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5589 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005590 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005591
5592 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5593 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5594 NULL, eANI_BOOLEAN_FALSE);
5595 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5596 NULL, eANI_BOOLEAN_FALSE);
5597
5598 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5599 "Switch to DTIM%d",powerRequest.uListenInterval);
5600 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5601
5602}
5603
Jeff Johnson295189b2012-06-20 16:38:30 -07005604VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5605{
5606 VOS_STATUS status = VOS_STATUS_SUCCESS;
5607
5608 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5609 {
5610 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5611 }
5612
5613 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5614 {
5615 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5616 }
5617
5618 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5619 {
5620 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5621 }
5622
5623 return status;
5624}
5625
5626VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5627{
5628 hdd_adapter_t *pAdapter = NULL;
5629 eHalStatus halStatus;
5630 VOS_STATUS status = VOS_STATUS_E_INVAL;
5631 v_BOOL_t disableBmps = FALSE;
5632 v_BOOL_t disableImps = FALSE;
5633
5634 switch(session_type)
5635 {
5636 case WLAN_HDD_INFRA_STATION:
5637 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005638 case WLAN_HDD_P2P_CLIENT:
5639 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005640 //Exit BMPS -> Is Sta/P2P Client is already connected
5641 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5642 if((NULL != pAdapter)&&
5643 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5644 {
5645 disableBmps = TRUE;
5646 }
5647
5648 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5649 if((NULL != pAdapter)&&
5650 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5651 {
5652 disableBmps = TRUE;
5653 }
5654
5655 //Exit both Bmps and Imps incase of Go/SAP Mode
5656 if((WLAN_HDD_SOFTAP == session_type) ||
5657 (WLAN_HDD_P2P_GO == session_type))
5658 {
5659 disableBmps = TRUE;
5660 disableImps = TRUE;
5661 }
5662
5663 if(TRUE == disableImps)
5664 {
5665 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5666 {
5667 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5668 }
5669 }
5670
5671 if(TRUE == disableBmps)
5672 {
5673 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5674 {
5675 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5676
5677 if(eHAL_STATUS_SUCCESS != halStatus)
5678 {
5679 status = VOS_STATUS_E_FAILURE;
5680 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5681 VOS_ASSERT(0);
5682 return status;
5683 }
5684 }
5685
5686 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5687 {
5688 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5689
5690 if(eHAL_STATUS_SUCCESS != halStatus)
5691 {
5692 status = VOS_STATUS_E_FAILURE;
5693 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5694 VOS_ASSERT(0);
5695 return status;
5696 }
5697 }
5698 }
5699
5700 if((TRUE == disableBmps) ||
5701 (TRUE == disableImps))
5702 {
5703 /* Now, get the chip into Full Power now */
5704 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5705 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5706 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5707
5708 if(halStatus != eHAL_STATUS_SUCCESS)
5709 {
5710 if(halStatus == eHAL_STATUS_PMC_PENDING)
5711 {
5712 //Block on a completion variable. Can't wait forever though
5713 wait_for_completion_interruptible_timeout(
5714 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5715 }
5716 else
5717 {
5718 status = VOS_STATUS_E_FAILURE;
5719 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5720 VOS_ASSERT(0);
5721 return status;
5722 }
5723 }
5724
5725 status = VOS_STATUS_SUCCESS;
5726 }
5727
5728 break;
5729 }
5730 return status;
5731}
5732
5733hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005734 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005735 tANI_U8 rtnl_held )
5736{
5737 hdd_adapter_t *pAdapter = NULL;
5738 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5739 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5740 VOS_STATUS exitbmpsStatus;
5741
5742 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5743
5744 //Disable BMPS incase of Concurrency
5745 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5746
5747 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5748 {
5749 //Fail to Exit BMPS
5750 VOS_ASSERT(0);
5751 return NULL;
5752 }
5753
5754 switch(session_type)
5755 {
5756 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005757 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005758 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 {
5760 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5761
5762 if( NULL == pAdapter )
5763 return NULL;
5764
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305765#ifdef FEATURE_WLAN_TDLS
5766 /* A Mutex Lock is introduced while changing/initializing the mode to
5767 * protect the concurrent access for the Adapters by TDLS module.
5768 */
5769 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5770 {
5771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5772 "%s: unable to lock list", __func__);
5773 return NULL;
5774 }
5775#endif
5776
Jeff Johnsone7245742012-09-05 17:12:55 -07005777 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5778 NL80211_IFTYPE_P2P_CLIENT:
5779 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005780
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 pAdapter->device_mode = session_type;
5782
5783 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305784#ifdef FEATURE_WLAN_TDLS
5785 mutex_unlock(&pHddCtx->tdls_lock);
5786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 if( VOS_STATUS_SUCCESS != status )
5788 goto err_free_netdev;
5789
5790 status = hdd_register_interface( pAdapter, rtnl_held );
5791 if( VOS_STATUS_SUCCESS != status )
5792 {
5793 hdd_deinit_adapter(pHddCtx, pAdapter);
5794 goto err_free_netdev;
5795 }
5796 //Stop the Interface TX queue.
5797 netif_tx_disable(pAdapter->dev);
5798 //netif_tx_disable(pWlanDev);
5799 netif_carrier_off(pAdapter->dev);
5800
5801 break;
5802 }
5803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 case WLAN_HDD_SOFTAP:
5806 {
5807 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5808 if( NULL == pAdapter )
5809 return NULL;
5810
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5812 NL80211_IFTYPE_AP:
5813 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 pAdapter->device_mode = session_type;
5815
5816 status = hdd_init_ap_mode(pAdapter);
5817 if( VOS_STATUS_SUCCESS != status )
5818 goto err_free_netdev;
5819
5820 status = hdd_register_hostapd( pAdapter, rtnl_held );
5821 if( VOS_STATUS_SUCCESS != status )
5822 {
5823 hdd_deinit_adapter(pHddCtx, pAdapter);
5824 goto err_free_netdev;
5825 }
5826
5827 netif_tx_disable(pAdapter->dev);
5828 netif_carrier_off(pAdapter->dev);
5829
5830 hdd_set_conparam( 1 );
5831 break;
5832 }
5833 case WLAN_HDD_MONITOR:
5834 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005835 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5836 if( NULL == pAdapter )
5837 return NULL;
5838
5839 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5840 pAdapter->device_mode = session_type;
5841 status = hdd_register_interface( pAdapter, rtnl_held );
5842#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5843 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5844#else
5845 pAdapter->dev->open = hdd_mon_open;
5846 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5847#endif
5848 hdd_init_tx_rx( pAdapter );
5849 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5850 //Set adapter to be used for data tx. It will use either GO or softap.
5851 pAdapter->sessionCtx.monitor.pAdapterForTx =
5852 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5854 {
5855 pAdapter->sessionCtx.monitor.pAdapterForTx =
5856 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5857 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 /* This workqueue will be used to transmit management packet over
5859 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005860 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5861 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5862 return NULL;
5863 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005864
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5866 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 }
5868 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 case WLAN_HDD_FTM:
5870 {
5871 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5872
5873 if( NULL == pAdapter )
5874 return NULL;
5875 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5876 * message while loading driver in FTM mode. */
5877 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5878 pAdapter->device_mode = session_type;
5879 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305880
5881 hdd_init_tx_rx( pAdapter );
5882
5883 //Stop the Interface TX queue.
5884 netif_tx_disable(pAdapter->dev);
5885 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 }
5887 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 default:
5889 {
5890 VOS_ASSERT(0);
5891 return NULL;
5892 }
5893 }
5894
5895
5896 if( VOS_STATUS_SUCCESS == status )
5897 {
5898 //Add it to the hdd's session list.
5899 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5900 if( NULL == pHddAdapterNode )
5901 {
5902 status = VOS_STATUS_E_NOMEM;
5903 }
5904 else
5905 {
5906 pHddAdapterNode->pAdapter = pAdapter;
5907 status = hdd_add_adapter_back ( pHddCtx,
5908 pHddAdapterNode );
5909 }
5910 }
5911
5912 if( VOS_STATUS_SUCCESS != status )
5913 {
5914 if( NULL != pAdapter )
5915 {
5916 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5917 pAdapter = NULL;
5918 }
5919 if( NULL != pHddAdapterNode )
5920 {
5921 vos_mem_free( pHddAdapterNode );
5922 }
5923
5924 goto resume_bmps;
5925 }
5926
5927 if(VOS_STATUS_SUCCESS == status)
5928 {
5929 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5930
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005931 //Initialize the WoWL service
5932 if(!hdd_init_wowl(pAdapter))
5933 {
5934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5935 goto err_free_netdev;
5936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 return pAdapter;
5939
5940err_free_netdev:
5941 free_netdev(pAdapter->dev);
5942 wlan_hdd_release_intf_addr( pHddCtx,
5943 pAdapter->macAddressCurrent.bytes );
5944
5945resume_bmps:
5946 //If bmps disabled enable it
5947 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5948 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305949 if (pHddCtx->hdd_wlan_suspended)
5950 {
5951 hdd_set_pwrparams(pHddCtx);
5952 }
5953 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 }
5955 return NULL;
5956}
5957
5958VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5959 tANI_U8 rtnl_held )
5960{
5961 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5962 VOS_STATUS status;
5963
5964 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5965 if( VOS_STATUS_SUCCESS != status )
5966 return status;
5967
5968 while ( pCurrent->pAdapter != pAdapter )
5969 {
5970 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5971 if( VOS_STATUS_SUCCESS != status )
5972 break;
5973
5974 pCurrent = pNext;
5975 }
5976 pAdapterNode = pCurrent;
5977 if( VOS_STATUS_SUCCESS == status )
5978 {
5979 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5980 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305981
5982#ifdef FEATURE_WLAN_TDLS
5983
5984 /* A Mutex Lock is introduced while changing/initializing the mode to
5985 * protect the concurrent access for the Adapters by TDLS module.
5986 */
5987 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5988 {
5989 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5990 "%s: unable to lock list", __func__);
5991 return VOS_STATUS_E_FAILURE;
5992 }
5993#endif
5994
Jeff Johnson295189b2012-06-20 16:38:30 -07005995 hdd_remove_adapter( pHddCtx, pAdapterNode );
5996 vos_mem_free( pAdapterNode );
5997
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305998#ifdef FEATURE_WLAN_TDLS
5999 mutex_unlock(&pHddCtx->tdls_lock);
6000#endif
6001
Jeff Johnson295189b2012-06-20 16:38:30 -07006002
6003 /* If there is a single session of STA/P2P client, re-enable BMPS */
6004 if ((!vos_concurrent_sessions_running()) &&
6005 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6006 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6007 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306008 if (pHddCtx->hdd_wlan_suspended)
6009 {
6010 hdd_set_pwrparams(pHddCtx);
6011 }
6012 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 }
6014
6015 return VOS_STATUS_SUCCESS;
6016 }
6017
6018 return VOS_STATUS_E_FAILURE;
6019}
6020
6021VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6022{
6023 hdd_adapter_list_node_t *pHddAdapterNode;
6024 VOS_STATUS status;
6025
6026 ENTER();
6027
6028 do
6029 {
6030 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6031 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6032 {
6033 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6034 vos_mem_free( pHddAdapterNode );
6035 }
6036 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6037
6038 EXIT();
6039
6040 return VOS_STATUS_SUCCESS;
6041}
6042
6043void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6044{
6045 v_U8_t addIE[1] = {0};
6046
6047 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6048 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6049 eANI_BOOLEAN_FALSE) )
6050 {
6051 hddLog(LOGE,
6052 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
6053 }
6054
6055 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6056 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6057 eANI_BOOLEAN_FALSE) )
6058 {
6059 hddLog(LOGE,
6060 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
6061 }
6062
6063 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6064 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6065 eANI_BOOLEAN_FALSE) )
6066 {
6067 hddLog(LOGE,
6068 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
6069 }
6070}
6071
6072VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6073{
6074 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6075 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6076 union iwreq_data wrqu;
6077
6078 ENTER();
6079
6080 switch(pAdapter->device_mode)
6081 {
6082 case WLAN_HDD_INFRA_STATION:
6083 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006084 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6086 {
6087 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6088 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6089 pAdapter->sessionId,
6090 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6091 else
6092 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6093 pAdapter->sessionId,
6094 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6095 //success implies disconnect command got queued up successfully
6096 if(halStatus == eHAL_STATUS_SUCCESS)
6097 {
6098 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6099 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6100 }
6101 memset(&wrqu, '\0', sizeof(wrqu));
6102 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6103 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6104 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6105 }
6106 else
6107 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306108 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006109 }
6110
6111 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6112 {
6113 INIT_COMPLETION(pAdapter->session_close_comp_var);
6114 if (eHAL_STATUS_SUCCESS ==
6115 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6116 hdd_smeCloseSessionCallback, pAdapter))
6117 {
6118 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006119 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006120 &pAdapter->session_close_comp_var,
6121 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6122 }
6123 }
6124
6125 break;
6126
6127 case WLAN_HDD_SOFTAP:
6128 case WLAN_HDD_P2P_GO:
6129 //Any softap specific cleanup here...
6130 mutex_lock(&pHddCtx->sap_lock);
6131 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6132 {
6133 VOS_STATUS status;
6134 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6135
6136 //Stop Bss.
6137 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6138 if (VOS_IS_STATUS_SUCCESS(status))
6139 {
6140 hdd_hostapd_state_t *pHostapdState =
6141 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6142
6143 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6144
6145 if (!VOS_IS_STATUS_SUCCESS(status))
6146 {
6147 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006148 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 }
6150 }
6151 else
6152 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006153 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006154 }
6155 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6156
6157 if (eHAL_STATUS_FAILURE ==
6158 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6159 0, NULL, eANI_BOOLEAN_FALSE))
6160 {
6161 hddLog(LOGE,
6162 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006163 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 }
6165
6166 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6167 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6168 eANI_BOOLEAN_FALSE) )
6169 {
6170 hddLog(LOGE,
6171 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6172 }
6173
6174 // Reset WNI_CFG_PROBE_RSP Flags
6175 wlan_hdd_reset_prob_rspies(pAdapter);
6176 kfree(pAdapter->sessionCtx.ap.beacon);
6177 pAdapter->sessionCtx.ap.beacon = NULL;
6178 }
6179 mutex_unlock(&pHddCtx->sap_lock);
6180 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006181
Jeff Johnson295189b2012-06-20 16:38:30 -07006182 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006183#ifdef WLAN_OPEN_SOURCE
6184 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6185#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006187
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 default:
6189 break;
6190 }
6191
6192 EXIT();
6193 return VOS_STATUS_SUCCESS;
6194}
6195
6196VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6197{
6198 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6199 VOS_STATUS status;
6200 hdd_adapter_t *pAdapter;
6201
6202 ENTER();
6203
6204 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6205
6206 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6207 {
6208 pAdapter = pAdapterNode->pAdapter;
6209 netif_tx_disable(pAdapter->dev);
6210 netif_carrier_off(pAdapter->dev);
6211
6212 hdd_stop_adapter( pHddCtx, pAdapter );
6213
6214 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6215 pAdapterNode = pNext;
6216 }
6217
6218 EXIT();
6219
6220 return VOS_STATUS_SUCCESS;
6221}
6222
6223VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6224{
6225 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6226 VOS_STATUS status;
6227 hdd_adapter_t *pAdapter;
6228
6229 ENTER();
6230
6231 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6232
6233 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6234 {
6235 pAdapter = pAdapterNode->pAdapter;
6236 netif_tx_disable(pAdapter->dev);
6237 netif_carrier_off(pAdapter->dev);
6238
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006239 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6240
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306242 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6243 {
6244 hdd_wmm_adapter_close( pAdapter );
6245 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6246 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006247
6248 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6249 pAdapterNode = pNext;
6250 }
6251
6252 EXIT();
6253
6254 return VOS_STATUS_SUCCESS;
6255}
6256
6257VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6258{
6259 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6260 VOS_STATUS status;
6261 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306262 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006263
6264 ENTER();
6265
6266 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6267
6268 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6269 {
6270 pAdapter = pAdapterNode->pAdapter;
6271
6272 switch(pAdapter->device_mode)
6273 {
6274 case WLAN_HDD_INFRA_STATION:
6275 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006276 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306277
6278 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6279
Jeff Johnson295189b2012-06-20 16:38:30 -07006280 hdd_init_station_mode(pAdapter);
6281 /* Open the gates for HDD to receive Wext commands */
6282 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006283 pHddCtx->scan_info.mScanPending = FALSE;
6284 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006285
6286 //Trigger the initial scan
6287 hdd_wlan_initial_scan(pAdapter);
6288
6289 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306290 if (eConnectionState_Associated == connState ||
6291 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006292 {
6293 union iwreq_data wrqu;
6294 memset(&wrqu, '\0', sizeof(wrqu));
6295 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6296 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6297 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006298 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006299
Jeff Johnson295189b2012-06-20 16:38:30 -07006300 /* indicate disconnected event to nl80211 */
6301 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6302 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006303 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306304 else if (eConnectionState_Connecting == connState)
6305 {
6306 /*
6307 * Indicate connect failure to supplicant if we were in the
6308 * process of connecting
6309 */
6310 cfg80211_connect_result(pAdapter->dev, NULL,
6311 NULL, 0, NULL, 0,
6312 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6313 GFP_KERNEL);
6314 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006315 break;
6316
6317 case WLAN_HDD_SOFTAP:
6318 /* softAP can handle SSR */
6319 break;
6320
6321 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006322 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006323 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006324 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 break;
6326
6327 case WLAN_HDD_MONITOR:
6328 /* monitor interface start */
6329 break;
6330 default:
6331 break;
6332 }
6333
6334 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6335 pAdapterNode = pNext;
6336 }
6337
6338 EXIT();
6339
6340 return VOS_STATUS_SUCCESS;
6341}
6342
6343VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6344{
6345 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6346 hdd_adapter_t *pAdapter;
6347 VOS_STATUS status;
6348 v_U32_t roamId;
6349
6350 ENTER();
6351
6352 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6353
6354 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6355 {
6356 pAdapter = pAdapterNode->pAdapter;
6357
6358 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6359 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6360 {
6361 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6362 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6363
6364 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6365 init_completion(&pAdapter->disconnect_comp_var);
6366 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6367 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6368
6369 wait_for_completion_interruptible_timeout(
6370 &pAdapter->disconnect_comp_var,
6371 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6372
6373 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6374 pHddCtx->isAmpAllowed = VOS_FALSE;
6375 sme_RoamConnect(pHddCtx->hHal,
6376 pAdapter->sessionId, &(pWextState->roamProfile),
6377 &roamId);
6378 }
6379
6380 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6381 pAdapterNode = pNext;
6382 }
6383
6384 EXIT();
6385
6386 return VOS_STATUS_SUCCESS;
6387}
6388
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006389void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6390{
6391 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6392 VOS_STATUS status;
6393 hdd_adapter_t *pAdapter;
6394 hdd_station_ctx_t *pHddStaCtx;
6395 hdd_ap_ctx_t *pHddApCtx;
6396 hdd_hostapd_state_t * pHostapdState;
6397 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6398 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6399 const char *p2pMode = "DEV";
6400 const char *ccMode = "Standalone";
6401 int n;
6402
6403 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6404 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6405 {
6406 pAdapter = pAdapterNode->pAdapter;
6407 switch (pAdapter->device_mode) {
6408 case WLAN_HDD_INFRA_STATION:
6409 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6410 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6411 staChannel = pHddStaCtx->conn_info.operationChannel;
6412 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6413 }
6414 break;
6415 case WLAN_HDD_P2P_CLIENT:
6416 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6417 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6418 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6419 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6420 p2pMode = "CLI";
6421 }
6422 break;
6423 case WLAN_HDD_P2P_GO:
6424 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6425 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6426 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6427 p2pChannel = pHddApCtx->operatingChannel;
6428 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6429 }
6430 p2pMode = "GO";
6431 break;
6432 case WLAN_HDD_SOFTAP:
6433 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6434 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6435 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6436 apChannel = pHddApCtx->operatingChannel;
6437 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6438 }
6439 break;
6440 default:
6441 break;
6442 }
6443 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6444 pAdapterNode = pNext;
6445 }
6446 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6447 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6448 }
6449 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6450 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6451 if (p2pChannel > 0) {
6452 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6453 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6454 }
6455 if (apChannel > 0) {
6456 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6457 apChannel, MAC_ADDR_ARRAY(apBssid));
6458 }
6459
6460 if (p2pChannel > 0 && apChannel > 0) {
6461 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6462 }
6463}
6464
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006465bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006466{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006467 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006468}
6469
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006470/* Once SSR is disabled then it cannot be set. */
6471void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006472{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006473 if (HDD_SSR_DISABLED == isSsrRequired)
6474 return;
6475
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 isSsrRequired = value;
6477}
6478
6479VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6480 hdd_adapter_list_node_t** ppAdapterNode)
6481{
6482 VOS_STATUS status;
6483 spin_lock(&pHddCtx->hddAdapters.lock);
6484 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6485 (hdd_list_node_t**) ppAdapterNode );
6486 spin_unlock(&pHddCtx->hddAdapters.lock);
6487 return status;
6488}
6489
6490VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6491 hdd_adapter_list_node_t* pAdapterNode,
6492 hdd_adapter_list_node_t** pNextAdapterNode)
6493{
6494 VOS_STATUS status;
6495 spin_lock(&pHddCtx->hddAdapters.lock);
6496 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6497 (hdd_list_node_t*) pAdapterNode,
6498 (hdd_list_node_t**)pNextAdapterNode );
6499
6500 spin_unlock(&pHddCtx->hddAdapters.lock);
6501 return status;
6502}
6503
6504VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6505 hdd_adapter_list_node_t* pAdapterNode)
6506{
6507 VOS_STATUS status;
6508 spin_lock(&pHddCtx->hddAdapters.lock);
6509 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6510 &pAdapterNode->node );
6511 spin_unlock(&pHddCtx->hddAdapters.lock);
6512 return status;
6513}
6514
6515VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6516 hdd_adapter_list_node_t** ppAdapterNode)
6517{
6518 VOS_STATUS status;
6519 spin_lock(&pHddCtx->hddAdapters.lock);
6520 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6521 (hdd_list_node_t**) ppAdapterNode );
6522 spin_unlock(&pHddCtx->hddAdapters.lock);
6523 return status;
6524}
6525
6526VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6527 hdd_adapter_list_node_t* pAdapterNode)
6528{
6529 VOS_STATUS status;
6530 spin_lock(&pHddCtx->hddAdapters.lock);
6531 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6532 (hdd_list_node_t*) pAdapterNode );
6533 spin_unlock(&pHddCtx->hddAdapters.lock);
6534 return status;
6535}
6536
6537VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6538 hdd_adapter_list_node_t* pAdapterNode)
6539{
6540 VOS_STATUS status;
6541 spin_lock(&pHddCtx->hddAdapters.lock);
6542 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6543 (hdd_list_node_t*) pAdapterNode );
6544 spin_unlock(&pHddCtx->hddAdapters.lock);
6545 return status;
6546}
6547
6548hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6549 tSirMacAddr macAddr )
6550{
6551 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6552 hdd_adapter_t *pAdapter;
6553 VOS_STATUS status;
6554
6555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6556
6557 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6558 {
6559 pAdapter = pAdapterNode->pAdapter;
6560
6561 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6562 macAddr, sizeof(tSirMacAddr) ) )
6563 {
6564 return pAdapter;
6565 }
6566 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6567 pAdapterNode = pNext;
6568 }
6569
6570 return NULL;
6571
6572}
6573
6574hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6575{
6576 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6577 hdd_adapter_t *pAdapter;
6578 VOS_STATUS status;
6579
6580 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6581
6582 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6583 {
6584 pAdapter = pAdapterNode->pAdapter;
6585
6586 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6587 IFNAMSIZ ) )
6588 {
6589 return pAdapter;
6590 }
6591 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6592 pAdapterNode = pNext;
6593 }
6594
6595 return NULL;
6596
6597}
6598
6599hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6600{
6601 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6602 hdd_adapter_t *pAdapter;
6603 VOS_STATUS status;
6604
6605 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6606
6607 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6608 {
6609 pAdapter = pAdapterNode->pAdapter;
6610
6611 if( pAdapter && (mode == pAdapter->device_mode) )
6612 {
6613 return pAdapter;
6614 }
6615 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6616 pAdapterNode = pNext;
6617 }
6618
6619 return NULL;
6620
6621}
6622
6623//Remove this function later
6624hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6625{
6626 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6627 hdd_adapter_t *pAdapter;
6628 VOS_STATUS status;
6629
6630 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6631
6632 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6633 {
6634 pAdapter = pAdapterNode->pAdapter;
6635
6636 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6637 {
6638 return pAdapter;
6639 }
6640
6641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6642 pAdapterNode = pNext;
6643 }
6644
6645 return NULL;
6646
6647}
6648
Jeff Johnson295189b2012-06-20 16:38:30 -07006649/**---------------------------------------------------------------------------
6650
6651 \brief hdd_set_monitor_tx_adapter() -
6652
6653 This API initializes the adapter to be used while transmitting on monitor
6654 adapter.
6655
6656 \param - pHddCtx - Pointer to the HDD context.
6657 pAdapter - Adapter that will used for TX. This can be NULL.
6658 \return - None.
6659 --------------------------------------------------------------------------*/
6660void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6661{
6662 hdd_adapter_t *pMonAdapter;
6663
6664 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6665
6666 if( NULL != pMonAdapter )
6667 {
6668 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6669 }
6670}
Jeff Johnson295189b2012-06-20 16:38:30 -07006671/**---------------------------------------------------------------------------
6672
6673 \brief hdd_select_queue() -
6674
6675 This API returns the operating channel of the requested device mode
6676
6677 \param - pHddCtx - Pointer to the HDD context.
6678 - mode - Device mode for which operating channel is required
6679 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6680 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6681 \return - channel number. "0" id the requested device is not found OR it is not connected.
6682 --------------------------------------------------------------------------*/
6683v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6684{
6685 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6686 VOS_STATUS status;
6687 hdd_adapter_t *pAdapter;
6688 v_U8_t operatingChannel = 0;
6689
6690 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6691
6692 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6693 {
6694 pAdapter = pAdapterNode->pAdapter;
6695
6696 if( mode == pAdapter->device_mode )
6697 {
6698 switch(pAdapter->device_mode)
6699 {
6700 case WLAN_HDD_INFRA_STATION:
6701 case WLAN_HDD_P2P_CLIENT:
6702 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6703 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6704 break;
6705 case WLAN_HDD_SOFTAP:
6706 case WLAN_HDD_P2P_GO:
6707 /*softap connection info */
6708 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6709 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6710 break;
6711 default:
6712 break;
6713 }
6714
6715 break; //Found the device of interest. break the loop
6716 }
6717
6718 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6719 pAdapterNode = pNext;
6720 }
6721 return operatingChannel;
6722}
6723
6724#ifdef WLAN_FEATURE_PACKET_FILTERING
6725/**---------------------------------------------------------------------------
6726
6727 \brief hdd_set_multicast_list() -
6728
6729 This used to set the multicast address list.
6730
6731 \param - dev - Pointer to the WLAN device.
6732 - skb - Pointer to OS packet (sk_buff).
6733 \return - success/fail
6734
6735 --------------------------------------------------------------------------*/
6736static void hdd_set_multicast_list(struct net_device *dev)
6737{
6738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006739 int mc_count;
6740 int i = 0;
6741 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306742
6743 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006744 {
6745 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306746 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006747 return;
6748 }
6749
6750 if (dev->flags & IFF_ALLMULTI)
6751 {
6752 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006753 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306754 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006755 }
6756 else
6757 {
6758 mc_count = netdev_mc_count(dev);
6759 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006760 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006761 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6762 {
6763 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006764 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306765 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006766 return;
6767 }
6768
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306769 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006770
6771 netdev_for_each_mc_addr(ha, dev) {
6772 if (i == mc_count)
6773 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306774 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6775 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6776 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006777 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306778 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006779 i++;
6780 }
6781 }
6782 return;
6783}
6784#endif
6785
6786/**---------------------------------------------------------------------------
6787
6788 \brief hdd_select_queue() -
6789
6790 This function is registered with the Linux OS for network
6791 core to decide which queue to use first.
6792
6793 \param - dev - Pointer to the WLAN device.
6794 - skb - Pointer to OS packet (sk_buff).
6795 \return - ac, Queue Index/access category corresponding to UP in IP header
6796
6797 --------------------------------------------------------------------------*/
6798v_U16_t hdd_select_queue(struct net_device *dev,
6799 struct sk_buff *skb)
6800{
6801 return hdd_wmm_select_queue(dev, skb);
6802}
6803
6804
6805/**---------------------------------------------------------------------------
6806
6807 \brief hdd_wlan_initial_scan() -
6808
6809 This function triggers the initial scan
6810
6811 \param - pAdapter - Pointer to the HDD adapter.
6812
6813 --------------------------------------------------------------------------*/
6814void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6815{
6816 tCsrScanRequest scanReq;
6817 tCsrChannelInfo channelInfo;
6818 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006819 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006820 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6821
6822 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6823 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6824 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6825
6826 if(sme_Is11dSupported(pHddCtx->hHal))
6827 {
6828 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6829 if ( HAL_STATUS_SUCCESS( halStatus ) )
6830 {
6831 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6832 if( !scanReq.ChannelInfo.ChannelList )
6833 {
6834 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6835 vos_mem_free(channelInfo.ChannelList);
6836 return;
6837 }
6838 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6839 channelInfo.numOfChannels);
6840 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6841 vos_mem_free(channelInfo.ChannelList);
6842 }
6843
6844 scanReq.scanType = eSIR_PASSIVE_SCAN;
6845 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6846 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6847 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6848 }
6849 else
6850 {
6851 scanReq.scanType = eSIR_ACTIVE_SCAN;
6852 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6853 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6854 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6855 }
6856
6857 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6858 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6859 {
6860 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6861 __func__, halStatus );
6862 }
6863
6864 if(sme_Is11dSupported(pHddCtx->hHal))
6865 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6866}
6867
6868struct fullPowerContext
6869{
6870 struct completion completion;
6871 unsigned int magic;
6872};
6873#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6874
6875/**---------------------------------------------------------------------------
6876
6877 \brief hdd_full_power_callback() - HDD full power callback function
6878
6879 This is the function invoked by SME to inform the result of a full power
6880 request issued by HDD
6881
6882 \param - callbackcontext - Pointer to cookie
6883 \param - status - result of request
6884
6885 \return - None
6886
6887 --------------------------------------------------------------------------*/
6888static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6889{
6890 struct fullPowerContext *pContext = callbackContext;
6891
6892 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306893 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006894
6895 if (NULL == callbackContext)
6896 {
6897 hddLog(VOS_TRACE_LEVEL_ERROR,
6898 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006899 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006900 return;
6901 }
6902
6903 /* there is a race condition that exists between this callback function
6904 and the caller since the caller could time out either before or
6905 while this code is executing. we'll assume the timeout hasn't
6906 occurred, but we'll verify that right before we save our work */
6907
6908 if (POWER_CONTEXT_MAGIC != pContext->magic)
6909 {
6910 /* the caller presumably timed out so there is nothing we can do */
6911 hddLog(VOS_TRACE_LEVEL_WARN,
6912 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006913 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006914 return;
6915 }
6916
6917 /* the race is on. caller could have timed out immediately after
6918 we verified the magic, but if so, caller will wait a short time
6919 for us to notify the caller, so the context will stay valid */
6920 complete(&pContext->completion);
6921}
6922
6923/**---------------------------------------------------------------------------
6924
6925 \brief hdd_wlan_exit() - HDD WLAN exit function
6926
6927 This is the driver exit point (invoked during rmmod)
6928
6929 \param - pHddCtx - Pointer to the HDD Context
6930
6931 \return - None
6932
6933 --------------------------------------------------------------------------*/
6934void hdd_wlan_exit(hdd_context_t *pHddCtx)
6935{
6936 eHalStatus halStatus;
6937 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6938 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306939 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006940 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 struct fullPowerContext powerContext;
6942 long lrc;
6943
6944 ENTER();
6945
Jeff Johnson88ba7742013-02-27 14:36:02 -08006946 if (VOS_FTM_MODE != hdd_get_conparam())
6947 {
6948 // Unloading, restart logic is no more required.
6949 wlan_hdd_restart_deinit(pHddCtx);
6950 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006951
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006955 {
6956 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6957 WLAN_HDD_INFRA_STATION);
6958 if (pAdapter == NULL)
6959 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6960
6961 if (pAdapter != NULL)
6962 {
6963 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6964 hdd_UnregisterWext(pAdapter->dev);
6965 }
6966 }
6967 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006968
Jeff Johnson295189b2012-06-20 16:38:30 -07006969 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006970 {
6971 wlan_hdd_ftm_close(pHddCtx);
6972 goto free_hdd_ctx;
6973 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006974 //Stop the Interface TX queue.
6975 //netif_tx_disable(pWlanDev);
6976 //netif_carrier_off(pWlanDev);
6977
Jeff Johnson295189b2012-06-20 16:38:30 -07006978 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6979 {
6980 pAdapter = hdd_get_adapter(pHddCtx,
6981 WLAN_HDD_SOFTAP);
6982 }
6983 else
6984 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006985 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 {
6987 pAdapter = hdd_get_adapter(pHddCtx,
6988 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006989 if (pAdapter == NULL)
6990 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 /* DeRegister with platform driver as client for Suspend/Resume */
6994 vosStatus = hddDeregisterPmOps(pHddCtx);
6995 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6996 {
6997 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6998 VOS_ASSERT(0);
6999 }
7000
7001 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7002 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7003 {
7004 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7005 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007006
7007 // Cancel any outstanding scan requests. We are about to close all
7008 // of our adapters, but an adapter structure is what SME passes back
7009 // to our callback function. Hence if there are any outstanding scan
7010 // requests then there is a race condition between when the adapter
7011 // is closed and when the callback is invoked. We try to resolve that
7012 // race condition here by canceling any outstanding scans before we
7013 // close the adapters.
7014 // Note that the scans may be cancelled in an asynchronous manner, so
7015 // ideally there needs to be some kind of synchronization. Rather than
7016 // introduce a new synchronization here, we will utilize the fact that
7017 // we are about to Request Full Power, and since that is synchronized,
7018 // the expectation is that by the time Request Full Power has completed,
7019 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007020 if (NULL != pAdapter)
7021 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7022 else
7023 hddLog(VOS_TRACE_LEVEL_ERROR,
7024 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007025
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007026 //Stop the traffic monitor timer
7027 if ( VOS_TIMER_STATE_RUNNING ==
7028 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7029 {
7030 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7031 }
7032
7033 // Destroy the traffic monitor timer
7034 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7035 &pHddCtx->tx_rx_trafficTmr)))
7036 {
7037 hddLog(VOS_TRACE_LEVEL_ERROR,
7038 "%s: Cannot deallocate Traffic monitor timer", __func__);
7039 }
7040
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 //Disable IMPS/BMPS as we do not want the device to enter any power
7042 //save mode during shutdown
7043 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7044 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7045 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7046
7047 //Ensure that device is in full power as we will touch H/W during vos_Stop
7048 init_completion(&powerContext.completion);
7049 powerContext.magic = POWER_CONTEXT_MAGIC;
7050
7051 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7052 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7053
7054 if (eHAL_STATUS_SUCCESS != halStatus)
7055 {
7056 if (eHAL_STATUS_PMC_PENDING == halStatus)
7057 {
7058 /* request was sent -- wait for the response */
7059 lrc = wait_for_completion_interruptible_timeout(
7060 &powerContext.completion,
7061 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7062 /* either we have a response or we timed out
7063 either way, first invalidate our magic */
7064 powerContext.magic = 0;
7065 if (lrc <= 0)
7066 {
7067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007068 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007069 /* there is a race condition such that the callback
7070 function could be executing at the same time we are. of
7071 primary concern is if the callback function had already
7072 verified the "magic" but hasn't yet set the completion
7073 variable. Since the completion variable is on our
7074 stack, we'll delay just a bit to make sure the data is
7075 still valid if that is the case */
7076 msleep(50);
7077 }
7078 }
7079 else
7080 {
7081 hddLog(VOS_TRACE_LEVEL_ERROR,
7082 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007083 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007084 VOS_ASSERT(0);
7085 /* continue -- need to clean up as much as possible */
7086 }
7087 }
7088
Yue Ma0d4891e2013-08-06 17:01:45 -07007089 hdd_debugfs_exit(pHddCtx);
7090
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 // Unregister the Net Device Notifier
7092 unregister_netdevice_notifier(&hdd_netdev_notifier);
7093
Jeff Johnson295189b2012-06-20 16:38:30 -07007094 hdd_stop_all_adapters( pHddCtx );
7095
Jeff Johnson295189b2012-06-20 16:38:30 -07007096#ifdef WLAN_BTAMP_FEATURE
7097 vosStatus = WLANBAP_Stop(pVosContext);
7098 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7099 {
7100 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7101 "%s: Failed to stop BAP",__func__);
7102 }
7103#endif //WLAN_BTAMP_FEATURE
7104
7105 //Stop all the modules
7106 vosStatus = vos_stop( pVosContext );
7107 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7108 {
7109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7110 "%s: Failed to stop VOSS",__func__);
7111 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7112 }
7113
Jeff Johnson295189b2012-06-20 16:38:30 -07007114 //Assert Deep sleep signal now to put Libra HW in lowest power state
7115 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7116 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7117
7118 //Vote off any PMIC voltage supplies
7119 vos_chipPowerDown(NULL, NULL, NULL);
7120
7121 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7122
Leo Chang59cdc7e2013-07-10 10:08:21 -07007123
Jeff Johnson295189b2012-06-20 16:38:30 -07007124 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007125 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007126
7127 //Close the scheduler before calling vos_close to make sure no thread is
7128 // scheduled after the each module close is called i.e after all the data
7129 // structures are freed.
7130 vosStatus = vos_sched_close( pVosContext );
7131 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7132 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7133 "%s: Failed to close VOSS Scheduler",__func__);
7134 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7135 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007136#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007137#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7138 /* Destroy the wake lock */
7139 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7140#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007141 /* Destroy the wake lock */
7142 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007143#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007144
7145 //Close VOSS
7146 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7147 vos_close(pVosContext);
7148
Jeff Johnson295189b2012-06-20 16:38:30 -07007149 //Close Watchdog
7150 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7151 vos_watchdog_close(pVosContext);
7152
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307153 //Clean up HDD Nlink Service
7154 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007155#ifdef WLAN_KD_READY_NOTIFIER
7156 nl_srv_exit(pHddCtx->ptt_pid);
7157#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307158 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007159#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307160
Jeff Johnson295189b2012-06-20 16:38:30 -07007161 /* Cancel the vote for XO Core ON.
7162 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7163 * exited at this point
7164 */
7165 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
7166 " when WLAN is turned OFF\n");
7167 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7168 {
7169 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7170 " Not returning failure."
7171 " Power consumed will be high\n");
7172 }
7173
7174 hdd_close_all_adapters( pHddCtx );
7175
7176
7177 //Free up dynamically allocated members inside HDD Adapter
7178 kfree(pHddCtx->cfg_ini);
7179 pHddCtx->cfg_ini= NULL;
7180
7181 /* free the power on lock from platform driver */
7182 if (free_riva_power_on_lock("wlan"))
7183 {
7184 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7185 __func__);
7186 }
7187
Jeff Johnson88ba7742013-02-27 14:36:02 -08007188free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007189 /* FTM mode, WIPHY did not registered
7190 If un-register here, system crash will happen */
7191 if (VOS_FTM_MODE != hdd_get_conparam())
7192 {
7193 wiphy_unregister(wiphy) ;
7194 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007195 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007196 if (hdd_is_ssr_required())
7197 {
7198 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007199 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007200 msleep(5000);
7201 }
7202 hdd_set_ssr_required (VOS_FALSE);
7203}
7204
7205
7206/**---------------------------------------------------------------------------
7207
7208 \brief hdd_update_config_from_nv() - Function to update the contents of
7209 the running configuration with parameters taken from NV storage
7210
7211 \param - pHddCtx - Pointer to the HDD global context
7212
7213 \return - VOS_STATUS_SUCCESS if successful
7214
7215 --------------------------------------------------------------------------*/
7216static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7217{
Jeff Johnson295189b2012-06-20 16:38:30 -07007218 v_BOOL_t itemIsValid = VOS_FALSE;
7219 VOS_STATUS status;
7220 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7221 v_U8_t macLoop;
7222
7223 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7224 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7225 if(status != VOS_STATUS_SUCCESS)
7226 {
7227 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
7228 return VOS_STATUS_E_FAILURE;
7229 }
7230
7231 if (itemIsValid == VOS_TRUE)
7232 {
7233 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
7234 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7235 VOS_MAX_CONCURRENCY_PERSONA);
7236 if(status != VOS_STATUS_SUCCESS)
7237 {
7238 /* Get MAC from NV fail, not update CFG info
7239 * INI MAC value will be used for MAC setting */
7240 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
7241 return VOS_STATUS_E_FAILURE;
7242 }
7243
7244 /* If first MAC is not valid, treat all others are not valid
7245 * Then all MACs will be got from ini file */
7246 if(vos_is_macaddr_zero(&macFromNV[0]))
7247 {
7248 /* MAC address in NV file is not configured yet */
7249 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7250 return VOS_STATUS_E_INVAL;
7251 }
7252
7253 /* Get MAC address from NV, update CFG info */
7254 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7255 {
7256 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7257 {
7258 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7259 /* This MAC is not valid, skip it
7260 * This MAC will be got from ini file */
7261 }
7262 else
7263 {
7264 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7265 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7266 VOS_MAC_ADDR_SIZE);
7267 }
7268 }
7269 }
7270 else
7271 {
7272 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7273 return VOS_STATUS_E_FAILURE;
7274 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007275
Jeff Johnson295189b2012-06-20 16:38:30 -07007276
7277 return VOS_STATUS_SUCCESS;
7278}
7279
7280/**---------------------------------------------------------------------------
7281
7282 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7283
7284 \param - pAdapter - Pointer to the HDD
7285
7286 \return - None
7287
7288 --------------------------------------------------------------------------*/
7289VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7290{
7291 eHalStatus halStatus;
7292 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307293 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007294
Jeff Johnson295189b2012-06-20 16:38:30 -07007295
7296 // Send ready indication to the HDD. This will kick off the MAC
7297 // into a 'running' state and should kick off an initial scan.
7298 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7299 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7300 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307301 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007302 "code %08d [x%08x]",__func__, halStatus, halStatus );
7303 return VOS_STATUS_E_FAILURE;
7304 }
7305
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307306 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007307 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7308 // And RIVA will crash
7309 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7310 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307311 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7312 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7313
7314
Jeff Johnson295189b2012-06-20 16:38:30 -07007315 return VOS_STATUS_SUCCESS;
7316}
7317
Jeff Johnson295189b2012-06-20 16:38:30 -07007318/* wake lock APIs for HDD */
7319void hdd_prevent_suspend(void)
7320{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007321#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007322 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007323#else
7324 wcnss_prevent_suspend();
7325#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007326}
7327
7328void hdd_allow_suspend(void)
7329{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007330#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007331 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007332#else
7333 wcnss_allow_suspend();
7334#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007335}
7336
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007337void hdd_allow_suspend_timeout(v_U32_t timeout)
7338{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007339#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007340 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007341#else
7342 /* Do nothing as there is no API in wcnss for timeout*/
7343#endif
7344}
7345
Jeff Johnson295189b2012-06-20 16:38:30 -07007346/**---------------------------------------------------------------------------
7347
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007348 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7349 information between Host and Riva
7350
7351 This function gets reported version of FW
7352 It also finds the version of Riva headers used to compile the host
7353 It compares the above two and prints a warning if they are different
7354 It gets the SW and HW version string
7355 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7356 indicating the features they support through a bitmap
7357
7358 \param - pHddCtx - Pointer to HDD context
7359
7360 \return - void
7361
7362 --------------------------------------------------------------------------*/
7363
7364void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7365{
7366
7367 tSirVersionType versionCompiled;
7368 tSirVersionType versionReported;
7369 tSirVersionString versionString;
7370 tANI_U8 fwFeatCapsMsgSupported = 0;
7371 VOS_STATUS vstatus;
7372
7373 /* retrieve and display WCNSS version information */
7374 do {
7375
7376 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7377 &versionCompiled);
7378 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7379 {
7380 hddLog(VOS_TRACE_LEVEL_FATAL,
7381 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007382 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007383 break;
7384 }
7385
7386 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7387 &versionReported);
7388 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7389 {
7390 hddLog(VOS_TRACE_LEVEL_FATAL,
7391 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007392 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007393 break;
7394 }
7395
7396 if ((versionCompiled.major != versionReported.major) ||
7397 (versionCompiled.minor != versionReported.minor) ||
7398 (versionCompiled.version != versionReported.version) ||
7399 (versionCompiled.revision != versionReported.revision))
7400 {
7401 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7402 "Host expected %u.%u.%u.%u\n",
7403 WLAN_MODULE_NAME,
7404 (int)versionReported.major,
7405 (int)versionReported.minor,
7406 (int)versionReported.version,
7407 (int)versionReported.revision,
7408 (int)versionCompiled.major,
7409 (int)versionCompiled.minor,
7410 (int)versionCompiled.version,
7411 (int)versionCompiled.revision);
7412 }
7413 else
7414 {
7415 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7416 WLAN_MODULE_NAME,
7417 (int)versionReported.major,
7418 (int)versionReported.minor,
7419 (int)versionReported.version,
7420 (int)versionReported.revision);
7421 }
7422
7423 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7424 versionString,
7425 sizeof(versionString));
7426 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7427 {
7428 hddLog(VOS_TRACE_LEVEL_FATAL,
7429 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007430 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007431 break;
7432 }
7433
7434 pr_info("%s: WCNSS software version %s\n",
7435 WLAN_MODULE_NAME, versionString);
7436
7437 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7438 versionString,
7439 sizeof(versionString));
7440 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7441 {
7442 hddLog(VOS_TRACE_LEVEL_FATAL,
7443 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007444 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007445 break;
7446 }
7447
7448 pr_info("%s: WCNSS hardware version %s\n",
7449 WLAN_MODULE_NAME, versionString);
7450
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007451 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7452 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007453 send the message only if it the riva is 1.1
7454 minor numbers for different riva branches:
7455 0 -> (1.0)Mainline Build
7456 1 -> (1.1)Mainline Build
7457 2->(1.04) Stability Build
7458 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007459 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007460 ((versionReported.minor>=1) && (versionReported.version>=1)))
7461 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7462 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007463
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007464 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007465 {
7466#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7467 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7468 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7469#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007470 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7471 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7472 {
7473 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7474 }
7475
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007476 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007477 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007478
7479 } while (0);
7480
7481}
7482
7483/**---------------------------------------------------------------------------
7484
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307485 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7486
7487 \param - pHddCtx - Pointer to the hdd context
7488
7489 \return - true if hardware supports 5GHz
7490
7491 --------------------------------------------------------------------------*/
7492static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7493{
7494 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7495 * then hardware support 5Ghz.
7496 */
7497 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7498 {
7499 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7500 return true;
7501 }
7502 else
7503 {
7504 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7505 __func__);
7506 return false;
7507 }
7508}
7509
7510
7511/**---------------------------------------------------------------------------
7512
Jeff Johnson295189b2012-06-20 16:38:30 -07007513 \brief hdd_wlan_startup() - HDD init function
7514
7515 This is the driver startup code executed once a WLAN device has been detected
7516
7517 \param - dev - Pointer to the underlying device
7518
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007519 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007520
7521 --------------------------------------------------------------------------*/
7522
7523int hdd_wlan_startup(struct device *dev )
7524{
7525 VOS_STATUS status;
7526 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007527 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007528 hdd_context_t *pHddCtx = NULL;
7529 v_CONTEXT_t pVosContext= NULL;
7530#ifdef WLAN_BTAMP_FEATURE
7531 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7532 WLANBAP_ConfigType btAmpConfig;
7533 hdd_config_t *pConfig;
7534#endif
7535 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007536 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007537
7538 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007539 /*
7540 * cfg80211: wiphy allocation
7541 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307542 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007543
7544 if(wiphy == NULL)
7545 {
7546 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007547 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007548 }
7549
7550 pHddCtx = wiphy_priv(wiphy);
7551
Jeff Johnson295189b2012-06-20 16:38:30 -07007552 //Initialize the adapter context to zeros.
7553 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7554
Jeff Johnson295189b2012-06-20 16:38:30 -07007555 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007556 hdd_prevent_suspend();
7557 pHddCtx->isLoadUnloadInProgress = TRUE;
7558
7559 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7560
7561 /*Get vos context here bcoz vos_open requires it*/
7562 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7563
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007564 if(pVosContext == NULL)
7565 {
7566 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7567 goto err_free_hdd_context;
7568 }
7569
Jeff Johnson295189b2012-06-20 16:38:30 -07007570 //Save the Global VOSS context in adapter context for future.
7571 pHddCtx->pvosContext = pVosContext;
7572
7573 //Save the adapter context in global context for future.
7574 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7575
Jeff Johnson295189b2012-06-20 16:38:30 -07007576 pHddCtx->parent_dev = dev;
7577
7578 init_completion(&pHddCtx->full_pwr_comp_var);
7579 init_completion(&pHddCtx->standby_comp_var);
7580 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007581 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007582 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307583 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007584
7585#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007586 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007587#else
7588 init_completion(&pHddCtx->driver_crda_req);
7589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007590
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307591 spin_lock_init(&pHddCtx->schedScan_lock);
7592
Jeff Johnson295189b2012-06-20 16:38:30 -07007593 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7594
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307595#ifdef FEATURE_WLAN_TDLS
7596 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7597 * invoked by other instances also) to protect the concurrent
7598 * access for the Adapters by TDLS module.
7599 */
7600 mutex_init(&pHddCtx->tdls_lock);
7601#endif
7602
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307603 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007604 // Load all config first as TL config is needed during vos_open
7605 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7606 if(pHddCtx->cfg_ini == NULL)
7607 {
7608 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7609 goto err_free_hdd_context;
7610 }
7611
7612 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7613
7614 // Read and parse the qcom_cfg.ini file
7615 status = hdd_parse_config_ini( pHddCtx );
7616 if ( VOS_STATUS_SUCCESS != status )
7617 {
7618 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7619 __func__, WLAN_INI_FILE);
7620 goto err_config;
7621 }
7622
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307623 /* INI has been read, initialise the configuredMcastBcastFilter with
7624 * INI value as this will serve as the default value
7625 */
7626 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7627 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7628 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307629
7630 if (false == hdd_is_5g_supported(pHddCtx))
7631 {
7632 //5Ghz is not supported.
7633 if (1 != pHddCtx->cfg_ini->nBandCapability)
7634 {
7635 hddLog(VOS_TRACE_LEVEL_INFO,
7636 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7637 pHddCtx->cfg_ini->nBandCapability = 1;
7638 }
7639 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307640
7641 /* If SNR Monitoring is enabled, FW has to parse all beacons
7642 * for calcaluting and storing the average SNR, so set Nth beacon
7643 * filter to 1 to enable FW to parse all the beaocons
7644 */
7645 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7646 {
7647 /* The log level is deliberately set to WARN as overriding
7648 * nthBeaconFilter to 1 will increase power cosumption and this
7649 * might just prove helpful to detect the power issue.
7650 */
7651 hddLog(VOS_TRACE_LEVEL_WARN,
7652 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7653 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7654 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007655 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307656 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307658 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007659 {
7660 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307661 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7662 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007663 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007664
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007665 // Update VOS trace levels based upon the cfg.ini
7666 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7667 pHddCtx->cfg_ini->vosTraceEnableBAP);
7668 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7669 pHddCtx->cfg_ini->vosTraceEnableTL);
7670 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7671 pHddCtx->cfg_ini->vosTraceEnableWDI);
7672 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7673 pHddCtx->cfg_ini->vosTraceEnableHDD);
7674 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7675 pHddCtx->cfg_ini->vosTraceEnableSME);
7676 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7677 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307678 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7679 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007680 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7681 pHddCtx->cfg_ini->vosTraceEnableWDA);
7682 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7683 pHddCtx->cfg_ini->vosTraceEnableSYS);
7684 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7685 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007686 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7687 pHddCtx->cfg_ini->vosTraceEnableSAP);
7688 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7689 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007690
Jeff Johnson295189b2012-06-20 16:38:30 -07007691 // Update WDI trace levels based upon the cfg.ini
7692 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7693 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7694 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7695 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7696 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7697 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7698 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7699 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007700
Jeff Johnson88ba7742013-02-27 14:36:02 -08007701 if (VOS_FTM_MODE == hdd_get_conparam())
7702 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007703 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7704 {
7705 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7706 goto err_free_hdd_context;
7707 }
7708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7709 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007710 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007711
Jeff Johnson88ba7742013-02-27 14:36:02 -08007712 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007713 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7714 {
7715 status = vos_watchdog_open(pVosContext,
7716 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7717
7718 if(!VOS_IS_STATUS_SUCCESS( status ))
7719 {
7720 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307721 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007722 }
7723 }
7724
7725 pHddCtx->isLogpInProgress = FALSE;
7726 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7727
Jeff Johnson295189b2012-06-20 16:38:30 -07007728 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7729 if(!VOS_IS_STATUS_SUCCESS(status))
7730 {
7731 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007732 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007733 }
7734
Amar Singhala49cbc52013-10-08 18:37:44 -07007735#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007736 /* initialize the NV module. This is required so that
7737 we can initialize the channel information in wiphy
7738 from the NV.bin data. The channel information in
7739 wiphy needs to be initialized before wiphy registration */
7740
7741 status = vos_nv_open();
7742 if (!VOS_IS_STATUS_SUCCESS(status))
7743 {
7744 /* NV module cannot be initialized */
7745 hddLog( VOS_TRACE_LEVEL_FATAL,
7746 "%s: vos_nv_open failed", __func__);
7747 goto err_clkvote;
7748 }
7749
7750 status = vos_init_wiphy_from_nv_bin();
7751 if (!VOS_IS_STATUS_SUCCESS(status))
7752 {
7753 /* NV module cannot be initialized */
7754 hddLog( VOS_TRACE_LEVEL_FATAL,
7755 "%s: vos_init_wiphy failed", __func__);
7756 goto err_vos_nv_close;
7757 }
7758
Amar Singhala49cbc52013-10-08 18:37:44 -07007759 /* registration of wiphy dev with cfg80211 */
7760 if (0 > wlan_hdd_cfg80211_register(wiphy))
7761 {
7762 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007763 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007764 }
7765#endif
7766
Jeff Johnson295189b2012-06-20 16:38:30 -07007767 status = vos_open( &pVosContext, 0);
7768 if ( !VOS_IS_STATUS_SUCCESS( status ))
7769 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007770 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007771 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007772 }
7773
Jeff Johnson295189b2012-06-20 16:38:30 -07007774 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7775
7776 if ( NULL == pHddCtx->hHal )
7777 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007778 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007779 goto err_vosclose;
7780 }
7781
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007782 status = vos_preStart( pHddCtx->pvosContext );
7783 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7784 {
7785 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7786 goto err_vosclose;
7787 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007788
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007789 /* Note that the vos_preStart() sequence triggers the cfg download.
7790 The cfg download must occur before we update the SME config
7791 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007792 status = hdd_set_sme_config( pHddCtx );
7793
7794 if ( VOS_STATUS_SUCCESS != status )
7795 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007796 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7797 goto err_vosclose;
7798 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007799
7800 //Initialize the WMM module
7801 status = hdd_wmm_init(pHddCtx);
7802 if (!VOS_IS_STATUS_SUCCESS(status))
7803 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007804 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007805 goto err_vosclose;
7806 }
7807
Jeff Johnson295189b2012-06-20 16:38:30 -07007808 /* In the integrated architecture we update the configuration from
7809 the INI file and from NV before vOSS has been started so that
7810 the final contents are available to send down to the cCPU */
7811
7812 // Apply the cfg.ini to cfg.dat
7813 if (FALSE == hdd_update_config_dat(pHddCtx))
7814 {
7815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7816 goto err_vosclose;
7817 }
7818
7819 // Apply the NV to cfg.dat
7820 /* Prima Update MAC address only at here */
7821 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7822 {
7823#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7824 /* There was not a valid set of MAC Addresses in NV. See if the
7825 default addresses were modified by the cfg.ini settings. If so,
7826 we'll use them, but if not, we'll autogenerate a set of MAC
7827 addresses based upon the device serial number */
7828
7829 static const v_MACADDR_t default_address =
7830 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7831 unsigned int serialno;
7832 int i;
7833
7834 serialno = wcnss_get_serial_number();
7835 if ((0 != serialno) &&
7836 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7837 sizeof(default_address))))
7838 {
7839 /* cfg.ini has the default address, invoke autogen logic */
7840
7841 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7842 bytes of the serial number that can be used to generate
7843 the other 3 bytes of the MAC address. Mask off all but
7844 the lower 3 bytes (this will also make sure we don't
7845 overflow in the next step) */
7846 serialno &= 0x00FFFFFF;
7847
7848 /* we need a unique address for each session */
7849 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7850
7851 /* autogen all addresses */
7852 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7853 {
7854 /* start with the entire default address */
7855 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7856 /* then replace the lower 3 bytes */
7857 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7858 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7859 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7860
7861 serialno++;
7862 }
7863
7864 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7865 MAC_ADDRESS_STR,
7866 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7867 }
7868 else
7869#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7870 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007871 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007872 "%s: Invalid MAC address in NV, using MAC from ini file "
7873 MAC_ADDRESS_STR, __func__,
7874 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7875 }
7876 }
7877 {
7878 eHalStatus halStatus;
7879 // Set the MAC Address
7880 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7881 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7882 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7883 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7884
7885 if (!HAL_STATUS_SUCCESS( halStatus ))
7886 {
7887 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7888 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007889 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007890 }
7891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007892
7893 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7894 Note: Firmware image will be read and downloaded inside vos_start API */
7895 status = vos_start( pHddCtx->pvosContext );
7896 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7897 {
7898 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7899 goto err_vosclose;
7900 }
7901
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007902 /* Exchange capability info between Host and FW and also get versioning info from FW */
7903 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007904
7905 status = hdd_post_voss_start_config( pHddCtx );
7906 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7907 {
7908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7909 __func__);
7910 goto err_vosstop;
7911 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007912
7913#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307914 wlan_hdd_cfg80211_update_reg_info( wiphy );
7915
7916 /* registration of wiphy dev with cfg80211 */
7917 if (0 > wlan_hdd_cfg80211_register(wiphy))
7918 {
7919 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7920 goto err_vosstop;
7921 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007922#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007923
Jeff Johnson295189b2012-06-20 16:38:30 -07007924 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7925 {
7926 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7927 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7928 }
7929 else
7930 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007931 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7932 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7933 if (pAdapter != NULL)
7934 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307935 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007936 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307937 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7938 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7939 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007940
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307941 /* Generate the P2P Device Address. This consists of the device's
7942 * primary MAC address with the locally administered bit set.
7943 */
7944 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007945 }
7946 else
7947 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307948 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7949 if (p2p_dev_addr != NULL)
7950 {
7951 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7952 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7953 }
7954 else
7955 {
7956 hddLog(VOS_TRACE_LEVEL_FATAL,
7957 "%s: Failed to allocate mac_address for p2p_device",
7958 __func__);
7959 goto err_close_adapter;
7960 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007961 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007962
7963 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7964 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7965 if ( NULL == pP2pAdapter )
7966 {
7967 hddLog(VOS_TRACE_LEVEL_FATAL,
7968 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007969 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007970 goto err_close_adapter;
7971 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007972 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007973 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007974
7975 if( pAdapter == NULL )
7976 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007977 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7978 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007979 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007980
Jeff Johnson295189b2012-06-20 16:38:30 -07007981#ifdef WLAN_BTAMP_FEATURE
7982 vStatus = WLANBAP_Open(pVosContext);
7983 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7984 {
7985 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7986 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007987 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007988 }
7989
7990 vStatus = BSL_Init(pVosContext);
7991 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7992 {
7993 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7994 "%s: Failed to Init BSL",__func__);
7995 goto err_bap_close;
7996 }
7997 vStatus = WLANBAP_Start(pVosContext);
7998 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7999 {
8000 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8001 "%s: Failed to start TL",__func__);
8002 goto err_bap_close;
8003 }
8004
8005 pConfig = pHddCtx->cfg_ini;
8006 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8007 status = WLANBAP_SetConfig(&btAmpConfig);
8008
8009#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008010
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008011#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8012 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8013 {
8014 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8015 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8016 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8017 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8018 }
8019#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008020#ifdef FEATURE_WLAN_SCAN_PNO
8021 /*SME must send channel update configuration to RIVA*/
8022 sme_UpdateChannelConfig(pHddCtx->hHal);
8023#endif
8024
Jeff Johnson295189b2012-06-20 16:38:30 -07008025 /* Register with platform driver as client for Suspend/Resume */
8026 status = hddRegisterPmOps(pHddCtx);
8027 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8028 {
8029 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8030#ifdef WLAN_BTAMP_FEATURE
8031 goto err_bap_stop;
8032#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008033 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008034#endif //WLAN_BTAMP_FEATURE
8035 }
8036
Yue Ma0d4891e2013-08-06 17:01:45 -07008037 /* Open debugfs interface */
8038 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8039 {
8040 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8041 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008042 }
8043
Jeff Johnson295189b2012-06-20 16:38:30 -07008044 /* Register TM level change handler function to the platform */
8045 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8046 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8047 {
8048 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8049 goto err_unregister_pmops;
8050 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008051
8052 /* register for riva power on lock to platform driver */
8053 if (req_riva_power_on_lock("wlan"))
8054 {
8055 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8056 __func__);
8057 goto err_unregister_pmops;
8058 }
8059
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 // register net device notifier for device change notification
8061 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8062
8063 if(ret < 0)
8064 {
8065 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8066 goto err_free_power_on_lock;
8067 }
8068
8069 //Initialize the nlink service
8070 if(nl_srv_init() != 0)
8071 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308072 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008073 goto err_reg_netdev;
8074 }
8075
Leo Chang4ce1cc52013-10-21 18:27:15 -07008076#ifdef WLAN_KD_READY_NOTIFIER
8077 pHddCtx->kd_nl_init = 1;
8078#endif /* WLAN_KD_READY_NOTIFIER */
8079
Jeff Johnson295189b2012-06-20 16:38:30 -07008080 //Initialize the BTC service
8081 if(btc_activate_service(pHddCtx) != 0)
8082 {
8083 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8084 goto err_nl_srv;
8085 }
8086
8087#ifdef PTT_SOCK_SVC_ENABLE
8088 //Initialize the PTT service
8089 if(ptt_sock_activate_svc(pHddCtx) != 0)
8090 {
8091 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8092 goto err_nl_srv;
8093 }
8094#endif
8095
Jeff Johnson295189b2012-06-20 16:38:30 -07008096 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008097 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008098 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008099 /* Action frame registered in one adapter which will
8100 * applicable to all interfaces
8101 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008102 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008104
8105 mutex_init(&pHddCtx->sap_lock);
8106
8107 pHddCtx->isLoadUnloadInProgress = FALSE;
8108
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008109#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008110#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8111 /* Initialize the wake lcok */
8112 wake_lock_init(&pHddCtx->rx_wake_lock,
8113 WAKE_LOCK_SUSPEND,
8114 "qcom_rx_wakelock");
8115#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008116 /* Initialize the wake lcok */
8117 wake_lock_init(&pHddCtx->sap_wake_lock,
8118 WAKE_LOCK_SUSPEND,
8119 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008120#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008121
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008122 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8123 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008124
8125 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8126 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05308127
Jeff Johnsone7245742012-09-05 17:12:55 -07008128 // Initialize the restart logic
8129 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308130
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008131 //Register the traffic monitor timer now
8132 if ( pHddCtx->cfg_ini->dynSplitscan)
8133 {
8134 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8135 VOS_TIMER_TYPE_SW,
8136 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8137 (void *)pHddCtx);
8138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008139 goto success;
8140
8141err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008142#ifdef WLAN_KD_READY_NOTIFIER
8143 nl_srv_exit(pHddCtx->ptt_pid);
8144#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008145 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008146#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008147err_reg_netdev:
8148 unregister_netdevice_notifier(&hdd_netdev_notifier);
8149
8150err_free_power_on_lock:
8151 free_riva_power_on_lock("wlan");
8152
8153err_unregister_pmops:
8154 hddDevTmUnregisterNotifyCallback(pHddCtx);
8155 hddDeregisterPmOps(pHddCtx);
8156
Yue Ma0d4891e2013-08-06 17:01:45 -07008157 hdd_debugfs_exit(pHddCtx);
8158
Jeff Johnson295189b2012-06-20 16:38:30 -07008159#ifdef WLAN_BTAMP_FEATURE
8160err_bap_stop:
8161 WLANBAP_Stop(pVosContext);
8162#endif
8163
8164#ifdef WLAN_BTAMP_FEATURE
8165err_bap_close:
8166 WLANBAP_Close(pVosContext);
8167#endif
8168
Jeff Johnson295189b2012-06-20 16:38:30 -07008169err_close_adapter:
8170 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008171
8172#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308173 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008174#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008175
8176err_vosstop:
8177 vos_stop(pVosContext);
8178
Amar Singhala49cbc52013-10-08 18:37:44 -07008179err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 status = vos_sched_close( pVosContext );
8181 if (!VOS_IS_STATUS_SUCCESS(status)) {
8182 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8183 "%s: Failed to close VOSS Scheduler", __func__);
8184 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8185 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008186 vos_close(pVosContext );
8187
8188err_wiphy_unregister:
8189
8190#ifdef CONFIG_ENABLE_LINUX_REG
8191 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008192
Amar Singhal0a402232013-10-11 20:57:16 -07008193err_vos_nv_close:
8194
8195 vos_nv_close();
8196
Jeff Johnson295189b2012-06-20 16:38:30 -07008197err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008198#endif
8199
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008200 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008201
8202err_wdclose:
8203 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8204 vos_watchdog_close(pVosContext);
8205
Jeff Johnson295189b2012-06-20 16:38:30 -07008206err_config:
8207 kfree(pHddCtx->cfg_ini);
8208 pHddCtx->cfg_ini= NULL;
8209
8210err_free_hdd_context:
8211 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008212 wiphy_free(wiphy) ;
8213 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 VOS_BUG(1);
8215
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008216 if (hdd_is_ssr_required())
8217 {
8218 /* WDI timeout had happened during load, so SSR is needed here */
8219 subsystem_restart("wcnss");
8220 msleep(5000);
8221 }
8222 hdd_set_ssr_required (VOS_FALSE);
8223
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008224 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008225
8226success:
8227 EXIT();
8228 return 0;
8229}
8230
8231/**---------------------------------------------------------------------------
8232
Jeff Johnson32d95a32012-09-10 13:15:23 -07008233 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008234
Jeff Johnson32d95a32012-09-10 13:15:23 -07008235 This is the driver entry point - called in different timeline depending
8236 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008237
8238 \param - None
8239
8240 \return - 0 for success, non zero for failure
8241
8242 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008243static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008244{
8245 VOS_STATUS status;
8246 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008247 struct device *dev = NULL;
8248 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008249#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8250 int max_retries = 0;
8251#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008252
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308253#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8254 vos_wconn_trace_init();
8255#endif
8256
Jeff Johnson295189b2012-06-20 16:38:30 -07008257 ENTER();
8258
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008259#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008260 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008261#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008262
8263 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8264 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8265
8266 //Power Up Libra WLAN card first if not already powered up
8267 status = vos_chipPowerUp(NULL,NULL,NULL);
8268 if (!VOS_IS_STATUS_SUCCESS(status))
8269 {
8270 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8271 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308272#ifdef WLAN_OPEN_SOURCE
8273 wake_lock_destroy(&wlan_wake_lock);
8274#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008275 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008276 }
8277
Jeff Johnson295189b2012-06-20 16:38:30 -07008278#ifdef ANI_BUS_TYPE_PCI
8279
8280 dev = wcnss_wlan_get_device();
8281
8282#endif // ANI_BUS_TYPE_PCI
8283
8284#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008285
8286#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8287 /* wait until WCNSS driver downloads NV */
8288 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8289 msleep(1000);
8290 }
8291 if (max_retries >= 5) {
8292 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308293#ifdef WLAN_OPEN_SOURCE
8294 wake_lock_destroy(&wlan_wake_lock);
8295#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008296 return -ENODEV;
8297 }
8298#endif
8299
Jeff Johnson295189b2012-06-20 16:38:30 -07008300 dev = wcnss_wlan_get_device();
8301#endif // ANI_BUS_TYPE_PLATFORM
8302
8303
8304 do {
8305 if (NULL == dev) {
8306 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8307 ret_status = -1;
8308 break;
8309 }
8310
8311#ifdef MEMORY_DEBUG
8312 vos_mem_init();
8313#endif
8314
8315#ifdef TIMER_MANAGER
8316 vos_timer_manager_init();
8317#endif
8318
8319 /* Preopen VOSS so that it is ready to start at least SAL */
8320 status = vos_preOpen(&pVosContext);
8321
8322 if (!VOS_IS_STATUS_SUCCESS(status))
8323 {
8324 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8325 ret_status = -1;
8326 break;
8327 }
8328
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008329#ifndef MODULE
8330 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8331 */
8332 hdd_set_conparam((v_UINT_t)con_mode);
8333#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008334
8335 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008336 if (hdd_wlan_startup(dev))
8337 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008338 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008339 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008340 vos_preClose( &pVosContext );
8341 ret_status = -1;
8342 break;
8343 }
8344
8345 /* Cancel the vote for XO Core ON
8346 * This is done here for safety purposes in case we re-initialize without turning
8347 * it OFF in any error scenario.
8348 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008349 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008350 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008351 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008352 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8353 {
8354 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8355 " Power consumed will be high\n");
8356 }
8357 } while (0);
8358
8359 if (0 != ret_status)
8360 {
8361 //Assert Deep sleep signal now to put Libra HW in lowest power state
8362 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8363 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8364
8365 //Vote off any PMIC voltage supplies
8366 vos_chipPowerDown(NULL, NULL, NULL);
8367#ifdef TIMER_MANAGER
8368 vos_timer_exit();
8369#endif
8370#ifdef MEMORY_DEBUG
8371 vos_mem_exit();
8372#endif
8373
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008374#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008375 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008376#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008377 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8378 }
8379 else
8380 {
8381 //Send WLAN UP indication to Nlink Service
8382 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8383
8384 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008385 }
8386
8387 EXIT();
8388
8389 return ret_status;
8390}
8391
Jeff Johnson32d95a32012-09-10 13:15:23 -07008392/**---------------------------------------------------------------------------
8393
8394 \brief hdd_module_init() - Init Function
8395
8396 This is the driver entry point (invoked when module is loaded using insmod)
8397
8398 \param - None
8399
8400 \return - 0 for success, non zero for failure
8401
8402 --------------------------------------------------------------------------*/
8403#ifdef MODULE
8404static int __init hdd_module_init ( void)
8405{
8406 return hdd_driver_init();
8407}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008408#else /* #ifdef MODULE */
8409static int __init hdd_module_init ( void)
8410{
8411 /* Driver initialization is delayed to fwpath_changed_handler */
8412 return 0;
8413}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008414#endif /* #ifdef MODULE */
8415
Jeff Johnson295189b2012-06-20 16:38:30 -07008416
8417/**---------------------------------------------------------------------------
8418
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008419 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008420
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008421 This is the driver exit point (invoked when module is unloaded using rmmod
8422 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008423
8424 \param - None
8425
8426 \return - None
8427
8428 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008429static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008430{
8431 hdd_context_t *pHddCtx = NULL;
8432 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008433 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008434
8435 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8436
8437 //Get the global vos context
8438 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8439
8440 if(!pVosContext)
8441 {
8442 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8443 goto done;
8444 }
8445
8446 //Get the HDD context.
8447 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8448
8449 if(!pHddCtx)
8450 {
8451 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8452 }
8453 else
8454 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008455 while(isWDresetInProgress()) {
8456 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8457 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008458 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008459
8460 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8461 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8462 "%s:SSR never completed, fatal error", __func__);
8463 VOS_BUG(0);
8464 }
8465 }
8466
Jeff Johnson295189b2012-06-20 16:38:30 -07008467
8468 pHddCtx->isLoadUnloadInProgress = TRUE;
8469 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8470
8471 //Do all the cleanup before deregistering the driver
8472 hdd_wlan_exit(pHddCtx);
8473 }
8474
Jeff Johnson295189b2012-06-20 16:38:30 -07008475 vos_preClose( &pVosContext );
8476
8477#ifdef TIMER_MANAGER
8478 vos_timer_exit();
8479#endif
8480#ifdef MEMORY_DEBUG
8481 vos_mem_exit();
8482#endif
8483
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308484#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8485 vos_wconn_trace_exit();
8486#endif
8487
Jeff Johnson295189b2012-06-20 16:38:30 -07008488done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008489#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008490 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008491#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008492 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8493}
8494
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008495/**---------------------------------------------------------------------------
8496
8497 \brief hdd_module_exit() - Exit function
8498
8499 This is the driver exit point (invoked when module is unloaded using rmmod)
8500
8501 \param - None
8502
8503 \return - None
8504
8505 --------------------------------------------------------------------------*/
8506static void __exit hdd_module_exit(void)
8507{
8508 hdd_driver_exit();
8509}
8510
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008511#ifdef MODULE
8512static int fwpath_changed_handler(const char *kmessage,
8513 struct kernel_param *kp)
8514{
Jeff Johnson76052702013-04-16 13:55:05 -07008515 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008516}
8517
8518static int con_mode_handler(const char *kmessage,
8519 struct kernel_param *kp)
8520{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008521 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008522}
8523#else /* #ifdef MODULE */
8524/**---------------------------------------------------------------------------
8525
Jeff Johnson76052702013-04-16 13:55:05 -07008526 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008527
Jeff Johnson76052702013-04-16 13:55:05 -07008528 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008529 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008530 - invoked when module parameter fwpath is modified from userspace to signal
8531 initializing the WLAN driver or when con_mode is modified from userspace
8532 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008533
8534 \return - 0 for success, non zero for failure
8535
8536 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008537static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008538{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008539 int ret_status;
8540
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008541 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008542 ret_status = hdd_driver_init();
8543 wlan_hdd_inited = ret_status ? 0 : 1;
8544 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008545 }
8546
8547 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008548
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008549 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008550
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008551 ret_status = hdd_driver_init();
8552 wlan_hdd_inited = ret_status ? 0 : 1;
8553 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008554}
8555
Jeff Johnson295189b2012-06-20 16:38:30 -07008556/**---------------------------------------------------------------------------
8557
Jeff Johnson76052702013-04-16 13:55:05 -07008558 \brief fwpath_changed_handler() - Handler Function
8559
8560 Handle changes to the fwpath parameter
8561
8562 \return - 0 for success, non zero for failure
8563
8564 --------------------------------------------------------------------------*/
8565static int fwpath_changed_handler(const char *kmessage,
8566 struct kernel_param *kp)
8567{
8568 int ret;
8569
8570 ret = param_set_copystring(kmessage, kp);
8571 if (0 == ret)
8572 ret = kickstart_driver();
8573 return ret;
8574}
8575
8576/**---------------------------------------------------------------------------
8577
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008578 \brief con_mode_handler() -
8579
8580 Handler function for module param con_mode when it is changed by userspace
8581 Dynamically linked - do nothing
8582 Statically linked - exit and init driver, as in rmmod and insmod
8583
Jeff Johnson76052702013-04-16 13:55:05 -07008584 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008585
Jeff Johnson76052702013-04-16 13:55:05 -07008586 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008587
8588 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008589static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008590{
Jeff Johnson76052702013-04-16 13:55:05 -07008591 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008592
Jeff Johnson76052702013-04-16 13:55:05 -07008593 ret = param_set_int(kmessage, kp);
8594 if (0 == ret)
8595 ret = kickstart_driver();
8596 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008597}
8598#endif /* #ifdef MODULE */
8599
8600/**---------------------------------------------------------------------------
8601
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 \brief hdd_get_conparam() -
8603
8604 This is the driver exit point (invoked when module is unloaded using rmmod)
8605
8606 \param - None
8607
8608 \return - tVOS_CON_MODE
8609
8610 --------------------------------------------------------------------------*/
8611tVOS_CON_MODE hdd_get_conparam ( void )
8612{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008613#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008614 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008615#else
8616 return (tVOS_CON_MODE)curr_con_mode;
8617#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008618}
8619void hdd_set_conparam ( v_UINT_t newParam )
8620{
8621 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008622#ifndef MODULE
8623 curr_con_mode = con_mode;
8624#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008625}
8626/**---------------------------------------------------------------------------
8627
8628 \brief hdd_softap_sta_deauth() - function
8629
8630 This to take counter measure to handle deauth req from HDD
8631
8632 \param - pAdapter - Pointer to the HDD
8633
8634 \param - enable - boolean value
8635
8636 \return - None
8637
8638 --------------------------------------------------------------------------*/
8639
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008640VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008641{
Jeff Johnson295189b2012-06-20 16:38:30 -07008642 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008643 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008644
8645 ENTER();
8646
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008647 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8648 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008649
8650 //Ignore request to deauth bcmc station
8651 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008652 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008653
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008654 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008655
8656 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008657 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008658}
8659
8660/**---------------------------------------------------------------------------
8661
8662 \brief hdd_softap_sta_disassoc() - function
8663
8664 This to take counter measure to handle deauth req from HDD
8665
8666 \param - pAdapter - Pointer to the HDD
8667
8668 \param - enable - boolean value
8669
8670 \return - None
8671
8672 --------------------------------------------------------------------------*/
8673
8674void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8675{
8676 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8677
8678 ENTER();
8679
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308680 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008681
8682 //Ignore request to disassoc bcmc station
8683 if( pDestMacAddress[0] & 0x1 )
8684 return;
8685
8686 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8687}
8688
8689void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8690{
8691 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8692
8693 ENTER();
8694
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308695 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008696
8697 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8698}
8699
Jeff Johnson295189b2012-06-20 16:38:30 -07008700/**---------------------------------------------------------------------------
8701 *
8702 * \brief hdd_get__concurrency_mode() -
8703 *
8704 *
8705 * \param - None
8706 *
8707 * \return - CONCURRENCY MODE
8708 *
8709 * --------------------------------------------------------------------------*/
8710tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8711{
8712 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8713 hdd_context_t *pHddCtx;
8714
8715 if (NULL != pVosContext)
8716 {
8717 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8718 if (NULL != pHddCtx)
8719 {
8720 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8721 }
8722 }
8723
8724 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008725 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008726 return VOS_STA;
8727}
8728
8729/* Decide whether to allow/not the apps power collapse.
8730 * Allow apps power collapse if we are in connected state.
8731 * if not, allow only if we are in IMPS */
8732v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8733{
8734 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008735 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008736 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008737 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8738 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8739 hdd_adapter_t *pAdapter = NULL;
8740 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008741 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008742
Jeff Johnson295189b2012-06-20 16:38:30 -07008743 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8744 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008745
Yathish9f22e662012-12-10 14:21:35 -08008746 concurrent_state = hdd_get_concurrency_mode();
8747
8748#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8749 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8750 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8751 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8752 return TRUE;
8753#endif
8754
Jeff Johnson295189b2012-06-20 16:38:30 -07008755 /*loop through all adapters. TBD fix for Concurrency */
8756 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8757 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8758 {
8759 pAdapter = pAdapterNode->pAdapter;
8760 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8761 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8762 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008763 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008764 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008765 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008766 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8767 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008768 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008769 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008770 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8771 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008772 return FALSE;
8773 }
8774 }
8775 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8776 pAdapterNode = pNext;
8777 }
8778 return TRUE;
8779}
8780
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008781/* Decides whether to send suspend notification to Riva
8782 * if any adapter is in BMPS; then it is required */
8783v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8784{
8785 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8786 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8787
8788 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8789 {
8790 return TRUE;
8791 }
8792 return FALSE;
8793}
8794
Jeff Johnson295189b2012-06-20 16:38:30 -07008795void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8796{
8797 switch(mode)
8798 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008799 case VOS_STA_MODE:
8800 case VOS_P2P_CLIENT_MODE:
8801 case VOS_P2P_GO_MODE:
8802 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008803 pHddCtx->concurrency_mode |= (1 << mode);
8804 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008805 break;
8806 default:
8807 break;
8808
8809 }
8810 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8811 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8812}
8813
8814
8815void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8816{
8817 switch(mode)
8818 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008819 case VOS_STA_MODE:
8820 case VOS_P2P_CLIENT_MODE:
8821 case VOS_P2P_GO_MODE:
8822 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008823 pHddCtx->no_of_sessions[mode]--;
8824 if (!(pHddCtx->no_of_sessions[mode]))
8825 pHddCtx->concurrency_mode &= (~(1 << mode));
8826 break;
8827 default:
8828 break;
8829 }
8830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8831 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8832}
8833
Jeff Johnsone7245742012-09-05 17:12:55 -07008834/**---------------------------------------------------------------------------
8835 *
8836 * \brief wlan_hdd_restart_init
8837 *
8838 * This function initalizes restart timer/flag. An internal function.
8839 *
8840 * \param - pHddCtx
8841 *
8842 * \return - None
8843 *
8844 * --------------------------------------------------------------------------*/
8845
8846static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8847{
8848 /* Initialize */
8849 pHddCtx->hdd_restart_retries = 0;
8850 atomic_set(&pHddCtx->isRestartInProgress, 0);
8851 vos_timer_init(&pHddCtx->hdd_restart_timer,
8852 VOS_TIMER_TYPE_SW,
8853 wlan_hdd_restart_timer_cb,
8854 pHddCtx);
8855}
8856/**---------------------------------------------------------------------------
8857 *
8858 * \brief wlan_hdd_restart_deinit
8859 *
8860 * This function cleans up the resources used. An internal function.
8861 *
8862 * \param - pHddCtx
8863 *
8864 * \return - None
8865 *
8866 * --------------------------------------------------------------------------*/
8867
8868static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8869{
8870
8871 VOS_STATUS vos_status;
8872 /* Block any further calls */
8873 atomic_set(&pHddCtx->isRestartInProgress, 1);
8874 /* Cleanup */
8875 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8876 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008877 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008878 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8879 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008880 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008881
8882}
8883
8884/**---------------------------------------------------------------------------
8885 *
8886 * \brief wlan_hdd_framework_restart
8887 *
8888 * This function uses a cfg80211 API to start a framework initiated WLAN
8889 * driver module unload/load.
8890 *
8891 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8892 *
8893 *
8894 * \param - pHddCtx
8895 *
8896 * \return - VOS_STATUS_SUCCESS: Success
8897 * VOS_STATUS_E_EMPTY: Adapter is Empty
8898 * VOS_STATUS_E_NOMEM: No memory
8899
8900 * --------------------------------------------------------------------------*/
8901
8902static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8903{
8904 VOS_STATUS status = VOS_STATUS_SUCCESS;
8905 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008906 int len = (sizeof (struct ieee80211_mgmt));
8907 struct ieee80211_mgmt *mgmt = NULL;
8908
8909 /* Prepare the DEAUTH managment frame with reason code */
8910 mgmt = kzalloc(len, GFP_KERNEL);
8911 if(mgmt == NULL)
8912 {
8913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8914 "%s: memory allocation failed (%d bytes)", __func__, len);
8915 return VOS_STATUS_E_NOMEM;
8916 }
8917 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008918
8919 /* Iterate over all adapters/devices */
8920 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8921 do
8922 {
8923 if( (status == VOS_STATUS_SUCCESS) &&
8924 pAdapterNode &&
8925 pAdapterNode->pAdapter)
8926 {
8927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8928 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8929 pAdapterNode->pAdapter->dev->name,
8930 pAdapterNode->pAdapter->device_mode,
8931 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008932 /*
8933 * CFG80211 event to restart the driver
8934 *
8935 * 'cfg80211_send_unprot_deauth' sends a
8936 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8937 * of SME(Linux Kernel) state machine.
8938 *
8939 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8940 * the driver.
8941 *
8942 */
8943
8944 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008945 }
8946 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8947 pAdapterNode = pNext;
8948 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8949
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008950
8951 /* Free the allocated management frame */
8952 kfree(mgmt);
8953
Jeff Johnsone7245742012-09-05 17:12:55 -07008954 /* Retry until we unload or reach max count */
8955 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8956 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8957
8958 return status;
8959
8960}
8961/**---------------------------------------------------------------------------
8962 *
8963 * \brief wlan_hdd_restart_timer_cb
8964 *
8965 * Restart timer callback. An internal function.
8966 *
8967 * \param - User data:
8968 *
8969 * \return - None
8970 *
8971 * --------------------------------------------------------------------------*/
8972
8973void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8974{
8975 hdd_context_t *pHddCtx = usrDataForCallback;
8976 wlan_hdd_framework_restart(pHddCtx);
8977 return;
8978
8979}
8980
8981
8982/**---------------------------------------------------------------------------
8983 *
8984 * \brief wlan_hdd_restart_driver
8985 *
8986 * This function sends an event to supplicant to restart the WLAN driver.
8987 *
8988 * This function is called from vos_wlanRestart.
8989 *
8990 * \param - pHddCtx
8991 *
8992 * \return - VOS_STATUS_SUCCESS: Success
8993 * VOS_STATUS_E_EMPTY: Adapter is Empty
8994 * VOS_STATUS_E_ALREADY: Request already in progress
8995
8996 * --------------------------------------------------------------------------*/
8997VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8998{
8999 VOS_STATUS status = VOS_STATUS_SUCCESS;
9000
9001 /* A tight check to make sure reentrancy */
9002 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9003 {
9004 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9005 "%s: WLAN restart is already in progress", __func__);
9006
9007 return VOS_STATUS_E_ALREADY;
9008 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009009 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009010#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009011 wcnss_reset_intr();
9012#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009013
Jeff Johnsone7245742012-09-05 17:12:55 -07009014 return status;
9015}
9016
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009017/*
9018 * API to find if there is any STA or P2P-Client is connected
9019 */
9020VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9021{
9022 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9023}
Jeff Johnsone7245742012-09-05 17:12:55 -07009024
Jeff Johnson295189b2012-06-20 16:38:30 -07009025//Register the module init/exit functions
9026module_init(hdd_module_init);
9027module_exit(hdd_module_exit);
9028
9029MODULE_LICENSE("Dual BSD/GPL");
9030MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9031MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9032
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009033module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9034 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009035
Jeff Johnson76052702013-04-16 13:55:05 -07009036module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009037 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);